식별자 없이 담고 있는 값 자체로 같음을 판단하는 불변 객체. 금액, 기간, 주소, 이메일처럼 "어떤 것"이 아니라 "얼마·무엇"을 나타내는 개념에 쓴다. 식별자로 같음을 판단하고 상태가 바뀌는 엔티티(Entity)와 대비된다(도메인 주도 설계 (DDD)).
- 바꿀 수 없으므로, 바꾸려면 새 객체를 만들어 통째로 교체한다
- 같은 값이면 같은 객체로 본다. 언어가 기본으로 참조 비교를 한다면 동치 비교 메서드를 직접 둔다
- 밖으로 건네도 몰래 바뀔 걱정이 없어 동시성·분산 환경에서 특히 다루기 편하다
class Money {
constructor(readonly amount: number, readonly currency: string) {}
minus(n: number) { return new Money(this.amount - n, this.currency) }
equals(o: Money) { return this.amount === o.amount && this.currency === o.currency }
}
product.price = product.price.minus(1000) // 내부 값을 고치지 않고 교체참조로 다뤄야 할 때
여러 객체가 한 대상을 공유하고, 그 대상이 바뀌면 모두가 알아야 한다면 값이 아니라 참조여야 한다. 같은 고객 데이터를 주문마다 복제해 두면 갱신할 때 하나라도 놓치면 일관성이 깨진다. 이럴 때는 저장소에서 같은 인스턴스를 꺼내 쓰게 바꾼다(값을 참조로 바꾸기, Change Value to Reference). 반대로 공유가 필요 없는 내부 객체는 값으로 바꾼다(참조를 값으로 바꾸기, Change Reference to Value).
- 원시값에 의미를 입히는 첫걸음은 기본형 집착, 세터를 없애는 과정은 변수·컬렉션 캡슐화
- 객체 복사의 깊이 문제는 얕은 복사와 깊은 복사
출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) · refactoring.com: Change Reference to Value · refactoring.com: Change Value to Reference · Martin Fowler: Value Object