SOLID 5 원칙, 다형성을 지향하는 객체지향 개발

Ryu·2022년 8월 9일
0

스프링 핵심 원리

목록 보기
1/1

뭔가 단순히 프로젝트 내용을 열거하는 것보다, 실제로 개발해보면서 마주친 에러들, 어려운 내용들을 정리해보자.

테스트 코드 작성

✅ 테스트 코드 작성 방법을 given, when, then 으로 나눠서 작성해보자.

@Test
void join() {
    //given, 특정 member 주어졌을 때
    Member member = new Member(1, "spring", Grade.VIP);

    //when, 특정 기능 테스트 (회원 가입)
    memberService.join(member);
    Member findMember = memberService.findMember(1);

    //then, 같은 값인지 테스트.
    Assertions.assertThat(findMember).isEqualTo(member);
}

주문과 할인 도메인 개발


단일 책임 원칙이 잘 지켜진 설계이다 !

// OrderServiceImpl.java

@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
    Member member = memberRepository.findById(memberId);
    int discountPrice = discountPolicy.discount(member, itemPrice);

    return new Order(memberId, itemName, itemPrice, discountPrice);
}

🤔 회원 도메인, 주문 도메인처럼 하나의 클래스로 구성해야 하는 경우 ?

  • 해당 객체가 정보를 많이 들고 있어야할 때.
    ’객체’는 데이터의 묶음이다.

다음 코드의 문제점은 무엇일까 ?

public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}
  1. OrderServiceImpl 은 인터페이스에만 의존해야 한다.
  • 그러나 현재, new FixDiscountPolicy(); 처럼 구현체에도 의존하고 있다.
  • 이렇게 설계하면, 유연한 설계가 아니며 DIP 를 위반한 것이다.
  • OCP 는 변경하지 않고 확장 가능한 것이어야 하는데 지금 코드에서는 할인정책 변경 시 클라이언트 코드에 영향을 준다. 즉, OCP 위반.

⭐ 5가지 SOLID 원칙에 대해서 알아보자.


✅ SRP (Single Responsible Principle) 단일 책임 원칙

  • 한 클래스는 하나의 책임만 가져야 한다.
  • 하나의 책임이라는 것의 기준은, ‘변경’이다. 코드 변경 시, 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것이다.

✅ OCP (Open / Closed Principle) 개방-폐쇄 원칙

  • 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
    • 다형성(인터페이스 - 구현체)을 활용하면 가능하다.
      유지보수가 매우 쉬워진다. (구현체 부분만 바꾸기 때문)
  • 그러나, 클라이언트 코드가 구현체 클래스에 의존하는 경우가 있다.
    • 분명 다형성을 적용했지만, OCP 원칙을 위배한다. (클라이언트의 코드 변경 발생)
    • 이 문제를 ‘스프링’이 해결해준다. (객체 생성과 연관관계 주입)

✅ LSP (Liskov substitution principle) 리스코프 치환 원칙

  • 다형성에서 하위클래스(구현 클래스)는 인터페이스 규약을 모두 지켜야 한다.
  • 단순히 컴파일 성공하는 것이 아닌, 인터페이스에 정해진 ‘규약’을 지켜야 한다는 뜻.

✅ ISP (Interface Segregation Principle) 인터페이스 분리 원칙

  • 특정 클라이언트를 위한 여러 개의 인터페이스가 범용적인 인터페이스 하나보다 낫다.
  • 인터페이스가 명확해질수록, 대체 가능성이 높아져 유지보수가 쉽다.

✅ DIP (Dependecy Inversion Principle) 의존관계 역전 원칙

⭐ 결론

  • 객체 지향의 핵심은 다형성이다. 다형성을 통해 부품을 쉽게 갈아 끼우듯 개발 가능하다.
  • 그러나 다형성 만으로는 OCP, DIP를 지킬 수 없다.
    • 구현 객체 변경 시 클라이언트 코드 변경도 일어나기 때문.
profile
Strengthen the core.

0개의 댓글