참조 투명성 관련 문제
public class OrderLine {
private Product product;
private Money price;
private int quantity;
public OrderLine(Product product, Money price, int quantity) {
this.product = product;
this.price = price;
this.quantity = quantity;
}
}
Product product = new Product("티셔츠");
Money price = new Money(1000);
OrderLine line = new OrderLine(product, price, 2);
// OrderLine에 price값이 변경될 수 있다.
price.setValue(2000);
public class OrderLine {
private Product product;
private Money price;
private int quantity;
public OrderLine(Product product, Money price, int quantity) {
this.product = new Product(product.getName()); // 새로운 객체
this.price = new Money(price.getValue()); // 새로운 객체
this.quantity = quantity;
}
}
Product product = new Product("티셔츠");
Money price = new Money(1000);
OrderLine line = new OrderLine(product, price, 2);
// 새로운 객체로 주입되므로 OrderLine에 price값이 변경될 수 없다.
price.setValue(2000);
public 형식의 set 메서드 넣지 않기
public class OrderLine {
private Product product;
private Money price;
private int quantity;
public OrderLine(Product product, Money price, int quantity) {
setProduct(product);
setPrice(price);
setQuantity(quantity);
}
// 필수적인 값 검증을 위한 set 메서드
private void setProduct(Product product) {
if (product == null || product.getName() == null)
throw new IllegalArgmentException("No Product");
this.product = new Product(product.getName());
}
private void setPrice(Money price) {
if (price == null || price.getValue() == null)
throw new IllegalArgmentException("No Price");
this.price = new Money(price.getValue());
}
private void setQuantity(int quantity) {
if (quantity <= 0)
throw new IllegalArgmentException("No Quantity");
this.quantity = quantity;
}
}
해석 가능한 도메인 용어
public enum OrderState {
STEP1, STEP2, STEP3, STEP4, STEP5
}
public enum OrderState {
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED
}