참조 투명성 관련 문제

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
}