[DDD START] 6장 응용 서비스와 표현 영역 - 응용 서비스의 역할

응용 서비스의 역할

응용 서비스는 도메인 객체 간의 흐름을 제어하기 때문에 단순하다

public Result doSomeFunc(SomeReq req) {
    // 1. 리포지터리에서 애그리거트를 구한다
    SomeAgg agg = someAggRepository.findById(req.getId());
    checkNull(agg);

    // 2. 애그리거트의 도메인 기능을 실행한다
    agg.doFunc(req.getValue());

    // 3. 결과를 리턴한다
    return createSuccessResult(agg);
}
public Result doSomeCreation(CreationSomeReq req) {
    // 1. 데이터 중복 등 데이터가 유효한지 검사한다
    checkValid(req);

    // 2. 애그리거트를 생성한다
    SomeAgg newAgg = createSome(req);

    // 3. 리포지터리에 애그리거트를 저장한다
    someAggRepository.save(newAgg);

    // 4. 결과를 리턴한다.
    return createSuccessResult(newAgg);
}

응용 서비스가 이것보다 복잡하다면 응용 서비스에서 도메인 로직의 일부를 구현하고 있을 가능성이 높다

예)암호 변경은 Member 도메인의 핵심 로직이므로 도메인에서 구현한다

public class ChangePasswordService {

    public void changePassword(String memberId, String oldPw, String newPw) {
        Member member = memberRepository.findById(memberId);
        checkMember(member);
        member.changePassword(oldPw, newPw);
      }
}
public class Member {

    public void changePassword(String oldPw, String newPw) {
        if (!matchPassword(oldPw)) throw new BadPasswordException();
        setPassword(newPw);
    }

    // 현재 암호와 일치하는지 검사하는 도메인 로직
    public boolean matchPassword(String pwd) {
        return passwordEncoder.matchs(pwd);
    }

    private void setPassword(String newPw) {
        if (isEmpty(newPw)) throw new IllegalArgumentException("no new password");
        this.password = newPw;
    }
}

아래 코드처럼 응용 서비스에서 암호 변경을 구현하면 안된다

public class ChangePasswordService {

    public void changePassword(String memberId, String oldPw, String newPw) {
        Member member = memberRepository.findById(memberId);
        checkMember(member);

        if (!passwordEncoder.matchs(oldPw, member.getPassword())) {
            throw new BadPasswordException();
        }
        member.setPassword(newPw);
    }
}

도메인 로직을 도메인 영역과 응용 서비스에 분산해서 구현하면

Reference