도메인 주도 설계 책을 읽으면서 주관적인 생각들을 간단히 모아두었습니다.
1부
- (일부 유실..)
3장 - 모델의 구현과 연계
- 프로그래머가 곧 모델러다 / 코드를 작성하기 때문에 최종 결정자라고 볼 수 있다.
- 따라서 책임 의식을 가져야한다.
- 모델에 기여하는 모든 기술자(도메인 전문가, 개발자 등)는 프로젝트 내에서 수행하는 역할과 상관없이 코드를 접하는 데 어느 정도 시간을 투자해야한다.
- 코드를 통해 모델을 표현하는 법을 반드시 배워야한다.
- 모든 개발자는 모델에 관한 논의에 깊이 관여해야 하고, 도메인 전문가와도 적극적으로 커뮤니케이션 해야한다.
2부 모델 주도 설계의 기본 요소
4장 - 도메인의 격리
- 도메인에서 발생하는 문제를 해결하는 소프트웨어의 각 요소는 전체 소프트웨어 시스템의 극히 작은 부분으로 구성되어 있다.
- 그말은 극히 작은 부분외에 다른 부분들은 도메인 문제와 직접적으로 관련이 없다는 이야기다. 예를 들어, 화면에 뷰를 그리고, 데이터 베이스에 쓰기, 읽기 작업이나 화면 이동 등이 될 수 있고 이런 코드들은 도메인과 격리 시켜야 한다. 이와 같은 격리를 위한 매우 정교한 기법들이 나타났고, 그중 잘 알려진 것중 하나가 뒤에서 설명하는 것이 Layered Architecture 이다.
- Layered Architecture
- 계층화의 핵심 원칙은 ?
- 한 계층의 모든 요소는 오직 같은 계층에 존재하는 다른 요소나 계층상 아래에 위치한 요소에만 직접 의존한다는 의미이다. / 상위로 의사소통은 간접적인 메커니즘을 거쳐야한다.
- 일반적으로 사용자 인터페이스 계층 → 응용 계층 → 도메인 계층 → 인프라스트럭처 계층 으로 통하지만 상위 계층은 중간 계층을 생략하고 하위 계층에 직접 의존할 수 있다.
- 사용자 인터페이스 계층 : 사용자와 상호작용하는 책임을 가진다 간혹 외부 시스템이 사용자가 되는 경우도 존재한다.
- 응용 계층 : 도메인 객체가 문제를 해결하기 위해 다른 시스템의 응용 계층과 상효 작용할 수 있도록 도와준다. 오직 작업을 조정하고, 아래 위치한 계층에 포함된 도메인 객체의 협력자에게 작업을 위임한다.
- 도메인 계층 : 업무 개념, 업무 규칙, 상황에 대한 정보 등 비즈니스를 책임진다. 상태를 가지며 상태 저장과 관련된 기술의 세부사항은 인프라스트럭처 계층에 위임한다.
- 인프라스트럭처 계층 : 상위 계층을 지원하기 위한 일반화된 기능들을 제공한다. 메세지 전송, 도메인 영속화, UI 에 위젯을 그리는 것 등이 있고, 해당 계층은 아키텍처 프래임워크를 통해 네가지 계층에 대한 패턴을 지원하기도 한다.
- 특정 프로젝트에서는 사용자 인터페이스와 애플리케이션 계층을 명확히 구분하지 않기도 하며, 여러개의 인프라스트럭처 계층을 가지는 프로젝트도 존재한다.
- 중요한 점은 모든 프로젝트들이 도메인 계층을 분리한다는 점에 있다.
- 계층화의 핵심 원칙은 ?
- 아키텍처 프레임워크의 목적은 도메인 모델을 표현하고, 도메인 모델을 이용해 중요한 문제를 해결하는 구현을 만들어내는 데 있다.
- 하나의 강력한 프레임워크로 일률적인 해법을 모색하는 것이 아니라, 여러 프레임워크를 목적에 따라 선택적으로 사용해야한다.
- 프레임워크의 유용한 기능만 분별력있게 적용한다면 구현과 프레임워크의 결합을 줄이고, 차후 설계 의사결정을 좀더 유연하게 내릴 수 있다.
- 하나의 강력한 프레임워크로 일률적인 해법을 모색하는 것이 아니라, 여러 프레임워크를 목적에 따라 선택적으로 사용해야한다.
5장 - 소프트웨어에서 표현되는 모델
모델의 연관 관계
- 연관 관계를 쉽게 다루는 법 (현실은 다대다 로 연관관계가 있고, 양방향인 경우가 많아 일반적으로 구현과 유지보수를 어렵게 하는 경우가 있다)
- 탐색 방향을 부여한다
- 한전장를 추가하여 다중성(복잡함)을 줄인다.
- 중요하지 않은 연관관계를 제거한다.
- 즉, 가능한 관계를 제약하는 것이 중요하다.
- 조지 워싱턴이 대통령이었던 나라가 어디입니까 ? → 이렇게 물어보는 경우는 없음 즉 의미 없는 관계일 수 있음
- 1970년 미국의 대통령은 누구였나요 ? → 국가 아래 대통령이 존재한다고 연관 관계를 추정해볼 수 있음
- 한 나라에는 한번에 한 명의 대통령만 존재한다는 사실 관계도 알 수 있게 됨
- 제약 조건은 항상 모델에서 표현되어야 한다.
- 모델을 표현하는 3가지 패턴 - ENTITY, VALUE OBJECT, SERVICE
- 모델에 포함된 연관관계가 적고 단순할수록 유지보수가 용이하고 더 나은 모델이라고 이야기 함.
ENTITY
- 근본적인 개념 : 객체의 생명주기 내내 이어지는 추상적인 연속성이며, 추상적인 연속성은 여러 형태를 거쳐 전달 된다는 것, 객체의 식별성으로 정의할 경우 그 객체를 ENTITY 라 부른다.
- 나 라는 사람의 정보가 어떤 서비스들에 전달되어 변형되다 보면 객체는 알아 볼 수 없을 만큼 변형될 수 있는데 객체를 나라고 식별할 수 있다면 ENTITY 라고 할 수 있음
- 식별성이 필요한 이유는 ?
- 객체를 추적하기 위해, 즉 객체를 추적해야하는 니즈가 있다면 ENTITY 로 활용해야한다.
- 추적? → 연속성을 지닌다는 말 → 어플리케이션 전반적으로 사용된다 → 계정, 주요 도메인 등
- 책에서는 도시, 자동차, 복권, 은행 거래 등을 예시로 들고 있음.
- 경기장 아무나 앉을 수 있는 일반석과 지정석을 생각해보자
- 추적? → 연속성을 지닌다는 말 → 어플리케이션 전반적으로 사용된다 → 계정, 주요 도메인 등
- 객체를 추적하기 위해, 즉 객체를 추적해야하는 니즈가 있다면 ENTITY 로 활용해야한다.
- 자바에서 동일성(==) 으로 모든 객체가 식별성을 지닌다고 생각할 수 있지만, 언어에서 제공하는 기능으로 대체할 수 없다.
- 코틀린의 데이터 클래스는 식별성을 지니기 어렵다.(값으로 판단하기 때문) 식별성을 만들어내는 수단이 있다면 문제 없다.
VALUE OBJECT
- 개념적 실병성을 갖지 않으면서 도메인의 서술적 측변을 나타나는 객체를 VALUE OBJECT 라 한다.
- 시장에서 물건을 사고 거스름돈을 받는데 동전이 어디 공장에서 만들어졌는지 의미를 지니지는 않을 것이다.
- 예를 들어 주소(address) 는 ENTITY 일까 VALUE OBJECT 일까 ?
- ENTITY 처럼 보일 수 있지만, 도메인에 따라 다르게 해석될 수 있음 회사에서 물건을 구매하고, 동료도 가은 물건을 회사에서 구매하면 두 사람이 주소는 같지만 이때는 회사 입장에서 두 사람이 같은 곳에 있다는 의미는 가치를 지니지 못하고 VALUE OBJECT 로 생각할 수 있다.
- VALUE OBJECT 는 다양한 ENTITY 가 조합되어 VALUE OBJECT 를 표현할 수도 있고 VALUE OBJECT 끼리 조합되어 표현되기도 한다.
- 지도 서비스에서 관광지 추천을 하는 경우 여러개의 도시, 고속도로 등의 (ENTITY) 가 모여 Router(VALUE OBJECT) 를 만들어 낼 수 있다.
- e.g. 사람은 ENTITY 로 표현 / 사람의 이름은 VALUE OBJECT 로 표현될 수 있음
- 불변적을 기본으로 다루고(경우에 따라 객체의 사본을 만드는 방식도 괜찮다.), 식별성 부여를 지양하며, 복잡성을 피하자.
- 성능이 중요한 경우(자주 변경되거나 생성, 삭제에 비용이 큰 경우) / 통신 부하가 낮은 경우 / 불변성이 지켜지는 경우
- Copy 하지 않고, 한 인스턴스를 레퍼런스로 공유할 수도 있지만, 상황에 맞게 사용하는 것을 권장함
- 시스템에 따라 달라짐
- VALUE OBJECT 끼리는 관계를 가지는 것을 지양하자.
- 식별성이 없기 때문에 그저 같은 값을 지닌 객체를 가리키고 있을 뿐이다.
- 연관 관계를 가지면 ENTITY 는 아닐지 고민해보자.
- 파악하지못한 식별성이 남아있을 수 있다.
SERVICE
- 도메인의 개념 가운데 객체로는 모델에 어울리지 않는 것들이 있고, 이를 표현하기 위해 사용한다.
- 잘 만들어진 서비스는 아래의 특징을 가진다.
- 연산이 ENTITY, VALUE OBJECT 의 일부를 구성하는 것은 아니지만, 도메인 개념과 관련돼 있다.
- 인터페이스가 도메인 모델의 외적 요소의 측면에서 정의된다.
- 연산이 상태를 갖지 않는다.
- 상태를 갖지 않는다는 것은 클라이언트가 특정 SERVICE 인스턴스의 개별 이력과는 상관없이 SERVICE 의 모든 인스턴스를 사용할 수 있다는 의미이다
- 부수효과를 발생할 수도 있다는 의미
- SERVICE 는 도메인 계층에서만 사용되는 것은 아니다.
- 여러 계층에서의 SERVICE
- 도메인 : 객체간의 상호 작용(Account, Ledger) / 이체 결과 확인 정보 제공
- 응용 : 입력 내용을 암호화 / 인프라스트럭쳐 서비스를 이용한 알림 통지 등의 결정 / 이체 처리를 위한 도메인 서비스로 메세지 전송
- 인프라스트럭처 : 통지 서비스(Application 이 지정한 곳으로 이메일, 우편 등 알림을 보냄)
- 도메인 로직이 응용 계층까지 스며드는 것을 막기 위해 도메인 서비스를 적절히 도입하면 계층 간의 경계를 선명하게 하는데 도움이 될 수 있다.
Module
- 왜 모듈이 필요할지 ?
- 인지적 과부화 때문에, 이는 곳 유지보수에 직접적으로 영향을 준다.
- 모듈을 바라보는 2가지 측면
- 모듈에 들어가서 세부사항을 보는 관점
- 모듈끼리의 관계를 보는 관점
- 리팩터링을 많이 하는 개발자도 프로젝트 초기에 생각해둔 모듈 구조에 만족하는 경향이 있다
- 지속적으로 변경되어야 한다. 그 누구든.
- 새로운 도메인 지식을 알게 되어 모듈에도 반영하면 풍부하게 활용될 수 있다.
- 관련 있는 개념들을 모듈에 담자 → 종종 모듈간의 결합도가 낮아지는 경험을 할 수 있는데, 그렇게 되지 ㅇ낳는다면 먼저 모델을 변경해서 얽혀 있는 개념들을 풀어낼 방법을 찾아보거나, 미처 못보고 지나친 개념이 있는지 찾아보자.
- 모듈의 이름도 당연히 유비쿼터스 언어에서 채택되어야한다.
- 인프라스트럭쳐(프레임워크) 주도 패키지화를 지양해야하는 이유는 ?
- 프레임워크의 분할 관례에 개념적으로 붙어 있어야 하는 요소들이 떨어져있게 되어 코드에서 모델이 표현되지 않을 수 있음
- 프리임워크 분할 관례에 따리기 때문에 모델을 의미있는 조각으로 나누는 능력이 퇴색되게 된다.
- 단순하게 유지하자
- 필수 혹은 실질적으로 개발에 도움이 되는 최소한의 분할 규칙만 사용하자.
패러다임이 혼재할 때(객체 지향, 룰 기반, 관계형 그외의 패러다임들) 도메인 주도 설계 고수하기
- 여러 패러다임에서 사용할 수 있는 모델을 유비쿼터스 언어를 통해 표현하자. 두 환경 사이에 벌어진 틈을 메우는데 도움이 될 것이다.
- 패러다임에 맞는 모델 개념을 찾는 것도 방법이다. 다만 이 경우도 유비쿼터스 언어에 의지한다.
- 새로운 개념이 나온다면 보통 관련자들이 이야기하며 용어를 만들어내고 명명해왔기 때문에, 커뮤니케이션을 적극적으로 하자라고 해석되는 것 같다.
6장 도메인 객체의 생명주기
- “도메인 객체의 핵심은 아래와 같고, 책에서는 3가지 패턴(AGGREGATE, FACTORY, REPOSITORY)을 이용해 해결책을 제시
- 불변(무결성)”을 어떤식으로 관리할 것이냐
- 생명주기 관리의 복잡성으로 모델이 난해해지는 것을 방지할 것이냐
7장 언어의 사용(확장 예제)
- 복잡한 문제는 위에서 이야기한 3가지 패턴을 종합적으로 사용해야 해결이 가능함.
- 운송 시스템 예시로 흐름은 아래와 같다(이미 어느정도 완성된 모델을 이용해 예제를 설명중)
- 도메인 격리 시키기
- 아래와 같이 크게 3가지 대표적인 기능이 있고, 어플리케이션 계층이 아닌 도메인 계층해서 이루어져야함
- 추적 절의 : 특정 화물의 과거와 현재 처리 상태 접근
- 예약 기능 : 새로운 화멸을 등록하고 등록된 화물 처리를 준비
- 이벤트 로그 : 각 화물들의 처리 내역을 기록
- 아래와 같이 크게 3가지 대표적인 기능이 있고, 어플리케이션 계층이 아닌 도메인 계층해서 이루어져야함
- ENTITY, VALUE OBJECT 모델 구분하기(모델링 작업)
- 고객(Customer) - 고객을 식별해야하니 ENTITY 이고, 도메인 전문가와 함께 무엇을 식별자로 둘 것인지 논의가 필요하다.
- 화물(Cargo) - 우리는 두 개의 동일한 컨테이너를 서로 구별할 수 있어야 하기 때문에 당연히 ENTITY 이다.
- 그리고 식별자는 고객이 화물이 어디에 있는지 확인하는데 사용되고, 고객이 아닌 내부적으로도 다양하게 활용될 것이다. Public 한 식별자를 가진다
- 이벤트 처리(Handling Event) & 운송수단 이동(Carrier Movement)
- 개별 이벤트를 토대로 처리 상황을 알아 낼 수 있기 때문에 ENTITY 에 해당한다.
- 또한 도메인 전문가와 논의를 하며 화물의 식별자와 완료 시간, 화물 유형을 조합하면 이벤트를 유니크하게 식별할 수 있다는 것을 알게 되었다. 이를테면 화물은 동시에 적재하면서 하역하지 못한다는 의미이다.
- 개별 이벤트를 토대로 처리 상황을 알아 낼 수 있기 때문에 ENTITY 에 해당한다.
- 위치(Location)
- 책에서는 VALUE OBJECT 로 구분
- 특정 위치들의 이름이 같다고 해서 같은 위치로 볼 수 는 없기 때문에 내부 식별자는 가지고 있을 것이다. A 의 목적지가 부산, B 의 목적지가 부산인 경우 같은 부산처럼 대체할 수도 있다.
- 책에서는 경도 위도가 식별자의 하나가 될 수 있지만 아주 실용적인 방법은 아니라고 설명. → 그 이유가 현행 시스템의 목적에 경도 위도가 맞지 않다고 하는데, 세월이 지나 지금은 표준처럼 활용되는 게 아닐까 싶기도 하다.
- 특정 위치들의 이름이 같다고 해서 같은 위치로 볼 수 는 없기 때문에 내부 식별자는 가지고 있을 것이다. A 의 목적지가 부산, B 의 목적지가 부산인 경우 같은 부산처럼 대체할 수도 있다.
- 책에서는 VALUE OBJECT 로 구분
- 배송 이력(Delivery History)
- 배송 이력은 서로 대체할 수 없기 때문에 ENTITY 로 봐야한다. 다만 화물과 일대일 관계에 있으므로 배송 이력 자체의 식별성은 없다. 배송 이력 식별성은 그것을 소유하고 있는 화물에서 가져온 것이다.
- 이는 곳 이후에 AGGREGATE 할 때, 화물이 루트가 되고, 배송 이력은 루트를 통해서만 가져올 수 있다는 의미로 해석할 수 있다.
- 배송 이력은 서로 대체할 수 없기 때문에 ENTITY 로 봐야한다. 다만 화물과 일대일 관계에 있으므로 배송 이력 자체의 식별성은 없다. 배송 이력 식별성은 그것을 소유하고 있는 화물에서 가져온 것이다.
- 배송 명세(Delivery Specification)
- VALUE OBJECT
- 명세가 가지고 있는 도착 시간 이라는 것이 화물의 도착 시간이니 화물에 의존적인 VALUE OBJECT 로 볼 수 있는데, 명세라는 것이 배송 이력의 상태를 표현한 것으로, 충분히 식별 가능하다는 판단을 내릴 수 있지 않을까 생각도 든다.
- VALUE OBJECT
- 역할과 그외 속성들..
- 역할은 VALUE OBJECT 로 연관 관계의 표현이 다른 객체로 충분히 대체 가능하다. 그저 연관 관계를 표현하기만 하면 된다. 식별성을 가질 필요가 없다.
- 시간/날짜 등 속성도 VALUE OBJECT 이다.
- 도메인 연관 관계 설계
- 내가 가지고 있는 역할의 지식만 포함하자.
- 순환 참조는 필요에 의해서만 신중하게 사용하자.
- 설계상의 타협점은 구현의 단순함과 성능 사이에서 균형을 이룬다.
- 둘다 놓치는 일은 없도록 하자. 가령 구현도 단순하지 않고 성능도 떨어지는 일 말이다.
- AGGREGATE 의 경계
- 앞서 이야기 했지만 AGGREGATE Root 는 꼭 ENTITY 만 되어야 하는 것은 아님
- AGGREGATE Root : Customer, Cargo, Handling Event, Location, Carrier Movement
- Repository 선정
- 우선 다양한 역할을 하는 고객(선적인, 수하인 등)을 가져오기 위한 Customer Repository 가 필요하다.
- 또한 화물의 목적지를 지정하고 위치를 찾아볼 수 있도록 Location Repository 도 만들어야한다.
- 어떤 운송 수단을 이용하여 이동되고 있는지 알려주기 위해 Carrier Movement Repository 도 필요하다.
- 또한 Customer 에게 어떤 화물이 적재되었는지 알려줘야하기 때문에 Cargo Repository 도 필요하다.
- 화물이 여러개일 수도 있다.
- Aggregate 내에 Repository 는 존재하지 않는다. & ENTITY 면서 AGGREGATE 의 루트의 복사는 신중하게 결정하자.
- 도메인 격리 시키기
- CheatSheet : Domain Layer 에 정의되지 않는 모델이면 값 객체로 의심해보면 좋을듯
- 모듈 이름은 팀 언어에 기여하고, 해당 모듈만 보고 대략적인 흐름이 이해가 되어야 한다. (직관적으로 분할 되어 있어야 한다.)
- 책에서는 고객 / 해운 / 결제 모듈을 보여주고 “고객을 위해 해운 업무를 수행하기 때문에 결제를 요구할 수 있다” 정도로 설명한다.
- 두 시스템의 연계
- 7장에서 중요한 항목으로 느껴짐 (현실 세계에서 빈번히 일어나고 있는 일중 하나)
3부
8장 더 심층적인 통찰력을 향한 리팩터링
- 가장 중요한 일은 도메인 전문가의 섬세한 관심사를 포착하고, 효과적인 설계를 이끌어줄 명확한 모델을 발견하는 것
- 유용한 모델을 성공적으로 개발하기 위해 명심해야할 3가지 항목
- 정교한 도메인 모델은 만들 수 있고, 노력을 들일 만한 가치가 있다.
- 해당 도메인을 학습하는 개발자와 도메인 전문가의 긴말한 참여와 반복적인 리팩터링 과정 없이 유용한 모델을 개발하기란 쉽지 않다.
- 유용한 모델을 효과적으로 구현하고 사용하려면 정교한 설계 기술이 필요할지도 모른다.
- 유용한 모델을 성공적으로 개발하기 위해 명심해야할 3가지 항목
- 리팩터링 ?
- 미래를 예측해야하는 부단감에서 해방할 수 있도록 결정을 미룰 수 있는 리팩터링이 중요한데, 리팩터링을 다루는 많은 문헌에서 코드의 가독성 등의 기계적인 변경에 초점을 맞추고 있음.
- 심층 모델이란 도메인의 피상적인 측면을 배제하고 도메인 전문가의 주요 관심사와 가장 적절한 지식을 알기 쉽게 표현하는 모델이다. 이 정의가 추상화를 의미하는 것은 아니다.
- 심층 모델이 추상적인 요소들을 포함하지만, 문제의 핵심을 표현하는 구체적인 요소도 포함될 수 있다.
도약
- 리팩토링을 위한 통찰력은 어느 순간 갑자기 떠오른다.
기본에 집중하자
- 모두가 이해할 수 있는, 유비쿼터스 언어를 만드는 일에 집중하자.
- 중요한 도메인 개념으 조사하고, 모델로 표현하고, 유연해지도록 설계하고 정제하자.
9장 암시적인 개념을 명확하게
- 개발자들이 토의 중에 단서를 얻거나 설계상에 암시적으로 존재하는 개념을 인지하면 도메인 모델과 관련된 코드를 대량으로 변환하게 되며, 그 후 하나 이상의 객체와 객체 간의 관계를 활용해 모델 내에 해당 개념을 명확하게 표현하게 된다.
- 성공적인 도약은 반복적인 래팩터링 과정을 거치며, 할당된 책임을 조정하고, 다른 객치와의 관계를 변경하며, 심지어 이름도 몇번이나 수정이 필요할지 모른다.
- 개발자와 도메인 전문가가 설계상에 표현돼 있지 않은 어휘를 사용하고 있다면, 위험한 경고일 수 있다.
암시적인 개념을 명확하게 하는 방안들.
- 언어(커뮤니케이션)에 귀를 기울이자
- 어색한 부분을 조사하자
- 필요한 개념이 항상 언어에 드러나 있을 것이라 보장하기는 어려움 → 먼저 어색한 부분이 없는지 확인하는 단계도 필요하다.
- 설계상 가장 어색한 부분을 골라서 조사해보자.
- 모순점을 깊이 있게, 진심으로 고민하자.
- 서적을 참고하자
이자 수익 예제도 이해하는데 난이도가 있는 편
- 이쯤해서 드는 생각
- 실제로 대출, 이자가 도메인인 회사를 가면 느끼는 느낌의 가벼운 수준이 아닐지 ..? 현실 문제를 해결하는 것은 훨씬 어려운 일이 아닐까 ?
동네걷기 DDD 를 적용한다면 ?
- 우리는 도메인 전문가와 어떤 대화를 나누게 될까? - 논의거리
- 회사 관련 내용이라 생략
새로운 경험의 축적 & 지식탐구를 거쳐 훌륭한 아이디어가 떠오르고, 기존의 결과를 크게 바꾸게 될 것이다. 너무 기존의 아이디어에 집착하지 말자.
명시적으로 표현해야할 프로세스와 숨겨야 할 프로세스를 구분하는 기법은 ?
- 도메인 전문가가 이야기 하고 있는 프로세스인가 혹은 단순히 컴퓨터 프로그램상의 메커니즘의 일부인지 확인하면 된다.
SPECIFICATION (명세) 패턴
- 책에서 이야기 하는 SPECIFICATION 의 기본적인 컨셉은 다른 객체에 대한 제약조건을 기술하는 것.
- 다른 객체가 SPECIFICATION 에 명시된 기준을 만족하는지 검사할 수 있는 것
- 검증(Validation) 용도
- 선택(또는 질의) 용도
- 예를 들어 Invoice(송장)에서 계정이나 정책 데이터베이스에 직접 접근한다면, Invocie 가 지불 요청(Invoice 의 기본적인 책임)과는 무관한 객체들과 결합될 수 있기 때문에, 이런 경우 Delinquent Invoice Specification 을 생성하고 Invoice 를 평가한 후 제거하므로, 특정 평가 정보를 Delinquent Invoice Specification 안에 포함할 수 있다.
- 아직 존재하지 않는 객체에 기준을 명시해서 생성하는데 SPECIFICATION 을 사용할 수 있다.
- 장점은 ?
- SPECIFICATION 을 사용한 인터페이스는 생성 규칙에서 명시적으로 체크되기 때문에 연산의 세부사항을 직접 이해하지 않고도 결과물을 예상할 수 있다.
- 장점은 ?
- 기존에는 프로시저를 많이 사용했기 때문에, 코드 언어 레벨에서 활용하는 방식을 지향하는 것으로 이해되는 듯하다.
타 팀과 협업하는데, 서로 구현에 의지해야하는 상황이라면 ?
- 리스크와 리소스를 줄이기 위해 인터페이스 기반으로 소통하자.
10장 유연한 설계(Supple Design)
소프트웨어가 비교적 깔끔하게 설계돼 있지 않다면 개발자들은 코드를 건드리는 것조차 두려워하며, 뭔가를 망가트릴지도 모르는 상황으로 인해 변경을 덜 하게 되고, 이는 악순환 될 수 있음 → 이런 취약성을 먼저 해결하자.
- 과도한 엔지니어링이 유연성이라는 명목으로 정당화 되어 왔음. 그러나 너무 과도한 추상 계층과 간접 계층이 존재하면 유연성에 방해가 됨.
의도를 드러내는 인터페이스
- 인터페이스에서 명확하게 의도를 드러내지 못한다면 → 사용하는 쪽에서는 구현체를 살펴봐야하는 어려움이 생긴다.
- 앞으로 코드를 읽는 모든 개발자들은 비슷한 고통을 감내해야할 것이다.
- 인지과부화가 걸려 코드와 힘겨운 투쟁을 벌여야할지도 모른다.
- 수행 방법에 대해 언급하지 말고, 결과와 목적만을 표현하도록 클래스와 연산의 이름을 부여하자.
- 개발자가 내부를 이해해야 할 필요성이 줄어든다.
SIDE-EFFECT-FREE Function(부수효과가 없는 함수)
우리가 잘 알고 있는 개념으로 DDD 에서도 설명하고 있다.
연산은 크게 명령(Command), 질의(Query) 라는 두가지 범주로 나눌 수 있다.
- 명령은 변수의 값을 변경하는 등의 작업을 통해 시스템 상태를 변경하는 연산
- 질의는 변수 안에 저장된 데이터에 접근하거나, 저장된 데이터를 기반으로 계산을 수행하여 시스템으로 정보를 얻는 연산
부수효과는 의되하지 않은 결과를 의미하기도 하지만, 컴퓨터 과학에서는 시스템의 상태에 대한 영향력을 의미하기도 한다.
- 다수의 규칙에 따라 상호작용하거나, 여러 가지 계산을 조합하면 결과를 극도로 예측하기 어려워진다.
- 연산 자체도 이해해야하지만, 연산이 호출하는 다른 연산들의 구현도 이해해야한다. 고구마 줄기 처럼..
- 세부사항을 이해해야한다 ? 인터페이스를 추상화로 얻을 수 있는 유용성에 재한이 생긴다.
- 함수는 여러번 호출해도 매번 동일한 값을 반환한다. - 멱등성 & 보통 순수 함수라고도 부르지만 책에서는 함수로 표현한다.(X → Y)
- 연산 자체도 이해해야하지만, 연산이 호출하는 다른 연산들의 구현도 이해해야한다. 고구마 줄기 처럼..
부수효과를 지향할 수 있는 방법들?
- 명령과 질의를 엄격하게 분리하자. 변경을 발생시키는 메서드는 도메인 데이터를 반환하지 않아야 하고, 가능한 단순하게 유지하자. → 질의 해서만 반환 값을 가지자.
- 기존 객체를 변경하지 않고도 문제를 완화할 수 있다. 명령과 질의를 분리하기 어렵다면, 연산의 결과를 표현하는 새로운 VALUE OBJECT 를 생성해서 반환하자. → 생명주기를 신중하게 통제해야하는 ENTITY 와 달리 VALUE OBJECT 는 질의에 대한 응답으로 생성하고 반환후, 잊어버리자.→ Reference 로 사용을 지양하자.
Assertion(단언)
Assertion 을 이용하여, 호출되는 연산에서 보장하는 결과를 기술하자. 사후조건(연산의 부수효과 - 시스템에 변경을 일으키는 것)이 유요하기 위해 총족되어야 하는 조건들을 처리하자.
동료들이 의도된 Assertion 을 추측할 수 있게 인도하고, 모순된 코드를 작성하는 위험을 줄이는 응집도 높은 개념이 포함된 모델을 만들기 위해 노력하자.
Contextual contour(개념적 윤곽)
- 유사한 개념을 한 곳으로 모으고, 관리하자
- 기능 / 상태를 명확히 구분하자
Standalone class (독립형 클래스)
- 의존성이 하나라면 2개의 책임을 개발자가 이해해야 한다는 것을 의미함.
- 결합도를 낮추는 것은 개발의 기본 소양이자 원리임. 가능한 결합도를 낮추기 위해 노력하자. 현재 상황과 맞지 않는 개념이 있다면 과감히 제거하자.
- 모듈화를 한다해도 모듈내 복잡도가 높아지면 개발자에게 부담이 된다.
- 같은 모듈이라면 그나마 덜 부담스럽고, 접근제어자를 잘 챙겨보자.
- 복잡도가 높은 클래스가 있다면, 단일 클래스로
Closer Of Operation(연산의 닫힘)
- 프리미티브 타입만을 사용해서 인터페이스를 사용하면 위에서 이야기한 INTENTION-REVEAILING-INTERFACE 을 표현하기 어려움 → 당연한 이야기가 아닐까 싶었는데, 다른 고려할 사항이 있었나..?
- 너무 불필요한 개념이 인터페이스에 노출되는 것을 염두해둔것인지?
- 특정 유형의 객체 집합(예: Money객체)이 있고 이에 대한 연산(예: 덧셈, 뺄셈)을 수행하면 결과도 Money객체여야 한다.
- 일반적으로 VALUE OBJECT(값 객체)에 많이 활용됨
선언적 설계
- "무엇을 할 것인가"에 집중하고, "어떻게 할 것인가"는 감춤. by ChatGPT
- 도메인 규칙이나 제약조건을 코드로 명시적으로 표현. by ChatGPT
도메인 특화 언어 (DSL)
- Kotlin 에서 제공하는 DSL 형태로 많이 활용하고 있는데, Swift 도 비슷하게 제공되는지 ?
- 디자인 시스템 ?
- 이벤트 시스템 ?
- 스킴 프로그래밍
- Rootage ?
- 표현의 언어가 달라도, 도메인 지식을 충분히 활용할 수 있음
- Rootage ?
선언적인 형식의 설계
DDD 의 선언적 의미 : 비즈니스 규칙이나 요구사항을 코드에 명시적으로 표현해서, 코드만 봐도 도메인 개념이 드러나게 하는 것
- 논리 연산을 이용한 SPECIFICATION 조합 (AND, OR, NOT)
- 여러 개의 SPECIFICATION 을 조합해서 사용하면 유용한 상황들에 사용하자
- paint mixin, 강화 container 예시
- 여러 개의 SPECIFICATION 을 조합해서 사용하면 유용한 상황들에 사용하자
- 포섭 관계(Subsume relation)
- 더 엄격한 SPECIFICATION 은 덜 엄격한 SPECIFICATION 을 포함한다.
- 새로운 SPECIFICATION 을 만족하는 임의의 대상은 기존의 SPECIFICATION 역시 만족시키는 경우
- 새로운 SPECIFICATION 은 기존의 SPECIFICATION 을 포섭한다 라고 한다.
- A → B 라고 표현할 수 있으며 A 가 참이면 B 또한 참이다. (A 가 더 엄격한 SPECIFICATION 인 경우)
- 책에서 이야기 하는 예시인 화학물질에 적절한 컨테이너를 찾아야 하는 요구사항에 잘 어울리는 것 같다.
받음각(?) - 비행기가 상승 하강 할 수 있는 각도을 의미
거대한 시스템을 가리키며 “자 이제 이 시스템을 유연하게 만들어 봅시다” 라고 말하는 것으로는 충분하지 않다. 다양한 기법을 알고 있더라도 설계 목표를 달성하기란 굉장히 어려운 일이다.
- CQRS 하자
- 대출 관련 예시 - 도메인을 깊게 이해하고, 잘게 쪼개진 모델을 통해 다양한 유즈케이스에 대응 가능하개 됨.
- 예시의 흐름
- 사이드 이펙트 분리하고 (CQRS)
- 복잡한 로직은 VALUE OBJECT 로 캡슐화
- 기존 객체의 상태를 변경하는 로직이 제거되었기 때문에 자유롭게 함수들을 호출하고 결합할 수 있음
- 이 과정에서 함수들도 잘게 나눠지고 한가지 기능만 수행하리라 기대할 수 있게 됨.
- 위 과정으로 모델 간의 결합도가 낮아지게 됨. (최소한의 관계만 맺고 있음)
- 독립적이며, 물리적인 코드량도 줄어들어 쉽게 이해할 수 있게 됨
- 예시의 흐름
11장 분석 패턴의 적용
분석패턴 ?
- 업무 모델링 과정에서 발견되는 공통적인 구조를 표현하는 개념의 집합이다.
- 단 하나의 도메인에 대해서만 적절할 수 있고, 여러 도메인에 걸쳐 적용이 가능할 수도 있다.
'한달에 교양 책 한권' 카테고리의 다른 글
| 위대한 기업에 투자하라 (0) | 2026.01.11 |
|---|---|
| 최고의 프롬프트 엔지니어링 강의 (0) | 2025.03.22 |
| 올웨더투자법 feat.판교불패 (0) | 2025.03.01 |
| 도메인 주도 설계란 무엇인가? (0) | 2025.02.10 |
| 팀워크의 부활 (4) | 2024.11.24 |