일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- SWIFT
- 리펙토링
- 리펙터링
- uiscrollview
- clean architecture
- 애니메이션
- 리팩토링
- Human interface guide
- Protocol
- map
- 클린 코드
- ios
- RxCocoa
- uitableview
- rxswift
- collectionview
- swift documentation
- Xcode
- UITextView
- Observable
- ribs
- combine
- Refactoring
- 스위프트
- UICollectionView
- HIG
- swiftUI
- tableView
- MVVM
- Clean Code
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] Clean Code(클린 코드) - 12. 냄새와 휴리스틱 (3) (이름, 테스트) 본문
[iOS - swift] Clean Code(클린 코드) - 12. 냄새와 휴리스틱 (3) (이름, 테스트)
jake-kim 2021. 11. 29. 23:58* 냄새와 휴리스틱: 파틴 파울러의 "Refactoring"에서 "코드 냄새"를 표현하여 주의해야하는 코드 사항들에 대해 나열한 것에 더하여 저자 로버트 C.마틴의 생각을 더한 것
이름
- 서술적인 이름을 사용할 것
- 소프트웨어가 진화할 경우 의미도 변하므로 선택한 이름이 적합한지, 성급하지 않고 신중하게 고를 것
- 로버트 C마틴에 의하면, 소프트웨어 가독성의 90%는 이름이 결정
- 주석을 통해 추가 설명을 하려고 하기전에, 먼저 서술적인 이름으로 코드를 구성하는 방향으로 구현하면 다 읽지 않아도 유추하기가 쉬워져서, 코드 생산성에도 긍정적인 영향을 부여
RIGHT
- 서술적인 이름으로 인해 함수의 이름만 보고도 내용을 예측할수 있는 형태
private let ballCountToStrike = 10
private isStrike(frame: Int) -> Bool {
return rolls[frmae] == ballCountToStrike
}
- 적절한 추상화 수준에서 이름을 선택할 것
- 추상화 수준이 너무 낮은 변수 이름은 확장 가능성을 제한하므로 발견하면 추상화 수준을 높게 바꾸는 것으로 지향
WRONG
- phoneNumber라는 추상화 수준이 낮은 변수 이름을 사용하여, 전화번호가 아닌 포트 번호로 통신하는 경우 확장성에 제한되는 코드
protocol {
func dial(phoneNumber: String) -> Bool
func disconnect() -> Bool
func send(message: String) -> Bool
func recv() -> String
func getConnectedPhoneNumber() -> String
}
RIGHT
- phoneNumber 이름을 변경하여 연결 대상의 이름을 전화번호로 제한하지 않고, 다른 연결 방식에도 확장 가능하도록 수정
protocol {
func connect(connectionLocator: String) -> Bool
func disconnect() -> Bool
func send(message: String) -> Bool
func recv() -> String
func getConnectedLocator() -> String
}
- 함수, 변수 이름이 길지라도 서술적이고 명확한 이름이 된다면 변경할 것
WRONG
- doRename이라는 이름은 명확하지 않고 아주 광범위하고 모호한 형태
private func doRename() -> String {
if refactorReferences {
renameReferences()
}
renamePage()
pathToRename.removeNameFromEnd()
pathToRename.addNameToEnd(newName)
return PathParser.render(pathToRename)
}
RIGHT
- 함수 이름을 doRename에서 renamePageAndOptionallyReferences로 변경 (길더라도 서술적이고 명확한 형태)
private func renamePageAndOptionallyReferences() -> String {
if refactorReferences {
renameReferences()
}
renamePage()
pathToRename.removeNameFromEnd()
pathToRename.addNameToEnd(newName)
return PathParser.render(pathToRename)
}
- 코드 rows의 길이가 짧은 함수에는, 함수 안의 변수들의 이름을 짧게 지어도 괜찮지만, rows길이가 길면 긴 이름을 사용할 것
RIGHT
- rows가 5줄밖에 안되므로, i와 j같은 짧은 변수 이름을 사용해도 무방
private func rollMany(n: Int, pins: Int) {
for i in 0..<n {
g.roll(pins)
}
}
- 함수 블록에서 발생하는 side effect를 함수 이름만 보고도 유추할 수 있도록 함수 이름에 side effect의 내용이 들어가도록 할 것
WRONG
- 함수 블록 내부에서, 단순히oos만 가져오지 않고 값이 없는 경우에는 oos를 생성하는 함수지만, 함수이름에는 단순히 getOos이고 oos를 생성하는 side effect내용을 알 수 없는 상태
func getOos() -> ObjectOutputStream {
if let oos = oos {
return oos
} else {
return ObjetOuputStream(socket.getOutputStream())
}
}
RIGHT
- 함수 이름을 getOos에서 createOrReturnOos로 변경하여, 함수 이름만 봐도 side effect을 알 수 있는 형태
func createOrReturnOos() -> ObjectOutputStream {
if let oos = oos {
return oos
} else {
return ObjetOuputStream(socket.getOutputStream())
}
}
테스트
- 유닛 테스트 코드를 충분히 만들 것
- 대부분의 개발자들이 "이 정도면 충분하지 않을까"라는 척도를 사용하지만, 테스트 케이스는 잠재적으로 깨질만한 부분을 모두 테스트해야 안전한 코드 확립 가능
- 사소한 테스트도 건너뛰지 말고 진행할 것
- 테스트 코드는 단순히 테스트, 변경에 유연한 코드일 뿐만이 아니라, 문서적 가치를 제공하므로 구현에 드는 비용보다 값진 것
- 특정 함수에서 버그가 하나 나왔다면, 다른 버그도 나올 가능성이 높으므로 테스트 코드의 수를 늘릴 것
- 일정이 촉박하면 느린 테스트 케이스를 제일 먼저 건너뛰어야 하므로, 테스트 코드 구현 시 빠르게 돌아가게끔 할것
cf) 테스트 개념: Clean Code(클린 코드) - 8. Unit Test (단위 테스트)
* 참고: Clean Code (로버트 C. 마틴)
'Clean Code (클린 코드)' 카테고리의 다른 글
[iOS - swift] Clean Code(클린 코드) - 12. 냄새와 휴리스틱 (2) (일반) (0) | 2021.11.28 |
---|---|
[iOS - swift] Clean Code(클린 코드) - 12. 냄새와 휴리스틱 (1) (주석, 환경, 함수, 일반) (0) | 2021.11.26 |
[iOS - swift] Clean Code(클린 코드) - 11. 창발성 (4가지의 규칙을 따라서 클린 코드 유지방법) (0) | 2021.11.24 |
[iOS - swift] Clean Code(클린 코드) - 10. 시스템 (Abstract Factory 패턴, DI) (0) | 2021.11.23 |
[iOS - swift] Clean Code(클린 코드) - 9. 클래스 (SRP, Cohesion) (0) | 2021.11.23 |