본 포스트 시리즈는 「도메인 주도 설계 철저 입문」책을 요약한 내용입니다.
이전 발행 글 보기
2024.09.02 - [DDD/도메인 주도 설계 철저 입문] - 도메인 주도 설계란? - 「도메인 주도 설계 철저 입문」 1장
2024.09.04 - [DDD/도메인 주도 설계 철저 입문] - 도메인 주도 설계란? - 「도메인 주도 설계 철저 입문」 2장 (1)
2024.09.05 - [DDD/도메인 주도 설계 철저 입문] - 도메인 주도 설계란? - 「도메인 주도 설계 철저 입문」 2장 (2)
2024.09.09 - [DDD/도메인 주도 설계 철저 입문] - 도메인 주도 설계란? - 「도메인 주도 설계 철저 입문」 3장 (1)
2024.09.11 - [DDD/도메인 주도 설계 철저 입문] - 도메인 주도 설계란? - 「도메인 주도 설계 철저 입문」 3장 (2)
04장 부자연스러움을 해결하는 도메인 서비스
서비스란
도메인 주도 설계에는 도메인을 위한 서비스(도메인 서비스)와 애플리케이션을 위한 서비스(애플리케이션 서비스) 두 가지 서비스가 있다. (애플리케이션 서비스는 6장에 나옴.)
도메인 서비스란
값 객체나 엔티티 같은 도메인 객체에는 객체의 행동을 정의할 수 있긴 하지만, 객체에 정의하면 부자연스러운 행동들이 있다. 예를 들면 시스템에 사용자명이 중복되면 안되는 규칙이 있을 때, 이 규칙을 User 클래스에 정의하면 다음과 같이 이상한 코드가 된다.
public class User {
private final UserId id;
private UserName name;
public User(UserId id, UserName name) {
(...생략...)
}
// 사용자명 중복 여부 확인
public boolean exists(User user) {
// 사용자명 중복을 확인하는 코드
return false;
}
}
위 코드가 이상한 이유는, User의 중복을 User 자신에게 물어야하기 때문이다. 이처럼, 부자연스러움을 해결해주는 객체를 도메인 서비스라고 한다. UserService라는 도메인 서비스에 중복 확인 기능을 구현한 다음 코드가 비로소 자연스러운 코드이다.
public class UserService {
public boolean exists(User user) {
// 사용자명 중복을 확인
(...생략...)
}
}
그리고 UserService를 사용해 사용자 중복을 확인하는 코드는 다음과 같을 것이다.
public class Program {
public static void main(String[] args) {
UserService userService = new UserService();
UserId userId = new UserId("id");
UserName userName = new UserName("naruse");
User user = new User(userId, userName);
// 사용자명 중복 확인 - 자연스러움
boolean duplicateCheckResult = userService.exists(user);
System.out.println(duplicateCheckResult);
}
}
도메인 서비스 남용은 금물
그러나 도메인 서비스를 남용하면 엔티티나 값 객체 같은 도메인 객체에는 Getter나 Setter밖에 남지 않게 된다. 예를 들어 다음 코드와 같이 사용자명 수정 메서드 정도는 User 엔티티가 가지고 있는 것이 적절하다. 도메인 객체는 단순히 데이터를 저장해두는 곳이 아니라 객체에 대한 규칙이나 정보를 제공해야한다는 것을 잊지 말아야 한다.
public class User {
private final UserId id;
private UserName name;
public User(UserId id, UserName name) {
(...생략...)
}
public void changeName(UserName name) {
if (name == null) {
throw new IllegalArgumentException("name cannot be null");
}
this.name = name;
}
}
도메인 서비스는 가급적 피하기
위의 중복 검사 기능처럼 도메인 서비스로 옮겨야만 하는 행위도 있지만, 도메인 객체에 구현할지 도메인 서비스에 구현할지 망설여진다면 가급적 도메인 객체에 구현하는 것이 좋다. 서비스를 남용하면 데이터와 행위가 단절되서 로직이 분산되기 쉽기 때문이다. 로직 분산은 곧 소프트웨어가 변화에 대응하기 어려워진다는 뜻이다.
도메인 서비스 남용은 금물
그러나 도메인 서비스를 남용하면 엔티티나 값 객체 같은 도메인 객체에는 Getter나 Setter밖에 남지 않게 된다. 예를 들어 다음 코드와 같이 사용자명 수정 메서드 정도는 User 엔티티가 가지고 있는 것이 적절하다. 도메인 객체는 단순히 데이터를 저장해두는 곳이 아니라 객체에 대한 규칙이나 정보를 제공해야한다는 것을 잊지 말아야 한다.
요약
1. 도메인 객체에 나타내면 어색해지는 행위들을 나타내는 객체를 도메인 서비스라고 한다. 2. 가급적이면 로직 분산을 막기 위해 도메인 서비스에 행위를 담지 않는 것이 좋다. |
'DDD > 도메인 주도 설계 철저 입문' 카테고리의 다른 글
레포지토리 구현 방법과 테스트 방법 - 「도메인 주도 설계 철저 입문」 5장 (2) (2) | 2024.09.30 |
---|---|
레포지토리란? - 「도메인 주도 설계 철저 입문」 5장 (1) (0) | 2024.09.30 |
엔티티의 생애주기와 도메인 객체 - 「도메인 주도 설계 철저 입문」 3장 (2) (0) | 2024.09.11 |
도메인 엔티티란? - 「도메인 주도 설계 철저 입문」 3장 (1) (1) | 2024.09.09 |
값 객체의 장점 - 「도메인 주도 설계 철저 입문」 2장 (2) (2) | 2024.09.05 |