public boolean validateOrder(Order order) {
if (order.getItems().size() == 0) {
log.info("주문 항목이 없습니다.");
return false;
} else {
if (order.getTotalPrice() > 0) {
if (!order.hasCustomerInfo()) {
log.info("사용자 정보가 없습니다.");
return false;
} else {
return true;
}
} else if (!(order.getTotalPrice() > 0)) {
log.info("올바르지 않은 총 가격입니다.");
return false;
}
}
return true;
}
public boolean validateOrder(Order order) {
if (order.getItems().size() == 0) {
log.info("주문 항목이 없습니다.");
return false;
}
if (order.getTotalPrice() > 0) {
if (!order.hasCustomerInfo()) {
log.info("사용자 정보가 없습니다.");
return false;
}
return true;
}
if (!(order.getTotalPrice() > 0)) {
log.info("올바르지 않은 총 가격입니다.");
return false;
}
return true;
}
public boolean validateOrder(Order order) {
if (order.getItems().size() == 0) {
log.info("주문 항목이 없습니다.");
return false;
}
if (!(order.getTotalPrice() > 0)) {
log.info("올바르지 않은 총 가격입니다.");
return false;
}
if (!order.hasCustomerInfo()) {
log.info("사용자 정보가 없습니다.");
return false;
}
return true;
}
public boolean validateOrder(Order order) {
if (order.getItems().size() == 0) {
log.info("주문 항목이 없습니다.");
return false;
}
if (order.getTotalPrice() <= 0) {
log.info("올바르지 않은 총 가격입니다.");
return false;
}
if (order.hasNotCustomerInfo()) {
log.info("사용자 정보가 없습니다.");
return false;
}
return true;
}
public void validateOrder(Order order) {
if (order.getItems().size() == 0) {
throw new OrderException("주문 항목이 없습니다.");
}
if (order.getTotalPrice() <= 0) {
throw new OrderException("올바르지 않은 총 가격입니다.");
}
if (order.hasNotCustomerInfo()) {
throw new OrderException("사용자 정보가 없습니다.");
}
}
public class OrderException extends RuntimeException {
public OrderException(String message) {
super(message);
}
}
public class Order {
private List<Item> items;
private Customer customer;
private Order(List<Item> items, Customer customer) {
this.items = items;
this.customer = customer;
validateOrder();
}
public static Order of(List<Item> items, Customer customer) {
return new Order(items, customer);
}
public int getItemCount() {
return items.size();
}
public int getTotalPrice() {
return items.stream()
.mapToInt(Item::getPrice)
.sum();
}
private void validateOrder() {
if (hasNotItems()) {
throw new OrderException("주문 항목이 없습니다.");
}
if (isIllegalTotalPrice()) {
throw new OrderException("올바르지 않은 총 가격입니다.");
}
if (hasNotCustomerInfo()) {
throw new OrderException("사용자 정보가 없습니다.");
}
}
private boolean hasNotItems() {
return items == null || getItemCount() == 0;
}
private boolean isIllegalTotalPrice() {
return getTotalPrice() <= 0;
}
private boolean hasNotCustomerInfo() {
return customer == null;
}
}
public class OrderException extends RuntimeException {
public OrderException(String message) {
super(message);
}
}
단일 책임 원칙이란 말 그대로 하나의 클래스는 하나의 책임만을 가져야 한다는 의미이다.
하나의 클래스가 여러 책임을 가지게 되면 클래스의 기능이 불분명해지고 가독성이 떨어지게 된다.
한 클래스가 어떠한 책임을 가지게 할 것인가는 개발자의 판단에 달려 있고 이에 대한 판단을 명확히 하기 위해 노력해야 한다.
개방 폐쇄 원칙이란 확장에는 열려있지만 수정에는 닫혀있다는 의미이다.
요구사항에 따라 변경이 필요할 때 다른 클래스에까지 영향을 주지 않아야 한다.
추상화한 클래스를 의존함으로써 내부 수정이 있더라도 해당 클래스를 의존하는 다른 클래스에는 영향을 미치지 않을 수 있다.
리스코프 치환 원칙은 상위 타입의 인스턴스가 하위 타입의 인스턴스의 역할을 다할 수 있어야 한다는 의미이다.
어떠한 하위 타입이 상위 타입 대신 들어오더라도 정상적인 기능을 해야 한다.
인터페이스 분리 원칙은 인터페이스의 단일 책임 원칙이다.
인터페이스 또한 하나의 책임을 가지고 있어야 하고, 만약 그렇지 않다면 분리가 필요하다.
의존성 역전 원칙은 고수준 모듈이 저수준 모듈에 의존해서는 안된다는 의미이다.
고수준 모듈이 저수준 모듈을 의존하는 게 순방향적인 관계지만, 이렇게 되면 저수준 모듈에 변경이 발생하는 경우 고수준 모듈에도 영향이 간다.
이를 방지하기 위해서 둘 다 추상화에 의존하여야 한다.