일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- uitableview
- ribs
- Xcode
- RxCocoa
- UICollectionView
- swiftUI
- clean architecture
- Observable
- Clean Code
- collectionview
- UITextView
- ios
- Refactoring
- Human interface guide
- 리팩토링
- swift documentation
- combine
- rxswift
- SWIFT
- HIG
- map
- Protocol
- MVVM
- uiscrollview
- 애니메이션
- 리펙토링
- tableView
- 클린 코드
- 스위프트
- 리펙터링
- Today
- Total
목록클린 코드 (17)
김종권의 iOS 앱 개발 알아가기
클린한 클래스 작성하는 방법 * 아래에서 해당 개념 설명 예정 SRP 준수: 클래스의 변경 이유는 한가지가 되도록 설계 Cohesion 준수: 인스턴스 변수를 최소화 클래스는 작게 만들 것 함수에서의 클린 코드 내용과 같이 클래스 역시도 작아야 가독성, 유지보수에 이점이 있는 코드 함수에서는 내용의 길이를 행의 수 20줄도 긴 수치라고 했었지만, 클래스는 맡은 책임의 개수를 보고 판단 클래스의 책임의 개수 판단 메소드의 개수는 5개 이하가 적정 클래스 이름은 해당 클래스 책임을 기술하는 최소의 범위로 작성 (Manaer, Processor가 붙으면 해당 클래스에서 여러 책임을 떠안겼다는 증거) ex) 책임이 많은 클래스 WRONG - 메소드의 개수는 5개 이지만, SuperDashboard이름에서 Sup..
Unit Test 코드가 중요한 이유 테스트 케이스가 있으면, 실제 코드를 변경하는 것이 두렵지 않은 장점이 존재 유연성, 유지보수성, 재사용성을 제공 테스트 케이스가 있으면, 실제 코드를 변경할 때 테스트 케이스를 사용하여 수정한 코드가 잘 돌아가는지 테스트할 수 있기 때문에 결함율이 낮아지는 효과 (= 유연성과 유지보수성) 테스트 케이스를 작성해 놓으면 해당 테스트 케이스는 계속 사용할 수 있으므로 재사용성 제공 아키텍처가 아무리 유연하고 설계를 아무리 잘 나누었더라도, 테스트 케이스가 없다면 변경에 주저할 수 밖에 없는 상황이 발생 쌓인 테스트 케이스, 즉 테스트 슈트는 설계와 아키텍처를 변경하기 쉬워지므로, 이런 것들을 최대한 깨끗하게 보존하는 열쇠 TDD의 개념 Test Driven Develo..
소프트웨어의 경계 모든 소프트웨어를 직접 개발하는 경우는 드물고, 프레임워크를 이용하여 작성하는데 이때 외부 코드를 작성하려는 코드에 깔끔하게 통합이 필수 소프트웨어의 경계를 깔끔하게 처리하여 깔끔하게 통합 소프트웨어의 경계가 무너지기 쉬운 경우 인터페이스 제공자 vs 인터페이스 사용자 제공자: 적용성을 최대한 높이면 더 많은 고객이 구매하니까, 제네릭하게 작성 사용자: 자신의 요구에 집중하는 인터페이스를 원하는 상황 소프트웨어의 경계 모듈 예시 MyArray 모듈 - 제공자 protocol MyArray { func get(key: String) -> Any } class MyArrayImpl: MyArray { ... var datas = [String: Any]() func get(key: Stri..
오류 코드보다 예외를 지향 예외처리는 논리가 들어간 로직부분과 예외를 처리하는 부분을 나누어서 코드가 섞이지 않게되어 복잡해지지 않게되는 장점이 존재 오류 코드는 테스트가 힘들지만, 예외를 사용하면 throw에 관한 리턴값을 확인할 수 있어서 TDD에도 용이 WRONG class DeviceController { func sendShutDown() -> Void { if handle != DevcieHandle.INVALID { if record.getStatus() != DEVICE_SUSPENDED { pauseDevice(handle) clearDeviceWorkQueue(handle) closeDevice(handle) } else { Log.error("Device suspended. Unabl..
Interface를 사용해야 하는 이유 Interface는 swift에서 protocol을 의미 추상화 - 외부에서 구현체의 변수에 의존하지 않도록하기 위함 인터페이스는 자료 구조를 명백하게 표현 WRONG ex) Interface가 아닌 경우 - 구현을 외부에 노출 외부에서 구현체를 알아야하는지? 외부에서는 직교 좌표계인지, 극 좌표계인지 알 필요없이 값만 필요한 상황이므로 불필요한 정보를 외부에 노출하여, 외부에서 데이터를 사용할 때 불필요한 고민을 주는 상황 class Point { var x: CGFloat var y: CGFloat init(x: CGFloat, y: CGFloat) { self.x = x self.y = y } } RIGHT ex) Interface인 경우 - 구현을 외부에 감..
되로록이면 주석을 지양 잘 달린 주석은 그 어떤 정보보다 유용하지만, 프로그래밍 언어 자체의 표현력이 풍부하다면 주석이 거의 필요하지 않을 것이므로, 주석이 필요 없도록 프로그래밍의 표현력에 집중 코드는 분리되어 점점 변하지만 주석을 직접 수정해주지 않으면 남아있는 경우가 존재 주석은 나쁜 코드를 보완하지 못하므로, "모듈의 이해를 위해서 주석을 달아야지" 보다는 "코드를 정리해야지"의 관점이 필요 WRONG - 나쁜 코드를 보완하려는 목적으로 주석이 사용되었지만, 나쁜 코드를 정리하는 것이 훨씬 중요 // 직원에게 복지 혜택을 받을 자격이 있는지 검사 if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) { ... } RIGHT - 나쁜 코드를 정리하..
짧은 이름보다는 서술적인 이름을 선택 함수를 구현할 때 항상 함수의 이름을 확인하면서, 함수의 이름에 부합하는 작업만 포함하고 있는지 확인할 것 길지라도 서술적인 이름이 지향 함수가 하는 일을 좀 더 잘 표현 좋은코드는 코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행하도록 짜는 코드이므로 서술적인 코드가 짐작하기가 용이 ex) SetupTeardownIncluder, isTestable(), includeSetupAndTeardownPages() 모듈 내에서의 일관성 모듈 내에서함수 이름은 같은 문구, 명사, 동사를 사용 class IncludeModule { func includeSetupAndTeardownPages() {} func includeSetupPages() {} func inclu..
의도를 명확히 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 더 많은 장점이 존재 의도가 명확하게 이름을 지을 것 (주석이 필요하다면 의도를 명확히 드러내지 못한 것) 존재 이유는? 수행 기능은? 사용 방법은? WRONG var d: Int // 경과 시간 (단위: 날짜) RIGHT var elapsedTimeInDays: Int var daysSinceCreation: Int var daysSinceModification: Int var fileAgeInDays: Int 잘못된 정보를 지양 여러 계정 그룹을 묶을 때 실제 List가 아니면 accountList라 하지 않는것을 주의 실제 컨테이너가 List인 경우에도 컨터이너 유형을 이름에 넣지 않는 것이 바람직 WRONG var ..