앞에서 도출한 모델은 Entity와 Value로 구분할 수 있다
식별자가 동일하면 같다고 판단 가능하다 → equals and hashcode 메서드로 구현가능ex) 주문 domain: 주문번호가 주문의 식별자가 된다
모델 표현력을 증가시킨다
의미를 명확히 표현하기 위해 밸류를 사용할 수 있다
ex) ShippingInfo에서 받는 사람을 나타내는 Value
public class ShippingInfo {
private String receiverName;
private String receiverPhoneNumber;
...
}
➡️ receiverName, receiverPhoneNumber 는 "받는사람" 에 대한 정보이다
➡️ 두개를 묶어 Receiver Value를 생성할 수 있다
-- Receiver Value 생성
public class ShippingInfo {
private Receiver receiver;
...
}
public class Receiver {
private String receiverName;
private String receiverPhoneNumber;
}
Value가 항상 두 개 이상의 데이터를 가져야 하는 것은 아니다
의미를 명확히 하기 위해 Value를 사용할 수 있다
ex) OrderLine의 price 표현
private class OrderLine {
private int price;
...
}
-- Money Value 생성 후
private class OrderLine {
private Money price;
...
}
private class Money {
private int value;
// 돈 계산에 대한 로직
}
왜 불변으로 구현할까?
- 불변객체: 생성 후 바꿀 수 없는 객체.
- 객체가 참조(reference)를 통해 공유되어있다면 상태가 언제든지 변경될 가능성이 있다
- 불변객체는 객체를 복제할 때 객체 전체가 아니라 참조만 복사하고 끝난다 → 참조는 보통 객체 그 자체보다 작아서 메모리가 절감되고 프로그램 성능에도 좋다
- 가변객체의 참조를 가지고 있는 어떤 장소에서 객체 변경 시, 해당 참조를 공유하는 모든 곳에서 영향을 받는다
- 멀티스레드 프로그래밍에서 유용하다
- 불변이란 객체가 컴퓨터의 메모리 내에서 쓰기를 할 수 없다는 뜻이 아니다.
ex) String str = “ABC”;
str.toLowerCase() → str 값을 변경하는 것이 아님. 새로운 String 객체가 생성되고, 생성 시 abc 값이 주어진다.
Value 객체를 비교할 땐 모든 속성이 같은지 비교한다.
엔티티의 식별자 데이터도 도메인 내에서 특별한 의미를 지니므로 Value로 표현할 수 있다
도메인 모델에 get/set method 습관적으로 만들지 말자
도메인 객체가 불완전한 상태로 사용되는 것을 막기위해서는 생성시점에 필요한 것을 전달해준다
→ 생성자를 통해 필요한 데이터를 모두 받아야 한다
→ 생성자를 호출하는 시점에 필요한 데이터가 올바른지 검사할 수 있다
-- 보통 이렇게 하겠죠
public class OrderService {
public void service_method() {
// Order 객체를 만들었다 가정하고
if ("PAYMENT_WAITING".equals(order.orderState) && "PREPARING".equals(order.orderState)) {
// 주문 배송전입니다
}
}
}
이렇게 구현하지 말고,
public class Order {
private OrderState state; -- enum으로 만들자
public void veryfyNotYetShipped() {
if (state != OrderState.PAYMENT_WAITING && state != OrderState.PREPARING) {
// 주문 배송전입니다
}
}
}
public enum OrderState {
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED, CANCELED;
}
service method 등에서 state를 getter로 가져와서 비교하지 말고, 해당 도메인 내에서 체크하는 함수를 만들고 그걸 가져다 쓰자
-- 안좋은예시 (setter 사용)
public class OrderService {
public void service_method() {
// Order 객체 생성했다 생각하고
order.setState(OrderState.CANCELED); // setter 사용
}
}
``` java
public class Order {
private OrderState state; -- enum으로 만들자
-- 도메인 내에 구현
public void cancel() {
this.state = OrderState.CANCELED;
}
}
public enum OrderState {
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED, CANCELED;
}
public class OrderService {
public void service_method() {
// Order 객체 생성했다 생각하고
order.cancel();
}
}