package buckpal.domain;
public class Account {
private Accountld id;
private Money baselineBalance;
private Activitywindow activitywindow;
// 생성자와 getter는 생략
public Money calculateBalance() {
return Money.add(
this.baselineBalance,
this.activitywindow.calculateBalance(this.id));
}
public boolean withdraw(Money money, Accountld targetAccountld) {
if (!mayWithdraw(money)) {
return false;
}
Activity withdrawal = new Activity(
this.id,
this.id,
targetAccountld,
LocalDateTime.now(),
money);
return true;
}
private boolean mayWithdraw(Money money) {
return Money.add(
this.calculateBalanceQ,
money.negate()
.isPositive();
}
public boolean deposit(Money money, Accountld sourceAccountld) {
Activity deposit = new Activity(
this.id,
sourceAccountld,
this.id,
LocalDateTime.now(),
money);
this.activitywindow.addActivity(deposit);
return true;
}
}
유스케이스 코드가 도메인 로직에만 신경 써야 하고 입력 유효성 검증으로 오염되면 안 된다. 입력 유효성 검증은 다른 곳에서 처리한다. 그러나 유스케이스는 비즈니스 규칙(business rule)을 검증할 책임이 있다.
package buckpal.application.service;
@RequiredArgsConstructor
@Transactional
public class SendMoneyService implements SendMoneyUseCase {
private final LoadAccountPort loadAccountPort;
private final AccountLock accountLock;
private final UpdateAccountStatePort updateAccountStatePort;
©Override
public boolean sendMoney(SendMoneyCommand command) {
// TODO: 비즈니스 규칙 검증
// TODO: 모델 상태 조작
// TODO: 출력 값 반환
}
}
입력 유효성 검증은 유스케이스 클래스의 책임 X,
하지만 여전히 애플리케이션 계층의 책임 O -> 왜? -> 유스케이스 호출자(celler) 가 모두 검증 했다고 믿을 수 없다
그럼 어디? -> 입력 모델 -> 정확히 말하면 생성자 내에서 입력 유효성을 검증
구현은 어떻게? -> Bean Validation API를 활용하여
유스케이스 구현체 주위에 사실상의 오류 방지 계층을 만들었다
생성자에 필요한 파라미터가 많으면 어떻게 해야하지? -> 빌더 패턴? -> 빌더는 유효성을 검증을 컴파일 단계에서 해주지 못한다
흠.. 이러한 이유로 생성자를 사용하자는 거 같은데 자바가 문제가 많다.. 코틀린으로 넘어가자
범용성이 높은 입력 모델을 사용하기 위해서는 null 를 허용하게 된다 -> 그 자체로 문제가 발생
-> 동의하는 부분
비즈니스 규칙 검증은 현재 상태에 접근을 해야된다!!!
구현 방법은 어떻게? -> 도메인 엔티티 안에 넣자 (DDD?) -> 여의치 않다면 -> 유스케이스에 -> 당연한 듯?
출력도 구체적으로, 꼭 필요한 데이터만 들고 있어야 한다.
-> 흠... 근데 이러면 도메인이 출력에 의존적으로 바뀌는 거 아닌가? -> 엔티티를 입력 모델이나 출력 모델로 사용하는 것은 11장에서...
애플리케이션 코어의 관점에서는 단순한 데이터 쿼리 -> 쿼리 서비스
CQS, CQRS 개념과 맞게
단점은 작업의 양이 많아진다... -> 매핑과정이 늘어서
하지만 유스케이스를 명확하게 이해하게 하고 장기적 유지보수를 쉽게 만든다