1. 예제 확장
위 그림과 같이 예제를 확장해보자.
Plan(Creature, CaringPrice, Policy)
관리 계획에서는 Plan이라는 객체가 있고, Plan은 생물(creature)의 종류, 생물 종류에 따른 Caring Price, 관리 정책 Policy에 의해 제어된다.
Service, 로직을 구현하는 위치
클라이언트로부터 받은 파라미터 값을 검증(validation)하거나, 계산하는 등 input값을 바탕으로 적절한 output을 만들어 내는 곳이다.
Creature, 관리 대상인 생물들
생물들은 각기 무게(weight)가 있고, 무게에 비례하게 관리 비용(expense)이 든다고 가정한다. 또한 동물이든 식물이든 멸종위기 종의 기준인 Grade가 있어서, 일반 종은 Normal, 멸종위기종은 Endangered로 표기된다.
Repository, 동물원이냐 식물원이냐
생물 저장소는 달리말해 동물원이냐 식물원이냐를 결정한다. CreatureRepositoryAnimals 구현체를 연결하면 동물원이 되고, CreatureRepositoryPlants를 연결하면 식물원이 된다.
CaringPolicy, 관리 자금을 어떻게 투입할 것인가
생물의 등급(Grade)이 어떤지에 따라 비용(expense)이 변하고, 관리정책이 FixedCaringPolicy(정량 정책), RateCaringPolicy(정률 정책) 이냐에 따라서 생물체들을 관리하는 비용을 다르게 매긴다. 예를 들어서 정량 정책인 경우 일반 종에는 10,000원, 멸종위기 종에는 20,000원(+10,000원)을 배정할 수 있다. 정률은 이와 다르게 일정한 비율을 갖고 일반 종과 멸종위기종의 관리에 들어갈 비용을 산출한다. 50%를 적용한다면 일반종에는 10,000원, 멸종위기종에는 15,000원을 투입할 수 있을 것이다.
2. SRP(Single Resonsibility Principle)
"하나의 객체는 하나의 책임만 갖는다."
1. 예제 확장과 같이 관리 정책(CaringPolicy), 관리 계획(Plan)을 분리해서 설계했기 때문에, 프로그램 작성 시에 각 객체들이 분리되어 변경이 용이해짐을 알 수 있다. 아래 코드에서 좀 더 자세히 살펴본다.
2-1. CaringPolicy
caring 패키지를 생성한다. 각 policy는 생물과 기본 비용(expense) 정보를 받고, 정책을 적용해서 총 금액을 계산해주는 기능을 갖는다.
CaringPolicy.interface
FixedCaringPolicy.class
CaringPolicy를 implements로 받아온다.
2-2. Plan
클라이언트에 전달할 Plan 객체를 작성한다. creatureId, expense, totalExpense를 필드값으로 갖는다. 아래의 Constructor, Getter and Setter 및 toString은 윈도우에서는 [Alt + insert] 키를 통해 자동으로 생성할 수 있다.
PlanService
creatureId와 expense값을 전달하면, CaringPolicy를 적용한 최종 비용인 totalExpense를 계산하고, 이것을 파라미터로 한 Plan 객체를 다시 반환해준다.
SRP를 지켜서 Plan과 Policy를 따로 작성했던 것이 여기서 힘을 발휘한다. 따로 작성된 Policy를 Plan에서 불러오고, totalExpense를 계산하도록 하였다. 이런 부분을 "PlanService가 CaringPolicy 객체에 의존한다." 또는 "PlanService가 CaringPolicy와 의존 관계를 갖는다." 라고 표현한다. 만약 CaringPolicy가 변경된다면, CaringPolicy를 작성한 부분으로 이동하여 해당 부분만 수정하면 된다.
PlanService가 CaringPolicy를 주입받는다
단순히 의존하는 것과는 약간 다른 개념이다. 다음 글에서 PlanService가 CaringPolicy 등을 주입받는다는 개념을 생성자 주입 방식으로 알아보자.
참조
1. 인프런_스프링 핵심 원리 기본편_김영한 님 강의
www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard
'Programming-[Backend] > Spring' 카테고리의 다른 글
[스프링 기초] 7. IoC, DI, 컨테이너 (0) | 2021.06.12 |
---|---|
[스프링 기초] 6. 사용영역과 구성영역 나누기로 SRP, OCP, DIP 원칙 실현하기 (0) | 2021.06.06 |
[스프링 기초] 4. 예제 만들기 (0) | 2021.05.25 |
[스프링 기초] 3. 프로젝트의 구조 및 생성 (0) | 2021.05.25 |
[TIL] BeanUtils.copyProperties, 엔티티 객체 복사하기 (0) | 2021.05.25 |