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
- swiftUI
- MVVM
- Protocol
- HIG
- 리펙토링
- rxswift
- SWIFT
- ios
- Xcode
- UITextView
- 클린 코드
- collectionview
- Human interface guide
- UICollectionView
- 리팩토링
- Observable
- 리펙터링
- clean architecture
- Refactoring
- 애니메이션
- 스위프트
- ribs
- swift documentation
- Clean Code
- RxCocoa
- uiscrollview
- combine
- uitableview
- map
- tableView
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[Refactoring] 7-4. 기능 이동 (함수 옮기기, 중첩함수 제거, 모듈성) - 문장을 호출한 곳으로 옮기기 본문
Refactoring (리펙토링)
[Refactoring] 7-4. 기능 이동 (함수 옮기기, 중첩함수 제거, 모듈성) - 문장을 호출한 곳으로 옮기기
jake-kim 2023. 4. 19. 01:07리펙토링 핵심
- 각 방법들을 '왜' 수행해야 하는지 깨닫고 유연하게 적용하기
문장을 호출한 곳으로 옮기기
- 한 함수는 한 가지의 일만 해야하는데 두 가지 이상의 일을 하는 경우, 함수 안의 문장을 밖으로 빼내는 작업
- 함수는 프로그래머가 쌓아 올리는 추상화의 기본 빌딩 블록이지만 추상화의 경계를 항상 올바르게 긋기가 어려움
- 기능 범위가 달라지면 추상화의 경계도 움직이게 되므로 함수 관점에서 응집도가 높고 한 가지 일만 수행해야하는 함수가 둘 이상의 다른 일을 수행하게 될 수 있으므로 이런 부분들을 리펙토링하는것
- 반대 리펙토링: 문장을 함수로 옮기기
문장을 호출한 곳으로 옮기기 리펙토링
ex) photo, person 데이터가 있고, 이것을 렌더링하는 함수가 있는 상태
- getRecentPhotos(_:)에서도 emit(photo:)를 호출하는 상황
- 이때 getRecentPhotos(_:) 메소드에서는 location 정보를 emit(photo:)에서 호출하는 방식과 다르게 commit해야하는 경우 리펙토링?
- emit(photo:) 부분의 location 커밋 부분은 공통적으로 사용하지 않도록 리펙토링 하는 것
- 코드는 깃허브 참고
var recentDate: Date?
private func render(person: Person) {
Storage.commit(message: "이름: \(person.name)")
render(photo: person.photo)
emit(photo: person.photo)
}
private func render(photo: Photo?) {
// render photo...
}
private func emit(photo: Photo?) {
Storage.commit(message: "제목: \(photo?.title)")
Storage.commit(message: "날짜: \(photo?.date)")
Storage.commit(message: "위치: \(photo?.location)")
}
private func getRecentPhotos(_ photos: [Photo]) -> [Photo] {
let recentPhotos = photos
.filter { $0.date?.timeIntervalSince1970 ?? 0 < recentDate?.timeIntervalSince1970 ?? 0 }
recentPhotos
.forEach { photo in
Storage.commit(message: "\(photo) start")
emit(photo: photo)
Storage.commit(message: "\(photo) end")
}
return recentPhotos
}
struct Person {
var name: String?
var photo: Photo?
}
struct Photo {
var title: String?
var date: Date?
var location: String?
}
enum Storage {
static func commit(message: String) {
// commit message ...
}
static func store(value: Any) {
// store value ...
}
}
- emit(photo:)를 호출하는 부분인 render(person:) 사이드 이펙을 막으면서 리펙토링하기 위해서 render(person:) 부분을 수정
// before
private func render(person: Person) {
Storage.commit(message: "이름: \(person.name)")
render(photo: person.photo)
emit(photo: person.photo)
}
// after
private func render(person: Person) {
Storage.commit(message: "이름: \(person.name)")
render(photo: person.photo)
// emit대신 temp()와 emit안에 있던 위치 관련 문장 끌어내기
temp(photo: person.photo)
Storage.commit(message: "위치: \(person.photo?.location)")
}
- getRecentPhotos(_:)에서도 emit 호출 부분을 수정
// before
private func getRecentPhotos(_ photos: [Photo]) -> [Photo] {
let recentPhotos = photos
.filter { $0.date?.timeIntervalSince1970 ?? 0 < recentDate?.timeIntervalSince1970 ?? 0 }
recentPhotos
.forEach { photo in
Storage.commit(message: "\(photo) start")
emit(photo: photo)
Storage.commit(message: "\(photo) end")
}
return recentPhotos
}
// after
private func getRecentPhotos(_ photos: [Photo]) -> [Photo] {
let recentPhotos = photos
.filter { $0.date?.timeIntervalSince1970 ?? 0 < recentDate?.timeIntervalSince1970 ?? 0 }
recentPhotos
.forEach { photo in
Storage.commit(message: "\(photo) start")
// emit(photo:) 대신 temp와 emit안에 있던 위치 관련 문장 끌어내기
temp(photo: photo)
Storage.commit(message: "위치: \(photo.location)")
Storage.commit(message: "\(photo) end")
}
return recentPhotos
}
- emit(photo:)호출하는 부분을 모두 변경하였으므로 emit(photo:)를 지우고, temp(photo:)를 emit(photo:)로 변경한 후, temp(photo:)를 호출하던 부분도 모두 emit(photo:)로 변경하면 완료
// before
private func emit(photo: Photo?) {
temp(photo: photo)
Storage.commit(message: "위치: \(photo?.location)")
}
func temp(photo: Photo?) {
Storage.commit(message: "제목: \(photo?.title)")
Storage.commit(message: "날짜: \(photo?.date)")
}
// after
func emit(photo: Photo?) {
Storage.commit(message: "제목: \(photo?.title)")
Storage.commit(message: "날짜: \(photo?.date)")
}
핵심
- emit(photo:)안의 내용을 변경하고 싶은 경우, temp(photo:)와 같은 간단한 함수를 만든 후 이것을 적용시키며 동시에 테스트까지하면서 코드를 변경할때마다 빌드가 성공되게끔 할 것
- 가끔 빌드가 실패되게끔 변경하다보면 개발자의 실수가 들어가기 때문에 항상 빌드가 성공하게끔 temp(photo:)와 같은 함수를 만들어서 진행할것
* 전체 코드: https://github.com/JK0369/ex_refactoring
* 참고
- Refactoring (Marting Flowler)
'Refactoring (리펙토링)' 카테고리의 다른 글
[Refactoring] 7-6. 기능 이동 (함수 이동, 중첩함수 제거, 모듈성) - 문장 슬라이드 (0) | 2023.04.25 |
---|---|
[Refactoring] 7-5. 기능 이동 (함수 옮기기, 중첩함수 제거, 모듈성) - 인라인 코드를 함수 호출로 바꾸기 (0) | 2023.04.23 |
[Refactoring] 7-3. 기능 이동 (함수 옮기기, 중첩함수 제거, 모듈성) - 문장을 함수로 옮기기 (0) | 2023.04.18 |
[Refactoring] 7-2. 기능 이동 (함수 옮기기, 중첩함수 제거, 모듈성) - 필드 옮기기 (1) | 2023.04.17 |
[Refactoring] 7-1. 기능 이동 (함수 옮기기, 중첩함수 제거, 모듈성) - 함수 옮기기 (0) | 2023.03.26 |
Comments