토스 Slash 강의에서 나왔던 문제와 그 해결
패키지 관리에 대한 문제
- 패키지 관리는 중요하다.
- 햄버거를 팔 때, 만일 빵 패티 피클, 감자튀김, 콜라를 전부 같은 통에 부어버린다면 과연 이것은 햄버거 세트인가?
- 패키지는 유연해야 한다. 적절한 패키지는 상황에 따라 달라진다.
- 햄버거 세트 100개를 판다면, 똑같이 포장하여 팔 것인가?
- 한 박스에 햄버거 100개를 따로 넣고
- 한 박스에는 감자튀김 100개를 따로 넣고
- 따로 포장된 음료 캐리어에는 콜라 100 개를 따로 넣는 것이 낫지 않을까?
- 햄버거 세트 100개를 판다면, 똑같이 포장하여 팔 것인가?
import 문에서 살펴보기
import com.core.component.CardPaymentProcessor;
import com.core.component.CardValidator;
import com.core.component.OrderValidator;
import com.core.dataaccess.StoreReader;
import com.core.dataaccess.CardReader;
import com.core.vo.Card;
import com.core.vo.CardPaymentRequest;
import com.core.vo.CustomerCard;
import com.core.vo.Order;
import com.core.vo.Store;
import org.springframework.stereotype.Service;
Card
도메인에 관련된 모든 것들이 나눠져있는 것처럼 보인다.- 햄버거로 치면, 패티, 치즈, 빵이 따로 포장된 것처럼 느껴진다.
import 문 개선해보기
package com.core.domain.card;
import com.core.domain.order.Order;
import com.core.domain.order.OrderValidator;
import com.core.domain.store.Store;
import com.core.domain.store.StoreReader;
import org.springframework.stereotype.Service;
이렇게 바꾸어보면 어떨까? domain
이란 곳에 card
에 관련된 기능을 모아놓았다.
생각해볼 문제
그런데, card
패키지에 너무 많은 클래스가 생긴다면? 그럴 때는 하위 그룹을 묶어서 하위 패키지를 한번 더 만들어주자.
package com.core.domain.card;
import com.core.domain.card.owner.CardIssuer;
import com.core.domain.card.owner.CardIssuerType;
import com.core.domain.card.owner.CardMaintainer;
Layer 에 관한 문제
클린 아키텍처를 지키기 위해 아래와 같은 참조 방향을 갖는다고 가정하자.
- ↓
Presentation Layer
- ↓
Business Layer
- ↓
Implementation Layer
- ↓
Data Access Layer
역방향 참조는 불가능하다.
import 문 살펴보기
import com.core.controller.MobilePaymentHttpRequest;
import com.core.controller.MobilePaymentHttpResponse;
import org.springframework.stereotype.Service;
@Service
class MobileService{
MobilePaymentHttpResponse addPayment(MobilePaymentHttpRequest request) {
// ...
}
}
Business Layer
인 Service
에서 Presentation Layer
를 참조하고 있다. 이는 참조 규칙을 위배하게 된다.
import 문 개선하기
import com.core.domain.payment.PaymentRequest;
import com.core.domain.store.Store;
import org.springframework.stereotype.Service;
@Service
class MobileService{
MobilePayment addPayment(Store store, PaymentRequst paymentRequest, CustomerMobile customerMobile) {
// ...
}
}
모듈 격리
최종적으로 모듈까지 격리하여 Service
에는 정말 비즈니스에 필요한 코드만 남게 만들어본다.
핵심
- 코드 하나하나를 소중히 여긴다.
- 동작하는 가장 간단한 코드로부터 출발하여 지속 성장 가능한 코드를 만든다.
- 통제
- 올바른 응집으로 코드를 관리한다.
- Layer 간의 규칙을 지킨다.
- 적절한 모듈화로 기술을 격리하여 다양한 변화에 대응할 수 있도록 한다.
- 이러한 통제를 통해 소프트웨어를 자유자제로 통제할 수 있어야 한다.
- 지속 성장
- 단순히 사업을 이어가는 것이 아니라 산업을 이끄는 시스템을 구축
- 진화할 수 있는 소프트웨어로 산업을 혁신시킨다.
- 오랜기간 사용해야 할 소프트웨어는 살아있는 소프트웨어이다.
- 변경에 유연해야 한다.
- 그러면서도 코드는 깔끔하고 의도를 알기 쉬워야 한다.
반응형