도메인 모델링
도메인 모델링을 할 때 모델을 구성하는 핵심 구성요소
, 규칙
, 기능
을 찾는 것이 가장 기본이며, 위 요소는 요구사항에서 출발합니다.
요구사항에 의해 도메인 모델을 점진적으로 발전시켜 나갈 수 있으며, 도메인을 더 잘 알게 되면서 중간에 모델에 대한 부분을 변경할 수 있습니다.
Entity 와 Value
요구 사항에서 도출한 도메인 모델은 크게 Entity와 Value로 구분되며, 잘 구분해야 도메인을 올바르게 설계하고 구현할 수 있습니다. 그러므로 둘의 차이를 명확하게 이해하는 것이 중요합니다.
Entity
Entity 의 가장 큰 특징은 식별자(identity) 가 있다는 점입니다. 식별자는 Entity 객체마다 고유합니다.
Value
Value 타입은 개념적으로 완전한 하나를 표현할 때 사용합니다. 예를 들어, 주문자 정보(주문자명, 주문자 이메일)에 대한 Value 타입은 다음과 같이 정의할 수 있습니다.
class Buyer(
name: String,
email: String,
) {
companion object {
fun init(name: String, email: String): Buyer {
return Buyer(name = name, email = email)
}
}
}
Buyer는 주문자
라는 도메인 개념을 표현하며, Value 타입을 사용하여 완전한 하나의 개념을 잘 표현할 수 있게 됩니다.
Value 타입은 두 개 이상의 데이터를 가져야 하는 것은 아니며, 의미를 명확하게 표현하기 위해 Value 타입을 사용하는 경우도 있습니다.
추가로 Value 타입을 위한 기능을 추가할 수 있다는 장점이 있습니다.
즉, 코드의 의미를 더 잘 이해할 수 있는데 도움이 됩니다.
Value 객체는 데이터 변경 시 기존 데이터를 변경하기보다 새로운 객체를 생성하는 방법을 더 선호합니다.
class Money(
val amount: Double,
val currencyCode: String,
) {
fun add(amount: Double): Money {
return init(currencyCode = this.currencyCode, amount = this.amount + amount)
}
companion object {
fun init(currencyCode: String, amount: Double): Money {
return Money(amount, currencyCode)
}
}
}
이렇게 데이터 변경을 제공하지 않는 타입을 immutable(불변) 타입이라 하며, 안전한 코드를 작성할 수 있기 때문에 Value 타입을 불변 타입으로 구현하는 것을 선호합니다.
참고로 불변 객체는 스레드에 안전하며, 참조 투명성(동일한 입력값에 대해 항상 동일한 출력값을 보장하는 특성)의 특징을 가지고 있습니다.
kotlin에서는 typealias
로 해당 필드가 어떤 용도인지 의미가 드러나도록 설정하기도 합니다.
typealias SerialNumber = String
도메인 모델 get/set method 지양
도메인 모델에는 get/set method를 습관적으로 추가하는 것은 도메인의 핵심 개념이나 의도를 코드에서 사라지게 만들기 때문에 좋지 않은 습관입니다. set method는 도메인 객체를 생성할 때 온전하지 않은 상태가 될 수도 있으므로, 생성자를 통해서 필요한 데이터는 모두 받도록 구현해야 합니다. set method는 클래스 내부에서 데이터를 변경할 목적으로 private 접근 범위로 사용하는 용도로 활용하는 것이 좋습니다.
불변 Value 타입을 사용하게 되면 자연스럽게 set method 는 구현하지 않게 됩니다.
도메인 용어
도메인 용어는 해당 값만 보고 어떤 의미인지 바로 알 수 있도록 정의하는 것이 중요합니다.
예를 들어, 상품 판매 상태(판매대기, 판매 중, 판매종료, 품절) 구현 시
enum class SaleStatus {
STATUS1, STATUS2, STATUS3, STATUS4
}
단순히 STATUS4
가 아닌 도메인에서 사용하는 용어를 최대한 코드에 반영한 OUT_OF_STOCK
와 같이 정의하는 것이 좋습니다. 이렇게 정의하면 코드의 가독성을 높여주고, 코드를 분석하고 이해하는 시간을 줄일 수 있게 됩니다.
enum class SaleStatus {
PRE_SALE, SALE, ENDED, OUT_OF_STOCK
}
에릭 에반스는 도메인 설계 시 용어의 중요함을 강조하기 위해 유비쿼터스 언어(Ubiquious Language)라는 용어를 사용했습니다. 도메인과 관련된 공통의 언어를 만들고, 모든 곳에서 같은 용어를 사용하게 되면 소통 과정에서 발생하는 용어의 모호함을 줄일 수 있을 뿐만 아니라 코드와 도메인 사이의 불필요한 해석 과정을 줄일 수 있기 때문입니다.
'개발' 카테고리의 다른 글
DDD - Aggregate (2) | 2024.09.22 |
---|---|
DIP 의존 역전 원칙 (0) | 2024.09.21 |
DDD - 도메인이란? (1) | 2024.09.19 |
TDD (테스트 주도 개발) (1) | 2024.09.18 |
동기/비동기 (0) | 2024.09.18 |