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
- UICollectionView
- 리팩토링
- ios
- combine
- 클린 코드
- UITextView
- SWIFT
- tableView
- 리펙터링
- 리펙토링
- Clean Code
- Xcode
- Refactoring
- ribs
- Observable
- RxCocoa
- 애니메이션
- uitableview
- uiscrollview
- Protocol
- 스위프트
- rxswift
- clean architecture
- swift documentation
- Human interface guide
- MVVM
- HIG
- collectionview
- swiftUI
- map
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[Refactoring] 11-2 상속 리펙토링 (enum case 타입 코드를 서브클래스로 바꾸기) 본문
Refactoring (리펙토링)
[Refactoring] 11-2 상속 리펙토링 (enum case 타입 코드를 서브클래스로 바꾸기)
jake-kim 2023. 7. 25. 01:47케이스를 서브클래스로 바꾸기
- 특정 타입에 따라서 기능을 달리해야하는 경우 보통 enum case로 타입을 구분하고 하나의 파일에서 분기를 넣는데, 이렇게되면 하나의 역할에 대해서만 책임 (Single Responsibility Prinsiple, SRP)을 지키지 못하는 코드로 변동
- SRP를 지키지 못하면 type에 대한 특정 동작이 하나의 파일에 섞여나게되어, type에 대한 기능이 수정되어야 할 때 특정 type과 관련없는 코드가 변경될 우려가 존재
- 변경사항에 대해 코드를 수정해야하는 개발자 입장에서는 변경하려는 type 외에도 다른 type들도 고려하게되어 수정하기가 쉽지 않게 유지
- SRP를 지키도록 type으로 하나의 파일에 여러개의 역할에 대해 구분할 때, 서브 클래스로 만들면 유지보수에 용이
리펙토링 실습
- 툴팁 뷰 구현에 있어서, tip 부분이 위에 있는 코드와 아래 있는 코드가 있는데 이를 enum으로 받아서 하나의 뷰 안에서 분기문이 들어가 있는 상태
- 툴팁 뷰 구현 설명은 이 포스팅 글 참고
- 리펙토링이 필요한 부분
- TipView (삼각형 뷰) 부분에 enum타입으로 아래에 tip이 위치할지, 위에 tip이 위치할지 결정하는 분기가 존재
- TipView를 사용하는쪽에서 bottom, top 위치를 필요로 하는데, 이 2가지 기능에 대해 TipView에서 2가지의 책임을 지게 되므로 SRP 위배
private class TipView: UIView {
var tipPoistion = TipPosition.bottom
var bgColor = UIColor.gray
override func draw(_ rect: CGRect) {
backgroundColor = .clear
bgColor.setFill()
tipPoistion == .top ? drawTopTip(rect) : drawBottomTip(rect)
}
private func drawTopTip(_ rect: CGRect) {
let path = UIBezierPath()
path.move(to: CGPoint(x: rect.midX, y: 0))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.close()
path.fill()
}
private func drawBottomTip(_ rect: CGRect) {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: rect.maxX, y: 0))
path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
path.close()
path.fill()
}
}
- 하나의 클래스에서 하나의 책임만을 담당하도록 서브클래싱하여 리펙터링
- TopTipView와 BottomTipView로 나누어서 구현
private class TipView: UIView {
var bgColor = UIColor.gray
override func draw(_ rect: CGRect) {
backgroundColor = .clear
bgColor.setFill()
drawTip(rect)
}
func drawTip(_ rect: CGRect) {
// override point
}
}
private class TopTipView: TipView {
override func drawTip(_ rect: CGRect) {
let path = UIBezierPath()
path.move(to: CGPoint(x: rect.midX, y: 0))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.close()
path.fill()
}
}
private class BottomTipView: TipView {
override func drawTip(_ rect: CGRect) {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: rect.maxX, y: 0))
path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
path.close()
path.fill()
}
}
- 사용하는 쪽
- TopTipView(), BottomTipView() 나누어서 사용
init(title: String?, textColor: UIColor = .white, backgroundColor: UIColor = .gray, tipPoistion: TipPosition = .bottom) {
...
tipView = tipPoistion == .top ? TopTipView() : BottomTipView()
super.init(frame: .zero)
...
}
(리펙토링 전 코드 Github)
* 전체 코드: https://github.com/JK0369/ExRefactor_11_2
* 참고
- Refactoring (Martin Flowler)
'Refactoring (리펙토링)' 카테고리의 다른 글
[Refactoring] 11-4 상속 리펙토링 (Wrapper 만들기) (0) | 2023.07.28 |
---|---|
[Refactoring] 11-3 상속 리펙토링 (서브 클래스를 델리게이트로 바꾸기) (0) | 2023.07.27 |
[Refactoring] 11-1 상속 리펙토링 (메서드 올리기) (0) | 2023.07.15 |
[Refactoring] 10-6 API 리펙토링 (오류 코드를 예외로 바꾸기) (0) | 2023.07.13 |
[Refactoring] 10-5 API 리펙토링 (수정된 값 반환하기) (0) | 2023.07.12 |
Comments