6.1 표현 영역과 응용 영역
응용 영역과 표현 영역이 사용자와 도메인을 연결해주는 매개체 역활을 한다.
표현영역
- 사용자의 요청을 해석한다.
사용자가 HTTP 요청을 표현 영역에 전달.
요청받은 표현영역은 사용자가 실행하고 싶은 기능을 판별하여 응용 서비스를 실행.
응용영역
- 사용자가 원하는 기능을 제공하는 서비스.
기능을 실행하는데 필요한 입력 값을 메서드 인자로 받고 실행 결과를 리턴.
응용 서비스 메서드가 요구하는 파라미터와 표현영역이 사용자로 전달받은 데이터 형식이 일치하지 않기 때문에 표현 영역은 응용 서비스가 요구하는 형식으로 사용자 요청을 변환한다.
사용자와 상호작용은 표현영역이 처리하기 때문에, 응용 서비스는 표현 영역에 의존하지 않는다
- > 단지 기능 실행에 필요한 입력 값을 받고 실행결과만 리턴하면 될 뿐.
( 사용자가 사용하는 디바이스, 방식 등에 구애 받지 않는다?)
6.2 응용 서비스의 역할
응용 서비스는 사용자가 요청한 기능을 실행하고, 그 요청을 처리하기 위해 리포지터리에서 도메인 객체를 가져와 사용한다.
응용 서비스의 주요 역활은 도메인 객체를 사용해서 사용자의 요청을 처리하는 것.
응용 서비스는 주로 도메인 객체 간의 흐름을 제어!
응용 서비스가 복잡하다면 응용 서비스에서 도메인 로직의 일부를 구현하고 있을 가능성이 높다.
( ex : 값 체크, 계산 등 )
응용 서비스는 도메인의 상태 변경을 트랜잭션으로 처리 해야 한다.
6.2.1 도메인 로직 넣지 않기.
도메인 로직은 도메인 영역에 위치하고 응용 서비스는 도메인 로직을 구현하지 않는다.
예를 들어 암호 변경 기능을 위한 응용 서비스는 아래와 같다.
public class ChangePasswordService{
public void changePassword(String memberId, String oldPw, String newPw){
Member member = memberRepository.findById(memberId);
checkMemberExists(member);
member.changePassworld(oldPw, newPw);
}
}
public class member{
public void changePassword(String oldPw, String newPw){
if(!matchPassword(oldPw)) throw new BadPasswordException();
setPassword(newPw);
}
}
ex) 기존 암호를 올바르게 입력했는지를 확인하는 것은 도메인의 핵심 로직이기 때문에 서비스 단에서 이 로직을 구현하면 안된다.
도메인 로직을 도메인 영역과 응용 서비스에 분산해서 구현하면 코드 품질에 문제가 발생함.
코드의 응집력이 떨어지고, 도메인 로직을 파악하기 위해 여러 영역을 분석해야 한다는 점.
여러 응용 서비스에서 동일한 도메인 로직을 구현할 가능성이 높아짐.
-> 코드 중복이 발생.
그만큼 소프트웨어의 가치가 떨어진다.
코드 중복을 줄이고 응집도를 높여야한다.
6.3 응용 서비스의 구현.
응용 서비스는 표현 영역과 도메인 영역을 연결하는 매개체 역할을 한다. 이는 디자인 패턴에서 파사드와 같은 역할을 한다.
** 파사드 log4j
6.3.1 응용 서비스의 크기
응용 서비스는 보통 다음의 두 가지 방법 중 한가지 방식으로 구현한다.
- 한 응용 서비스 클래스에 회원 도메인의 모든 기능 구현하기.
- 구분되는 기능별로 응용 서비스 클래스를 따로 구현하기.
한 모데인과 관련된 기능을 구현한 코드가 한 클래스에 위치하면,
중복 로직을 쉽게 제거할 수 있다는게 장점이고, 한 서비스의 크기가 커진다는 것이 단점이다.
( 코드 크기가 커지면 연관성이 적은 코드가 한 클래스에 함께 위치할 가능성이 높아진다. 결과적으로 관련 없는 코드가 뒤섞여 코드를 이해하는데 방해가 된다.
구분되는 기능별로 서비스 클래스를 구현하는 방식은 한개 내지 2~3개의 기능을 구현한다.
클래스 개수는 많아지지만 한 클래스에 관련 기능을 모두 구현하는 것과 비교해서 코드 품질을 일정 수준으로 유지하는 데 도움이 된다.
각 클래스별 필요한 의존 객체만 포함하므로 다른 기능을 구현한 코드에 영향을 받지 않는다.
중복코드가 발생할 가능성이 있는데 이 경우 별도 공통 로직으로 중복 방지를 한다.
( 예시 : 멤버서비스헬퍼 클래스를 만들어 멤버 널체크 )
6.3.2 응용 서비스의 인터페이스와 클래스
인터페이스의 필요 여부 논쟁이 된다.
인터페이스가 필요한 몇 가지 상황은 구현 클래스가 여러 개인 경우이다.
인터페이스와 클래스를 따로 구현하면 소스 파일만 많아지고, 전체 구조가 복잡해지므로 명확하게 필요하기 전까지는 좋은 선택이라고 볼 수 없다.
TDD로 표현 영역부터 개발을 시작한다면, 응용 서비스 인터페이스부터 작성하게 될 수 있다.
도메인 영역이나 응용 영역의 개발을 먼저 시작하면 응용 서비스 클래스의 가짜객체가 필요한데 이를 위해 인터페이스를 추가할 수 도있다.
6.3.3 메서드 파라미터와 값 리턴
스프링같은 경우 웹 요청 파라미터를 자바 객체로 변환하는 기능을 제공해서 파라미터가 두개 이상 존재하면 DTO 클래스를 만드는게 편리하다.
6.3.4 표현 영역에 의존하지 않기.
응용 서비스의 파라미터 타입을 결정할 때 주의할 점은 표현 영역과 관련된 타입을 사용하면 안된다.
( HttpServletRequest, HttpSession... 을 응용 서비스에 파라미터로 전달하면 안됨.)
-> 단독으로 테스트하기가 어려워 짐. 응용 서비스의 구현도 함께 변경해야 하는 문제. 응용 서비스가 표현 영역의 역할까지 대신해야 하는 상황이 벌어짐. ( 표현 영역의 응집도가 깨짐. )
6.3.5 트랜잭션 처리
스프링은 @Transactional을 사용하면 코드를 간결하게 유지할 수 있다.
6.4 표현 영역
- 사용자가 시스템을 사용할 수 있는 흐름을 제공하고 제어
- 사용자의 요청에 알맞은 으용 서비스에 전달하고 결과를 사용자에게 제공
- 사용자의 세션을 관리.
주된 역할은 사용자의 연결 상태인 세션을 관리하는 것.
웹은 쿠키나 서버 세션을 이용해서 사용자의 연결 상태를 관리한다.
세션 관리는 권한 검사와도 연결된다.
6.5 값 검증
표현 영역과 응용 서비스 두 곳에서 모두 수행 할 수 있다.
원칙적으로 응용 서비스에서 처리한다.
스프링 MVC는 Errors나 BindingResult를 사용함.
컨트롤러에서 하면 번잡한 코드를 작성해야 한다.
응용 서비스에서는 값 검증을 하나만 할 수도 있지만 여러 에러 코드를 모아 하나의 익셉션으로 발생시키는 방법도 있다.
표현 영역과 응용 서비스가 값 검사를 나눠서 수행하는 방법은
표현영역 : 필수 값, 값의 형식, 범위 등을 검증
응용서비스 : 데이터의 존재 유무와 같은 논리적 오류를 검증.
6.6 권한 검사
스프링 시큐리티 같은 프레임웤을 사용하면 유연하고 확장 가능한 구조를 가지고 있다.
권한 검사는 보통 다음 세곳에서 한다.
표현 영역, 응용 서비스, 도메인
표현 영역에서 검사는 인증된 사용자 여부.
-> 서블렛 필터
응용 서비스는 검사 로직을 직접 구현해야 한다.
6.7 조회 전용 기능과 응용 서비스
조회는 서비스에서 수행하는 추갖거인 로직이 없을 뿐더러 단일 쿼리만 실행하는 조회 전용기능이여서 트랜잭션도 필요하지 않다.
이 경우라면 굳이 서비스를 만들 필요 없이 표현 영역에서 바로 조회 전용 기능을 사용해도 문제가 없다.
'책 리뷰 > 도메인 주도 개발하기' 카테고리의 다른 글
8장 애그리거트 트랜잭션 관리 (0) | 2022.07.23 |
---|---|
9장 도메인 모델과 바운디드 컨텍스트 (0) | 2022.07.16 |
7장 도메인 서비스 (0) | 2022.07.16 |
도메인 주도 개발하기 - 2장. 아키텍처 개요 (0) | 2022.06.25 |
도메인 주도 개발하기 - 1장. 도메인 모델 시작하기 (0) | 2022.06.19 |