블로그에 게시하는 위 글은 전체적인 내용 정리가 아닌
책을 읽으면서 새로 알게된 내용이나 제가 중요하다고 생각하는 내용을 정리한 글입니디.
사용자 - 표현 영역 - 응용 영역 - 도메인 영역
표현 영역
응용 영역
사용자가 요청한 기능을 실행하는 영역이자,
도메인 객체를 사용해서 사용자의 요청을 처리하는 영역
주로 아래와 같은 구조로 이루어져있다.
public Result doSomeFunc(SomeReq req) {
// 1. 리포지터리에서 애그리거트를 구한다.
SomeAgg agg = someAggRepository.findById(req.getId());
checkNull(agg);
// 2. 애그리거트의 도메인 기능을 실행한다.
add.doFunc(req.getValue());
// 3. 결과를 리턴한다.
return createSuccessResult(agg);
}
public Result doSomeCreation(CreateSomeReq req) {
// 1. 데이터 중복 등 데이터가 유효한지 검사합니다.
checkValid(req);
// 2. 애그리거트를 생성한다.
SomeAgg newAgg = createSome(req);
// 3. 리포지터리에 애그리거트를 저장한다.
someAggRepository.save(newAgg);
// 결과를 리턴한다.
return createSuccessResult(newAgg);
}
만약 위의 같은 구조가 아닌, 더 복잡한 로직이 들어가있다면
도메인 로직을 넣었나 확인해봐야한다.
또한 트랜잭션 처리도 이곳에서 한다.
→ 트랜잭션 범위에서 응용 서비스를 실행해야한다.
왜?
→ 코드 변경이 어려워진다
한 응용 서비스에 회원 도메인의 기능들 모두 구현
구분되는 기능별로 따로 구현 (추천)
한 개 내지 2~3개의 기능을 구현
클래스 수의 증가
코드 품질을 일정 수준으로 유지하는데 도움
중복이 생길 가능성 발생 (방지 가능)
public final class AggServiceHelper {
// Agg가 null이면 오류를 발생하는 로직
}
인터페이스가 필요할까?
→ 구현클래스가 여러개일 때에는 필요하다. 하지만 이런 경우는 매우 드물다.
인터페이스와 클래스를 따로 구현하게 되면
표현 영역말고 도메인, 응용 영역을 먼저 개발하면 응용 서비스 클래스가 먼저 만들어진다.
→ Mockito와 같은 테스트 도구를 사용하면 가짜 객체 사용 가능
메서드에서 파라미터를 전달 받는 방법
표현 영역에서는 애그리거트를 전체 리턴하기보다는 필요한 데이터만 뽑아서 리턴하는게 좋다.
파라미터 타입을 표현 영역과 관련된 타입을 사용하면 좋지 않음
(HttpServletRequest, HttpSession 같은)
서비스 메서드의 파라미터와 리턴 타입으로 표현 영역의 구현 기술 사용하지 않는게 좋다.
트랜잭션을 적극 사용 권장
커밋하고 예외가 발생하면 롤백하기 때문이다.
도메인 영역에서 발생시킨 이벤트를 처리하는게 응용 서비스의 역할 중 하나
도메인에서 내용이 바뀌면 이벤트를 발생시키는 코드를 구현할 수 있다.
표현, 응용 영역 두 곳 모두에서 수행 가능
보안 프레임워크를 제공해주지만 (ex. 스프링 시큐리),
이해도가 높지 않으면 직접 구현하는 것이 더 나을 수도 있다.
조회 기능은 트랜잭션을 필요로 하지 않는다.
그렇기 때문에 표현 영역 → 바로 도메인 레포지토리에 검색 가능