Refactoring (리펙토링)
[Refactoring] 11-4 상속 리펙토링 (Wrapper 만들기)
jake-kim
2023. 7. 28. 22:16
상속 관계를 제거하고 Wrapper 만들기
- 상속의 단점 (이전 포스팅 글에서 알아본 내용 복습)
- 단점1) 수퍼클래스와 서브클래스간의 결합도가 증가하여 부모를 수정하면 자식들의 기능을 헤칠 수 있음
- 단점2) 사람 객체의 동작이 나이대와 소득 수준으로 나뉜다면, 서브클래스를 부자와 서민으로 나눌 것인데 이렇게 된다면 각 서브클래스에서 하나의 인스턴스로 두 기능 모두 사용이 불가능한 상태
- 상속을 제거하려는 목적이 있고 새로운 기능이 별로 추가되지 않을 때 wrapper 모델을 만들고 여기에 추가 기능 확장을 하는 방식
ex) Person 이라는 모델이 있고 여기에 사람에 대한 정보가 있을 때, User라는 모델을 만들고 싶은 경우?
struct Person {
let name: String
let age: Int
var isNameUnique: Bool {
Bool.random()
}
func old(than otherAge: Int) -> Bool {
age < otherAge
}
}
- Person을 property로 가지고 있는 User 모델을 생성
- User모델에는 새로운 id 프로퍼티와 getPassword() 메소드가 존재
struct User {
let id = UUID().uuidString
let person: Person
func getPassword() -> String {
"\(id) \(person.name)"
}
}
- 사용하는 쪽에서는 Person이 wrapping 되었으므로 person 프로퍼티나 기능을 사용하려면 .person으로 접근하는 번거로움이 존재
let user = User(person: .init(name: "jake", age: 20))
let isUnique = user.person.isNameUnique
let name = user.person.name
- 핵심 - extension으로 인터페이스 뚫어주기
- User에 extension을 이용하여 인터페이스만 뚫어지면 쉽게 접근이 가능
extension User {
init(name: String, age: Int) {
self.person = .init(name: name, age: age)
}
var isNameUnique: Bool {
person.isNameUnique
}
var name: String {
person.name
}
}
사용하는쪽)
let user2 = User(name: "jake", age: 20)
let isUnique2 = user2.person
let name2 = user2.name
(extension으로 인터페이스 뚫기 전의 코드)
- 불필요하게 person 프로퍼티를 거쳐가는 방식이므로 extension으로 인터페이스를 뚫어주는게 핵심
let user1 = User(person: .init(name: "jake", age: 20))
let isUnique = user1.person.isNameUnique
let name = user1.person.name
* 전체 코드: https://github.com/JK0369/ExRefactor11_4/tree/main/ExRefactor12_1