단일 책임 원칙

  • Single Responsibility Principle
  • 하나의 클래스나 모듈은 하나의 책임만을 가져야 한다.
    • 책임을 나누는 중요한 기준은 변경으로 '해당 코드를 변경하려는 이유는 무엇인가?' 에 대한 질문에 단 하나의 이유만 존재해야함

 

책임을 분리하지 않을 경우의 문제점

@Service
@RequiredArgsConstructor
public class PaymentService {

    private final PaymentRepository paymentRepository;

    public void addHistory (long amount, AddProduct addProduct) {
        // 할인 정책 적용
        if (amount >= 100000) {
            amount *= 0.8;
        }
        else if (amount >= 50000) {
            amount *= 0.9;
        }

        // 추가 상품 구매 여부
        if (AddProduct.TUMBLER.equals(addProduct)) {
            amount += 30000L;
        } else if (AddProduct.BAG.equals(addProduct)) {
            amount += 10000L;
        }

        // 결제 내역 저장
        paymentRepository.save(amount);
    }
}


public enum AddProduct {
    BAG, TUMBLER
}

  • 위에 코드에서 addHistory 는 내부에 할인 정책에 따른 금액 계산과 추가 상품 구매시 추가 금액 계산까지 모두 처리하고 있다. 이는 요구사항이 추가 및 변경되었을 때 다음과 같은 문제를 발생시킬 수 있다.
    • 요구사항이 추가되었을 경우 해당 코드처럼 작성한다면 하나의 메서드에 작성하는 코드가 길어짐
    • 여러 작업이 작성되어있는 코드 중 일부를 변경해야 할 때 코드가 길어질 경우 변경 부분을 찾기 어려워질 수 있고 개발자의 실수로 잘못된 부분을 변경할 수 있음

 

책임을 분리하라!

@Service
@RequiredArgsConstructor
public class PaymentService {

    private final PaymentRepository paymentRepository;
    private final DiscountPolicy discountPolicy;

    public void addHistory (long amount, AddProduct addProduct) {
        // 할인 정책 적용
        amount = discountPolicy.apply(amount);

        // 추가 상품 구매 여부
        if (addProduct != null) {
            amount += addProduct.getValue();
        }

        // 결제 내역 저장
        paymentRepository.save(amount);
    }
}


public enum AddProduct {
    BAG(30000), TUMBLER(10000);

    private long value;

    AddProduct(long value) {
        this.value = value;
    }

    public long getValue() {
        return value;
    }
}


@Component
public class DiscountPolicy {

    public long apply(long amount) {
        if (amount >= 100000) {
            return (long) (amount * 0.9);
        } else if (amount >= 50000) {
            return (long) (amount * 0.8);
        }
        return amount;
    }
}

  • 이전 코드를 수정하여 할인 정책 계산과 추가 상품 구매 금액 부분을 외부로 분리하여 위임하도록 변경하였다. 이를 통해 다음과 같은 장점을 얻을 수 있다.
    • 변경사항이 발생할 경우 해당 변경사항을 책임지는 모듈만 변경하면 됨. 즉, 변경 포인트가 명확해짐
    • 변경사항 외의 다른 부분을 건드리는 실수를 방지할 수 있다.
    • 분리한 모듈을 다른 부분에서 재활용할 수 있다.

 

다음글

+ Recent posts