Refactoring (리펙토링)
[Refactoring] 8-5 데이터 조작화 (값을 참조로 바꾸기)
jake-kim
2023. 5. 22. 23:46
값을 참조로 바꾸기 개념
- 데이터를 공유해야하는 상황에서는 모델을 참조 타입으로 변경
- 데이터를 공유해야할때, 만약 값 타입을 사용하고 있다면 그 데이터를 변경하면 그 데이터의 모든 복제본을 찾아서 빠짐없이 갱신해주는 번거로움이 존재
- 갱신해주다가 만약 하나라도 놓치면 데이터의 일관성이 깨져버리는 현상이 발생

- 값을 참조로 바꾸게 되면 *엔티티(Entity) 하나당 객체도 단 하나만 존재하며, 이런 객체들을 한데 모아 놓고 클라이언트 코드(사용하는 쪽의 코드)들이 접근을 관리해주는 일종의 저장소가 필요
- 엔터티(Entity): 식별 가능한 개체
- ex) 고객이라는 Entity에는 이름, 나이, 주소와 같은 Attribute를 갖음
값을 참조로 바꾸기 리펙토링 해보기
ex) Order 모델 안에 Customer가 있는 상태
- value 타입을 사용하고 있기 때문에 order1의 updateCustomerDate()를 통해 Customer의 date를 변경했을때 order2, order3에도 일일이 다 반영해야하는 상황
struct Customer {
private let id: String
private var date: Date = .init()
init(id: String) {
self.id = id
}
func getID() -> String {
id
}
mutating func updateCustomerDate() {
date = .init()
}
}
struct Order {
private let number: Int
private var customer: Customer
init(number: Int, customerID: String) {
self.number = number
self.customer = Customer(id: customerID)
}
func getCustomer() -> Customer {
customer
}
mutating func updateCustomerDate() {
customer.updateCustomerDate()
}
}
let customerID = "123"
var order1 = Order(number: 0, customerID: customerID)
let order2 = Order(number: 2, customerID: customerID)
let order3 = Order(number: 4, customerID: customerID)
order1.updateCustomerDate()
- 리펙토링
- 1. 같은 부류에 속하는 객체들을 보관할 저장소 생성
- 2. 참조타입으로 변경
- 모델을 참조 타입 (class)로 변경
class RefactorCustomer {
private let id: String
private var date: Date = .init()
init(id: String) {
self.id = id
}
func updateCustomerDate() {
date = .init()
}
}
- 프로토콜 지향 + 저장소를 만들기 위해 프로토콜 정의
protocol Repository {
func registerCustomer(id: String)
func findCustomer(id: String) -> RefactorCustomer?
}
- 프로토콜을 준수하는 저장소를 구현하여 사용
class RepositoryImpl: Repository {
typealias ID = String
var customer = [ID: RefactorCustomer]()
func registerCustomer(id: String) {
customer[id] = RefactorCustomer(id: id)
}
func findCustomer(id: String) -> RefactorCustomer? {
customer[id]
}
}
- 사용하는 쪽(클라이언트 코드)에서는 위 저장소를 통해서 접근하여 사용
값을 참조로 변경할 때의 주의할점
- 같은 부류에 속하는 객체들을 모아놓기 위해서 저장소를 만들었는데, 이 저장소는 전역 저장소로 관리될 수 있기 때문에 웬만하면 DI(Dependency Injection)으로 저장소를 주입해주도록 사용할 것
참고) 반대 리펙토링 - 참조를 값으로 바꾸기
* 참고
- Refactoring (Martin Flowler)