-
개발 형식이 고정될 수 밖에없는 과제이지만, 유지 보수 관점도 고려해야 한다 생각합니다.
- 개발에서 가장 힘들게 하는 것이 유지 보수라 생각하기에, 확장성을 고려했습니다.
-
하지만, YAGNI (You Aren't Gonna Need It) 원칙, 오버엔지니어링에 대해서도 고민해보았습니다.
- 인터페이스 적용은 캡슐화의 장점을 가집니다.
하지만, 인터페이스과 구현체가 1:1로 구성되면 오히려 복잡도만 높힌다는 피드백이 있었습니다.
때문에, 이러한 경우엔 다음과 같은 근거가 있는 경우에만 적용했습니다.
(ex. View는 외부 시스템과의 연관되기 때문에 인터페이스를 도입했습니다.)
- 인터페이스 적용은 캡슐화의 장점을 가집니다.
-
전통적인 MVC 패턴을 기반하되, Model에 대해 도메인 주도적으로 접근하고자 했습니다.
- 과제 학습 목표를 수행하기 위해, 세분화된 도메인마다 관심있는 작업을 스스로 처리하는 객체로 구성합니다.
- 도메인 패키지 내 각각은 해당 클래스에 관심있는 내용만 다루도록 직관적으로 책임을 분리합니다.
store/
├── common/
│ ├── config/
│ ├── constant/
│ ├── exception/
│ └── util/
│
├── controller/
├── domain/
│ ├── stock/
│ ├── promotion/
│ └── receipt/
│
├── dto/
├── repository/
├── service/
│ └──processor/
├── view/
│ ├── impl/
│ └── interfaces/
└── Application.java
각 패키지 별 역할과 특징은 다음과 같습니다.
- 프로젝트 전반에서 사용되는 클래스의 집합입니다.
- config/DependingConfig는 의존성 주입을 관리합니다.
- 사용자의 요청을 처리하고 응답을 반환하는 클래스들이 위치합니다.
- 사용자의 입출력과 애플리케이션의 흐름 제어를 담당합니다.
- 상품 구매 프로세스의 전반적인 흐름을 제어합니다.
- 사용자로부터 구매할 상품 목록을 입력받고 구매 프로세스를 진행합니다.
- 프로모션 적용, 멤버십 확인, 영수증 출력 등의 순서를 조정합니다.
- 비즈니스 로직의 핵심이 되는 도메인 모델들이 위치합니다.
- 각 핵심 모델들은 스스로 행위를 할 수 있는 객체로서 정의합니다.
- 모델은 정적 메소드 사용을 최소화합니다. 정적 생성기 호출이 필요한 경우에는 Factory를 사용합니다.
- 데이터는 전달 목적으로만 사용되어, 불변 객체인 Record 클래스로 선언합니다.
- resources 폴더의 md 파일에 접근해 데이터를 조회, 수정합니다.
해당 클래스들은 추후 데이터 저장소 변경 등을 고려하여, Interface를 상속받습니다.- 현재 Stcok과 Promotion의 Repository의 유사성이 크기에, 추상 클래스를 통해 레포지를 구현하여 코드 복잡성을 낮췄습니다.
- 비즈니스 로직을 처리하는 클래스들이 위치합니다.
- 도메인 객체들을 조작하고 실제 업무 규칙을 구현합니다.
- 상품 구매와 관련된 핵심 비즈니스 로직을 처리합니다.
- 프로모션 적용 여부를 확인하고 적절한 프로세서에 위임합니다.
- 사용자와의 상호작용을 담당하는 서비스입니다.
- 사용자 입력을 받고 검증하는 책임을 가집니다.
- 멤버십 확인, 추가 구매 확인 등 모든 사용자 프롬프트를 처리합니다.
- 재고 및 프로모션 데이터의 로딩과 검증을 담당합니다.
- 파일에서 로드한 데이터의 정합성을 검증합니다.
- 특정 비즈니스 로직의 세부 처리를 담당하는 클래스들이 위치합니다.
- 전략 패턴을 활용하여 다양한 상황에 대한 처리를 구현합니다.
- 프로모션 처리를 위한 공통 인터페이스를 정의합니다.
- 모든 프로모션 프로세서가 구현해야 하는 메서드를 선언합니다.
- 재고가 부족한 상황에서의 프로모션 처리를 담당합니다.
- 사용자에게 추가 구매 여부를 확인하고 처리합니다.
- 일부 수량만 프로모션이 적용 가능한 경우의 처리를 담당합니다.
- 프로모션 적용 가능한 수량과 일반 구매로 처리할 수량을 구분하여 처리합니다.
- 일반적인 구매 처리를 담당합니다.
- 프로모션이 적용되지 않는 일반 구매를 처리합니다.
- 상황에 맞는 프로모션 프로세서를 생성하고 반환합니다.
- 프로모션 상태에 따라 적절한 프로세서를 선택합니다.
- View는 사용자 인터페이스로 IO 제어 및 관리를 담당합니다.
- 이때, InputView는 Console이라는 별도의 라이브러리에 의존니다.
- OutputView는 개발 환경에 따라 변화할 여지가 있습니다.
- 따라서, 외부 시스템이 변경되더라도 핵심 비즈니스 로직에는 영향을 주지 않도록 Interface로 추상화했습니다.