/////
Search
Duplicate
5️⃣

도메인 모델 도출

: 도메인에 이해 없이는 코딩을 시작할 수 없다. 따라서 기획서, 유스케이스, 사용자 슽리와 같은 요구사항과 관련자와의 대화를 통해 도메인을 이해하고 이를 바탕으로 도메인 모델 초안을 만들어야 비로소 코드를 작성할 수 있다. 화이트보드, 종이와 연필, 모델링 툴 중 무엇을 선택하든 구현을 시작하려면 도메인에 대한 초기 모델이 필요한 것
: 도메인을 모델링할 때 기본이 되는 작업은 모델을 구성하는 핵심 구성요소, 규칙, 기능을 찾는 것, 이 과정은 요구사항에서 출발한다.
주문 도메인과 관련된 요구사항 예시
최소 한 종류 이상의 상품을 주문해야 한다.
한 상품을 한 개 이상 주문할 수 있다.
총 주문 금액은 각 상품의 구매 가격 합을 모두 더한 금액이다.
각 상품의 구매 가격 합은 상품 가격에 구매 개수를 곱한 값이다.
주문할 때 배송지 정보를 반드시 지정해야 한다.
배송지 정보는 받는 사람 이름, 전화번호, 주소로 구성된다.
출고를 하면 배송지를 변경할 수 없다.
출고 전에 주문을 취소할 수 있다.
고객이 결제를 완료하기 전에는 상품을 준비하지 않는다.
: 위의 예시를 통해 주문은 ‘출고 상태로 변경하기’, ‘배송지 정보 변경하기’ 등의 기능을 제공한다는 것을 알 수 있다. 이런 정보들을 통해 상세 구현까진 불가하지만 주문에 관련된 기능을 메서드로 추가 가능하다.
: 다음 요구사항은 주문 항목(OrderLine)이 어떤 데이터로 구성되는 지 알려준다.
⇒ 한 상품을 한 개 이상 주문할 수 있다.
⇒ 각 상품의 구매 가격의 합은 상품 가격에 구매 개수를 곱한 값이다.
: 두 요구사항에 따르면 주문 항목을 표현하는 OrderLine은 적어도 주문할 상품, 상품의 가격, 구매 개수를 포함해야 하며 추가로 각 구매 항목의 구매 가격도 제공해야 함
export class OrderLine { private product: object; private quantity: number; private price: number; private amount: number; }
TypeScript
복사
: OrderLine은 한 상품(product)를 얼마에(price) 몇 개 살지(quantity) 담고 있으며 구매 가격또한 제공한다.
: 다음 요구사항은 OrderOrderLine 간의 관계를 설명해준다.
⇒ 최소한 한 종류 이상의 상품을 주문해야 한다.
⇒ 총 주문 금액은 각 상품의 구매 가격 합을 모두 더한 금액이다.
: 한 종류 이상의 상품을 주문할 수 있으므로 Order는 최소 한 개 이상의 OrderLine을 포함, 또한 총 주문 금액은 OrderLine으로 구할 수 있음
export class Order { private orderLines: OrderLine[]; private totalAmount: number; constructor(orderLines: OrderLine[]) { this.verifyAtLeastOneOrMoreOrderLines(orderLines); this.orderLines = orderLines; this.totalAmount = this.calculateTotalAmount(orderLines); } private verifyAtLeastOneOrMoreOrderLines(orderLines: OrderLine[]) { if (!orderLines || orderLines.length === 0) { throw new Error('Order must have at least one or more order lines.'); } } private calculateTotalAmount(orderLines: OrderLine[]) { return orderLines.map(orderLine => orderLine.getAmount()).reduce((a, b) => a + b, 0); } }
TypeScript
복사
: Order는 한 개 이상의 OrderLine을 가질 수 있으므로 Order를 생성할 때 OrderLine 목록을 List로 전달, 생성자에서는 verifyAt…, calculat…를 통해 초기화
: 배송지 정보는 이름, 전화번호, 주소 데이터를 가지므로 ShippingInfo 클래스를 다음과 같이 정의
export class ShippingInfo { private receiverName: string; private receiverPhone: string; private firstShippingAddress: string; private secondShippingAddress: string; private shippingZipCode: string; }
TypeScript
복사
: 앞서 요구사항 중, 주문할 때 배송지 정보를 반드시 지정해야 한다라는 내용을 통해 Order를 생성할 때 OrderLineList 뿐아니라 ShippingInfo도 넘겨주어야함을 알 수 있음
: 생성자에서 호출하는 setShippingInfo() 메서드는 ShippingInfo가 null이면 예외가 발생하는데, 이를 통해 배송지 정보 필수라는 도메인 규칙을 구현
: 도메인을 구현하다보면 특정 조건이나 상태에 따라 제약이나 규칙이 달리 적용되는 경우가 많음, 주문 요구사항에서는 다음 내용이 제약과 규칙에 해당됨
⇒ 출고를 하면 배송지 정보를 변경할 수 없다.
⇒ 출고 전에 주문을 취소할 수 있다.
: 이 요구사항들은 출고 상태가 되기 전과 후의 제약사항을 기술하고 있는데, 출고 상태에 따라 정보 변경 기능과 주문 취소 기능은 다른 제약을 갖음, 이런 요구사항을 반영 하기 위해 주문은 출고 상태에 대한 필드가 존재해야 함, 또한 다음 요구사항도 상태와 관련이 있음
⇒ 고객이 결제를 완료하기 전에는 상품을 준비하지 않는다.
: 이런 요구사항들을 통해 결제 완료 전을 의미하는 상태와 결제 완료 내지 상품 준비 중이라는 상태가 필요함을 알려줌, 이는 enum을 통해 표현할 수 있음
: 배송지 변경이나 주문 취소 기능은 추고 전에만 가능하다는 제약 규칙이 존재하므로 이 규칙을 적용하기 위해 changeShippingInfo()cancel()verifyNotYetShipped() 메서드를 먼저 실행 후 진행
export class Order { private orderLines: OrderLine[]; private shippingInfo: ShippingInfo; private totalAmount: number; private state: OrderState; public changeShipped() { this.state = OrderState.SHIPPED; } public changeShippingInfo(shippingInfo: ShippingInfo) { this.checkNotYetShipped(); this.setShippingInfo(shippingInfo) } public cancel() { this.checkNotYetShipped(); this.state = OrderState.CANCELED; } private checkNotYetShipped() { if (this.state !== OrderState.PAYMENT_WAITING && this.state !== OrderState.PREPARING) { throw new Error('Order already shipped.'); } } }
TypeScript
복사
: 지금까지 주문과 관련된 요구사항에서 도메인 모델을 점진적으로 만들어 나가는 프로세스를 진행했음, 일부는 구현수준까지도 만들었고 일부는 이름 정도만 결정하는 수준에서 끝나기도 했음, 이렇게 만든 모델은 요구사항 정련을 위해 도메인 전문가나 다른 개발자와 논의하는 과정에서 공유하기도 함, 모델을 공유할 때는 화이트보드나 위키와 같은 도구를 사용해서 누구나 쉽게 접근할 수 있도록 하면 더 좋음
문서화
문서화를 하는 주된 이유는 지식을 공유하기 위함, 실제 구현은 코드에 존재하므로 코드를 보면 다 알 수 있지만 코드는 상세한 모든 내용을 다루고 있기 때문에 코드를 이용해서 전체 소프트웨어를
분석하려면 많은 시간이 필요함, 즉 전반적인 기능 목록이나 모듈 구조, 빌드 과정은 코드를 직접 이해하는 것보단 상위 수준에서 정리한 문서를 참고하는 것이 소프트웨어 전반을 이해하는 데 도움이 됨,
코드를 보면서 도메인을 깊게 이해하면 되므로 코드 자체도 문서화의 대상이 됨