Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 리펙토링
- UITextView
- 리펙터링
- Refactoring
- Xcode
- MVVM
- clean architecture
- Human interface guide
- ios
- 클린 코드
- 애니메이션
- combine
- uitableview
- RxCocoa
- UICollectionView
- map
- HIG
- SWIFT
- swiftUI
- collectionview
- Protocol
- rxswift
- 리팩토링
- Observable
- tableView
- Clean Code
- ribs
- uiscrollview
- swift documentation
- 스위프트
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] Clean Code(클린 코드) - 3. 함수 (2) 본문
짧은 이름보다는 서술적인 이름을 선택
- 함수를 구현할 때 항상 함수의 이름을 확인하면서, 함수의 이름에 부합하는 작업만 포함하고 있는지 확인할 것
- 길지라도 서술적인 이름이 지향
- 함수가 하는 일을 좀 더 잘 표현
- 좋은코드는 코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행하도록 짜는 코드이므로 서술적인 코드가 짐작하기가 용이
- ex) SetupTeardownIncluder, isTestable(), includeSetupAndTeardownPages()
모듈 내에서의 일관성
- 모듈 내에서함수 이름은 같은 문구, 명사, 동사를 사용
class IncludeModule {
func includeSetupAndTeardownPages() {}
func includeSetupPages() {}
func includeSuiteSetupPage() {}
func includeSetupPage() {}
}
함수의 인수
- 함수에서 이상적인 인수 개수는 0개이므로 최대히 적게 사용하는것이 중요
- 인수가 4개를 사용할땐 특별한 이유가 필요
- 인수는 개념을 이해하기 어렵기 만들기 때문에 지양
- 인수가 생겨나면 본래의 함수 이름과 인수 사이의 추상화 수준이 달라지는 현상이 발생
인수가 있는 함수 | 인수가 없는 함수 |
includeSetupPageInfo(pageContent: PageContent) | includeSetupPageInfo() |
- 인수가 있는 함수에서 코드를 입는 사람은 pageContent 인수를 발견 할때마다 의미를 해석해야한다는 점이 존재
- testable 코드를 구성할 때 인수가 많아지면, 인수에 따른 변수가 여러가지가 더 생기므로 테스트 관점에서 안좋은 코드
인수가 1개인 함수
- 아래 2가지 형태가 아니면 가급적 인수를 사용하지 말것
1) 인수에 질문을 던지는 형태
func isExistsFile(_ fileName: String) -> Bool {}
2) 인수를 뭔가로 변환해 결과를 반환하는 경우
func transformToString(number: Int) -> String {}
- 절대 피해야하는 형태 - 플래그 인수
- 함수로 Boolean값을 넘긴다는 것은 함수 안에서 한꺼번에 여러 가지를 처리한다고 가정하는 것이므로 피해야되는 것을 주의
인수가 2개인 함수
- 인수가 2개인 함수는 인수가 1개인 함수보다 이해하기 어려운 점
인수가 1개인 함수 호출 | 인수가 2개인 함수 호출 |
writeField(name) | writeField(outputStream, name) |
- 인수가 2개로 사용될 수 밖에 없는 아래 케이스를 제외한 것들은 가능한 인수가 1개가 되도록 수정
let p = Point(0, 0)
- 인수 2개 > 1개로 변환 방법: 해당 인수의 클래스에 메소드로 추가
- 인수가 2개인 함수: writeField(outputStream, name)
- 인수가 1개인 함수로 변환: outputStream.writeField(name)
여러개의 인수인 경우, 인수 객체로 변환
- 인수가 3개 이상이 되면 이해하기가 어려워지므로 인수 객체를 만들어서 사용
인수가 4개인 경우 | 인수 객체를 이용한 방법 |
func makeCircle(x: Double, y: Double, radius: Double) -> Circle | func makeCircle(center: Point, radius: Double) -> Circle |
함수에 Side Effect가 있는 경우
- 함수안에서 다른것에 영향을 주는 Side Effect를 최대한 지양해야 하고, 어쩔수 없이 있는 경우에는 함수의 이름에 명시해주는것이 중요
ex) 유저의 패스워드를 찾아서 있다면 session을 초기화해주는 함수
Side Effect가 있는 함수 - checkPassword(userNmae:password:)는 이름만 봤을때 패스워드만 확인하는 것이지만 내부에서 Session.initialize()를 호출하게되어 session을 초기화하는 형태
class UserValidator {
private let cryptographer: Cryptographer
init (cryptographer: Cryptographer) {
self.cryptographer = cryptographer
}
func checkPassword(userName: String, password: String) -> Bool {
let user = UserGateway.findByName(userName)
guard let user = user else { return false }
let codedPhase = user.getPhraseEncodedByPassword()
let phrase = cryptographer.decrypt(codedPhase, password)
if ("Valid Password".contains(phrase)) {
Session.initalize()
return true
}
}
}
> 함수 이름을 변경하여 Side Effect를 예상하도록 변경 "checkPasswordAndInitializeSession"
오류 코드보다 예외 코드를 지향
- 오류 코드보다 try - catch 예외 처리를 사용해야 하는 이유
- 오류를 처리하는 코드가 원래의 코드에서 분리할 수 있기 때문에 더욱 코드가 깔끔해지게 되기 때문
WRONG
- 오류를 처리하는 부분과 원래의 코드가 같이 있어서 읽기 어려운 형태
if deletePage(page) == E_OK {
if registry.deleteReference(page.name) == E_OK {
if configKeys.deleteKey(page.name.makeKey()) == E_OK {
logger.log("page deleted")
} else {
logger.log("configKey not deleted")
}
} else {
logger.log("deleteReference from registry failed")
}
} else {
logger.log("delete failed")
return E_ERROR
}
RIGHT
- 오류를 처리하는 부분과, 원래의 코드가 분리된 형태
try {
deletePage(page)
registry.deleteReference(page.name)
configKeys.deleteKey(page.name.makeKey())
} catch {
logger.log(error)
}
func deletePageAndAllReference(page: Page) throws {
deletePage(page)
registry.deleteReference(page.name)
configKeys.deleteKey(page.name.makeKey())
}
저자인 로버트 C. 마틴이 함수를 짜는 방식
- 작가들의 글짓기와 비슷하게, 처음에는 길고 복잡하게 들여쓰기 단계도 많고 중복도 많고, 인수 목록이 길고 이름도 대충 구현
- 이런 함수들을 처음에 짤때 서투른 코드들에 대해서 unit test를 만드는 것은 빼먹지 않고 진행
- 코드를 다듬고 함수를 만들고 이름을 바꾸는 작업을 진행, 테스트 코드가 통과하는지 계속 확인
* 참고: Clean Code (로버트 C. 마틴)
'Clean Code (클린 코드)' 카테고리의 다른 글
[iOS - swift] Clean Code(클린 코드) - 5. 객체와 자료 구조 (객체지향, 절차지향 장단점) (0) | 2021.11.17 |
---|---|
[iOS - swift] Clean Code(클린 코드) - 4. 주석 (0) | 2021.11.14 |
[iOS - swift] Clean Code(클린 코드) - 3. 함수 (1) (0) | 2021.11.11 |
[iOS - swift] Clean Code(클린 코드) - 2. 의미 있는 이름 (0) | 2021.11.10 |
[iOS - swift] Clean Code(클린 코드) - 1. 클린 코드의 개념 (0) | 2021.11.10 |
Comments