워밍업 클럽 4기 - 백엔드 Day 4 미션: SOLID

1. 코드 리팩토링

public boolean validateOrder(Order order) {
    if (order.isEmpty()) {
        log.info("주문 항목이 없습니다.");
        return false;
    }

    if (order.hasZeroOrNegativeTotalPrice()) {
        log.info("올바르지 않은 총 가격입니다.");
        return false;
    }

    if (order.hasEmptyCustomerInfo()) {
        log.info("사용자 정보가 없습니다.");
        return false;
    }

    return true;
}

public class Order {
        
        // items, totalPrice, customerInfo는 있다고 가정

        public boolean isEmpty() {
            return this.items.size() == 0;
        }

        public boolean hasZeroOrNegativeTotalPrice() {
            return this.totalPrice <= 0;
        }

        public boolean hasEmptyCustomerInfo() {
            return this.customerInfo == null;
        }

    }

 

2. SOLID를 나만의 언어로 표현하기

 

  1. SRP(단일 책임 원칙):

    객체의 책임을 하나의 홑문장으로 설명할 수 있어야 한다.

  • 서술어가 2번 나온다는 말은 동작이 2번 나온다는 말이고, 과한 책임을 지고있거나 구체적인 특징만 나열한 경우일 수 있다.(예: 쿼터백은 패스 게임에서는 공을 던지고, 러닝 게임에서는 공을 러닝백에네 넘겨주고, 코치의 작전을 다른 공격 선수들에게 전달한다.)

  • 객체를 설명하는 말의 추상화 정도가 과하면 객체를 적절히 설명할 수 없다.(예: 쿼터백은 미식축구 포지션이다.)

  • 미식축구에서 쿼터백은 공격 전술을 지휘하는 포지션이다.

 

  1. OCP(개방 폐쇄 원칙): 기능을 변경할 때는 코드를 고치는 게 아니라 코드를 더하는 방식으로 구현해야 한다.

     

    • 변경해야 할 코드와 그대로 유지되어야 할 코드가 섞여 있으면, 기능을 수정할 때마다 기존 코드를 계속 수정하게 되고, 이로 인해 변경이 다른 코드에까지 영향을 미칠 수 있다.

       

    • 따라서 변경이 필요한 부분과 보존해야 할 부분을 명확히 분리하고, 새로운 기능은 기존 코드를 건드리지 않고 덧붙이는 방식으로 구현해야 한다.

 

  1. LSP(리스코프 치환 원칙): 부모 클래스가 자식 클래스에게 물려준 기능은 보존해야한다.

     

    • 부모 클래스를 자식 클래스로 교체한다는 것은, 부모의 기능을 자식이 할 수 있다는 전제가 깔려있다.

       

    • 그런데 만약 자식 클래스가 부모 클래스의 기능을 제대로 수행하지 못한다면, 예기치 못한 동작을 하거나 에러가 발생한다.

    • 그렇다면 부모 클래스를 자식 클래스로 교체하는데 추가적인 리소스가 든다.

    • 따라서 자식 클래스는 부모 클래스의 기능을 보존해야한다.

 

  1. ISP(인터페이스 분리 원칙): 응집도 높은 인터페이스를 설계해야 한다.

     

    • 인터페이스는 객체의 설계도다. 그리고 인터페이스가 변경된다면, 모든 구현체도 변경되어야 한다.

    • 인터페이스의 응집도가 낮아 여러 책임이 뒤섞여 있으면 일부 기능 변경으로 인해 구현체는 불필요한 변경을 할 수 있다.

    • 따라서 인터페이스는 관련 기능들로 묶인, 응집도 높은 형태로 설계해야 한다.

 

  1. DIP(의존 역전 원칙): 고수준 모듈과 저수준 모듈이 맺는 하나의 의존 관계를 2개의 의존 관계로 분리하여 결합도를 낮춘다.

     

    • 고수준 모듈과 저수준 모듈이 직접 연결되어 있으면, 저수준 모듈의 변경 사항은 고수준 모듈까지 전파될 수 있다.

    • 하지만 저수준 모듈을 추상화하면, 아래 같이 2개의 의존 관계로 쪼개진다.

      • 고수준 모듈은 추상화 모듈 의존

      • 저수준 모듈은 추상화 모듈 의존(의존성 역전)

    • 이렇게 2개로 쪼개진 의존 관계에서는, 저수준 모듈의 변경이 고수준 모듈에 영향을 주지 못해 코드의 유지보수성이 향상된다.

 

%추가% DI(의존성 주입): 어떤 포지션에 어떤 선수를 넣을지 말지는 감독의 책임이다.(스포츠 관점)

 

댓글을 작성해보세요.

채널톡 아이콘