4. 자바예제 - 주문과 할인 도메인 설계

Yuri JI·2023년 1월 8일
0

주문과 할인 도메인 설계

  • 주문과 할인 정책
    • 회원은 상품 주문 가능
    • 회원 등급에 따른 할인 정책 차등 적용
    • 모든 VIP는 1000원 할인 (고정 금액 할인) → 추후 변경 가능
    • 할인 정책은 변경 가능성이 높음. 회사의 기본 할인 정책은 아직 미확정 상태

⇒ 인터페이스를 만들고 구현체를 언제든지 갈아 끼울 수 있어야 한다 !
⇒ 앞에서 배운 객체 지향 설계 방법을 이용해서 비즈니스 요구 사항대로 설계해보자

  • 역할과 구현을 분리 자유롭게 구현 객체를 조립할 수 있도록 설계하자!
    • 회원을 메모리에서 조회하고, 정액 할인 정책(고정금액)을 지원해도 주문 서비스를 변경하지 않아도 된다. → 역할들의 협력 관계를 그대로 재사용 할 수 있다.

  • 클래스 다이어그램과 다르게 객체 다이어그램은 실제 내가 new로 생성하고 애플리케이션을 띄웠을 때 객체들의 연관관계가 동적으로 만들어지는 다이어 그램

주문과 할인정책 개발

  • 할인 정책
    • (역할) ((Interface)) DiscountPolicy 회원 정보와 물건의 가격을 토대로 할인 정책 결정
      public interface DiscountPolicy {
      
          /**
           * @return 할인 대상 금액
           */
          int discount(Member member, int price);
      }
    • (구현) FixDiscountPolicy 고정 할인 정책
      public class FixDiscountPolicy implements DiscountPolicy {
      
          /*   VIP면 1000원 할인, 아니면 할인 없음 */
      
          private int discountFixAmount = 1000; // 1000원 할인
      
          @Override
          public int discount(Member member, int price) {
              if (member.getGrade() == Grade.VIP) {
                  return discountFixAmount;
              } else {
                  return 0; // 할인 없어 !
              }
          }
      }
      
  • 주문
    • ((Interface))OrderService (역할)
      public interface OrderService {
          /*
              주문 생성
                  - 회원 ID
                  - 상품명
                  - 상품가격
              return 주문 결과 반환
           */
          Order createOrder(Long memberId, String itemName, int itemPrice);
      }
    • 구현체 OrderServiceImpl
      • 회원 검색을 위해 MemebrRepostitory가 필요함

      • 할인 정책을 위해 DiscountPolicy가 필요함

        public class OrderServiceImpl implemets OrderService {
        		
        		// MemberRepository에서 회원을 찾아야 한다.
        		private final MemberRepository memberRepository = new MemoryMembreRepository();
        		// DiscountPolicy에서 할인 정책을 찾는다.
        		private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
        
        		@Override
        		public Order createOrder(Long memberId, String itemName, int itemPrice) {
        				/*
        					Member 대신 Grade를 넣어줘도 된다. 나의 선택이다.
        	
        					회원을 조회하고, 아이템 가격을 넣어주면 주문 결과를 반환한다.
        				*/
        	
        				Member member = memberRepository.findById(memeberId);
        				int discountPrice = discountPolicy.discount(member, itemPrice);
        				
        				return new Order(memberId, itemName, itemPrice, discountPrice);
        		} 
        }

        ❗ 설계가 매우 잘된 상황

        why? OrderService에서는 할인에 대한 것을 모른다. DiscountPolicy가 할인을 처리한다. → 단일 책임 원칙 준수, 할인에 대한 변경은 할인 쪽에서만 이뤄진다.

주문과 할인정책 실행

  • OrderApp : main method를 이용한 실행
    // 멤버 서비스 
    // 주문 서비스 
    
    // 멤버 객체 생성 (할인 정책이 적용되었는지 알기위해 Grade.VIP)
    // 멤버 회원가입 
    
    // 멤버가 itemA(1000원) 주문함
    // System.out.println("order = " + order); // 9000

주문과 할인정책 테스트

  • OrderServiceTest
    import org.assertj.core.api.Assertions; 
    
    // 멤버 서비스 
    // 주문 서비스 
    
    @Test
    void createOrder() {
    		// 멤버 객체 생성 (할인 정책이 적용되었는지 알기위해 Grade.VIP)
    		// 멤버 회원가입 
    
    		// 멤버가 itemA(1000원) 주문함
    		Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
    }

✍️ 단위 테스트
스프링이나 컨테이너의 도움없이 자바 코드로만 테스트를 하는 것

  • 다음 시간에는 ~

    • 지금까지 작성한 코드에 변경이 생겼을 때 정말 우리가 객체지향적으로 개발되었는지? 변경 사항이 있을 때 클라이언트에게 영향을 주지 않는지 고민해야한다.
    • 현재까지의 코드는 역할과 구현을 잘 분리하면서 다형성을 잘 지켰다 !
    • 하지만 고정 할인 정책에서 정률 할인 정책으로 바꿀 때도 윗 줄처럼 말할 수 있을지 고민해보자 (DIP, OCP 위반)
  • 참고 사이트

profile
안녕하세요 😄

0개의 댓글