티스토리 뷰
마틴 파울러 - 리팩터링 (2판) 의 9장 내용 중 기억하고 싶은 것 기록 ✏️✏️
9.4 참조를 값으로 바꾸기 (change Reference to Value)
- 참조로 다루는 경우: 내부 객체는 그대로 둔 채 그 객체의 속성산 갱신함.
- 값으로 다루는 경우: 새로운 속성을 담은 객체로 기존 내부 객체를 통째로 대체함
값 객체는 불변이기 때문에 자유롭게 활용하기 쉽다.
불변 데이터 값은 프로그램 외부로 건네줘도 나중에 그 값이 나 몰래 바뀌어서 내부에 영향을 줄까 염려하지 않아도 된다.
값을 복제해 이곳저곳에서 사용하더라도 서로간의 참조를 관리하지 않아도 된다.
그래서 값 객체는 분산 시스템, 동시성 시스템에서 특히 유용하다.
9.5에서 나오지만..
이런 값 객체의 특성 때문에 이번 리팩터링을 적용하면 안되는 상황도 있다.
예컨대 특정 객체를 여러 객체에서 공유하고자 한다면, 그래서 공유 객체의 변경했을 때 이를 관련된 객체 모두에게 알려줘야한다면
공유 객체를 참조로 다뤄야한다.
[ 리팩터링 절차 ]
1. 후보 클래스가 불변이 될 수 있는 지 확인한다.
2. 각각의 세터를 하나씩 제거한다.
3. 값 객체의 필드들을 사용하는 동치성(equaility) 비교 메소드를 만든다.
[ 예시 ]
telephoneNumber를 들고 있는 Person 클래스를 예시로 살펴보자.
1. 가장 먼저 할 일은 전화번호를 불변으로 만들기다.
2. 필드들의 세터들만 제거하면 된다.
세터 제거의 첫 단계로, 세터로 설정하던 두 필드를 생성자에서 입력받아 설정하도록 하고
세터를 호출하는 쪽에서 전화번호를 매번 다시 만들어서 대입하도록 바꿔준다.
3. 이제 전화번호는 불변이 되었고 값 객체로 인정받기 위해 동치성 비교를 통과해야한다.
9.5 값을 참조로 바꾸기 (Change Value to Reference)
주문 목록을 생각해보자. 주문 목록을 읽다보면 같은 고객이 요청한 주문이 여러개 섞여있을 수 있다.
이때 고객을 값으로도, 혹은 참조로도 다룰 수 있다.
값으로 다룬다면 고객데이터가 각 주문에 복사되고, 참조로 다룬다면 여러 주문이 단 하나의 데이터 구조를 참조하게 된다.
고객 데이터를 갱신할 일이 없다면 어느 방식이든 상관없다.
하지만 논리적으로 같은 데이터를 물리적으로 복제해 사용할 때 가장 크게 문제되는 상황은 그 데이터를 갱신해야할 때다.
모든 복제본을 찾아서 빠짐없이 갱신해야하며, 하나라도 놓치면 데이터 일관성이 깨져버린다.
이런 상황이라면 복제된 데이터들을 모두 참조로 바꿔주는 게 좋다.
데이터가 하나면 갱신된 내용이 해당 고객의 주문 모두에 곧바로 반영되기 때문이다.
값을 참조로 바꾸면 entity 하나당 객체도 단 하나만 존재하게 되는데, 그러면 보통 이런 객체들을 한데 모아놓고 클라이언트들의 접근을 관리해주는 일종의 저장소가 필요해진다.
각 entity를 표현하는 객체를 한 번만 만들고, 객체가 필요한 곳에서는 모두 이 저장소로부터 얻어 쓰는 방식이 된다.
[ 리팩터링 절차 ]
1. 같은 부류에 속하는 객체들을 보관할 저장소를 만든다. (이미 있다면 생략)
2. 생성자에서 이 부류의 객체들 중 특정 객체를 정확하게 찾아내는 방법이 있는지 확인한다.
3. 호스트 객체의 생성자들을 수정하여 필요한 객체를 이 저장소에서 찾도록 한다. 하나 수정할 때마다 테스트한다.
[ 예시 ]
주문(Order) 클래스를 예시로 보자.
이 클래스는 생성자에서 주문 데이터(JSON 문서)를 입력받아 필드들을 채운다.
이 과정에서 주문 데이터에 포함된 고객 ID를 사용해 고객(Customer) 객체를 생성한다.
이런 방식으로 생성한 고객 객체는 값이다.
고객 ID가 123인 주문을 다섯 개 생성한다면 독립된 고객 객체가 다섯개 만들어진다.
이 중 하나를 수정하더라도 나머지 네 개에는 반영되지 않는다.
이제 값을 참조로 바꾸는 리팩터링을 시작해보자!
1. 항상 물리적으로 똑같은 고객 객체를 사용하고 싶다면 먼저 이 유일한 객체를 저장해둘 곳이 있어야한다.
저장소 객체 (repository object)를 만든다.
이 저장소는 고객 객체를 ID와 함께 등록할 수 있으며, ID 하나당 오직 하나의 고객 객체만 생성됨을 보장한다.
2. 주문의 생성자에서 올바른 고객 객체를 얻어오는 방법을 찾는다.
이번 예에서는 고객 ID가 입력 데이터로 들어오니까 쉽게 해결할 수 있다.
3. Order 클래스의 생성자을 수정하자. 고객을 이 저장소에서 찾도록 한다.
이제 특정 주문과 관련된 고객 정보를 갱신하면
같은 고객을 공유하는 주문 모두에서 갱신된 고객 데이터를 사용하게 된다.
'책도 읽고' 카테고리의 다른 글
리팩터링 (6) - 객체 통째로 넘기기 / 매개변수 / 예외 (0) | 2021.07.30 |
---|---|
리팩터링 (5) - 조건부 로직을 다형성으로 / 특이 케이스 / Assertion (0) | 2021.07.12 |
리팩터링 (3) - 캡슐화를 위한 리팩토링 기법 (0) | 2021.05.21 |
리팩터링 (2) - 좋은 테스트 습관 (0) | 2021.04.27 |
리팩터링 (1) - 리팩터링하는 이유 / 리팩터링 원칙 (0) | 2021.04.15 |
- Total
- Today
- Yesterday
- METAL
- Dart Factory
- 플러터 싱글톤
- github actions
- Python Type Hint
- Django FCM
- 플러터 얼럿
- Flutter Clipboard
- ipad multitasking
- ribs
- flutter 앱 출시
- flutter build mode
- drf custom error
- Django Firebase Cloud Messaging
- Flutter 로딩
- DRF APIException
- Flutter getter setter
- PencilKit
- flutter deep link
- 장고 URL querystring
- flutter dynamic link
- SerializerMethodField
- cocoapod
- Django Heroku Scheduler
- Flutter Spacer
- Flutter Text Gradient
- Watch App for iOS App vs Watch App
- Sketch 누끼
- 구글 Geocoding API
- 장고 Custom Management Command
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |