-
4장 - 유스케이스 구현하기클린 코드(Clean Code)/만들면서 배우는 클린 아키텍처 요약 2023. 2. 24. 00:01
도메인 모델 구현하기
한 계좌에서 다른 계좌로 송금하는 유스케이스를 구현합니다.
객체지향적인 방식으로 모델링하기 위해 입금과 출금을 할 수 있는 Account 엔티티를 만들고 출금 계좌에서 돈을 출금해서 입금계좌로 돈을 입금해야 합니다.
해당 엔티티는 withdraw()라는 출금 메서드를 가지고, deposit()이라는 입금 메서드를 통해 입출금을 수행할 수 있습니다.
또한 출금하지 전에는 잔고를 초과하는 금액을 출금할 수 없도록 하는 비즈니스 규칙을 검사합니다.
유스케이스 둘러보기
일반적으로 유스케이스는 다음과 같은 단계를 따릅니다.
- 입력 받기
- 비즈니스 규칙 검증
- 모델 상태 조작
- 출력 반환
유스케이스는 인커밍 어댑터로부터 입력을 받으며 이 단계에서 유효성 검증은 이루어지지 않습니다.
유스케이스 코드는 도메인 로직에만 신경 써야 하며 입력 유효성 검증으로 오염되면 안 됩니다.
하지만 비즈니스 규칙을 검증할 책임은 있으며 도메인 엔티티와 이 책임을 공유합니다.
이제 비즈니스 규칙을 충족하면 유스케이스는 입력을 기반으로 어떤 방법으로는 모델의 상태를 변경합니다.
마지막 단계는 아웃고잉 어뎁터로 출력 값을 반환합니다.
다음 그림은 하나의 서비스가 유스케이스를 구현하고, 도메인 모델을 변경하고, 변경된 상태를 저장하기 위해 아웃고잉 포트를 호출하는 모습입니다.
입력 유효성 검증은 어디에서?
SendMoneyCommand라는 입력 모델을 두고 생성자 내에서 유효성 검증을 수행합니다.
송금 계좌, 입금 계좌, 송금할 금액이 필요하므로 이들은 null이 아니여야 하며 송금액은 0보다 커야 합니다.
이러한 조건 중 하나라도 위배되면 객체를 생성할 때 예외를 던져 객체 생성을 막습니다.
이후에는 final 키워드를 통해 불변 필드로 만들어냅니다.
비즈니스 규칙 검증은 어디에서?
입력 유효성 검증과 조금 헷갈릴 수 있다고 생각합니다.
둘을 구분하기 위해서는 도메인 모델의 현재 상태를 접근해야 하는지로 판단하면 좋습니다.
예를 들어 은행의 잔고는 음수일 수 없습니다.
이는 비즈니스 규칙이며 이를 확인하기 위해서는 현재 상태에 접근해야 합니다.
하지만 N원 출금을 위해서 들어오는 N은 항상 0보다 커야 하는 입력 유효성 검증입니다.
현재 도메인 모델 상태와 전혀 무관하기 때문입니다.
풍부한 도메인 모델 vs 빈약한 도메인 모델
풍부한 도메인 모델은 애플리케이션 코어에 있는 엔티티에서 가증한 한 많은 도메인 로직이 구현됩니다.
엔티티들은 상태를 변경하는 메서드들을 제공하고, 비즈니스 규칙에 맞는 유효한 변경만을 허용합니다.
예제의 Account 엔티티와 유사한 방식입니다.
반면 빈약한 도메인 모델은 getter, setter 메서드만 포함하고 도메인 로직을 가지고 있지 않습니다.
이는 도메인 로직이 유스케이스 클래스에 구현되어 있음을 뜻합니다.
'풍부함'이 엔티티 대신 유스케이스에 존재합니다.
개인적으로 풍부한 도메인 모델을 선호합니다.
유스케이스마다 다른 출력 모델
유스케이스가 할 일을 다하고 나면 호출자에게 무엇을 반환해야 할까?
'송금하기'가 잘 끝났다고 boolean 값 하나를 반환하면 될까?
업데이트된 Account를 통째로 반환하면 될까?
이 질문에 정답은 없고 의심스럽다면 가능한 적게 반환합니다.
도메인 엔티티를 출력 모델로 사용하고 싶은 유혹도 견뎌내야 합니다.
그렇지 않으면 도메인 엔티티가 필요 이상으로 커지게 됩니다.
'클린 코드(Clean Code) > 만들면서 배우는 클린 아키텍처 요약' 카테고리의 다른 글
6장 - 영속성 어댑터 구현하기 (0) 2023.02.26 5장 - 웹 어댑터 구현하기 (0) 2023.02.25 3장 - 코드 구성하기 (0) 2023.02.22 2장 - 의존성 역전하기 (0) 2023.02.21 1장 - 계층형 아키텍처의 문제는 무엇일까? (0) 2023.02.20