도메인 주도 설계
Eric Evans의 책에서 처음 소개된 설계법
복잡한 도메인을 해결하는 목적의
소프트웨어를 우선순위로 해결해나가는 방법
도메인 주도 설계
Domain-Driven Design
도메인 주도 설계 프로세스
Domain-Driven Design Process
도메인 분석
Bounded
Context
엔터티, 집합체,
서비스 등 정의
계층 설계
도메인 모델
Bounded
Context
엔터티
사용자
인터페이스
유비쿼터스
언어
Context
map
값 객체
Value Object
응용
프로그램
Shared
Kernel
집합체
도메인
계층
기타
서비스
인프라
기타
도메인의 구성요소를 개념적으로 표현한 것
SW 전문가와 도메인 전문가가 만드는 것
도메인에 대한 이해가 필수!
어떤 특정한 다이어그램이 아니라 다이어그램이 전달하고자 하는 아이디어
내적 일관성이 없는 모델은 아무런 의미가 없다
도메인 모델
Domain Model
도메인 모델
Domain Model
예시: 영화 예매 시스템
Reservation 영화 예매 정보
Movie 영화 정보
Screening 상영 정보
AudienceName 관객이름
ReservationItem 예매 상품 정보
영화 예매 정보는 영화 정보ID, 상영 정보, 관객이름, 예매상품
정보를 갖는다
도메인 모델
Domain Model
Reservation Model
(이거보다 훨씬 풍성해져야 한다)
Reservation
ID
MovieID
ScreeningID
AudienceName
ReservationItems
빌딩 블록
엔터티
Entity
소프트웨어가
여러 과정을 거치는 동안에도
동일한 값을 유지하는 식별자를
지닌 유형의 객체
빌딩 블록
Building Block
값 객체
Value object
개념적 식별성이 없는,
어떤 특징을 묘사하는 객체
한번 만들어 지면
바뀌지 않는 객체
집합체 Aggregate
생명주기를 공유하는 데이터 집합
일관성을 유지해야 될 객체들을
묶어 놓은 것
빌딩 블록
Building Block
Root Entity
접근 범위에 있는
가장 상위 Entity
Aggregate은 Root Entity를 통해서만 외부에서 접근 할 수 있다
빌딩 블록
Building Block
집합체의 중요성
연관 관계를 줄이면서 복잡도가 감소한다
많은 도메인 모델을
간단하고 이해 가능한 수준으로
만들어 줄 수 있다
빌딩 블록
Building Block
Movie Aggregate
<<Entity>>
(Root)
Movie
Id: Guid
Title: string
Screenings : Screening[]
<<Entity>>
Screening
Id: Guid
TheaterId: Guid
Seats: Seat[]
ScreeningTime: DateTime
DefaultFee: Decimal
ChildrenFee: Decimal
<<Value Object>>
Seat
Row: int
Column: int
IsReserved: bool
빌딩 블록
Building Block
Reservation Aggregate
<<Entity>>
(Root)
Reservation
Id: Guid
MovieId: Guid
ScreeningId: Guid
AudienceName: string
Items : Array<ReservationItem>
<<Value Object>>
ReservationItem
…
이벤트 소싱
Capture all changes to an application
state as sequence of events.
- Martin Fowler
이벤트 소싱
Event Sourcing
Event sourcing is all about the
storing of facts.
- Greg Young
전통적 저장 방식
Traditional Store
저장소
Cart_id User_id
1 3
2 5
…
Cart_id Item_id Count
1 3 1
1 2 1
1 10 1
<Cart> <CartItem>
이벤트 소싱
Event Sourcing
이벤트 저장소
이벤트
CartCreated
ItemsAdded
ItemsDeleted
CartOrdered
……
이벤트 소싱
Event Sourcing
이벤트 구성
Key Value
ObjectId EventType
Version Serialized PayLoad
이벤트 소싱
Event Sourcing
이벤트 저장소 구현 예시
ReservationId Version EventType PayLoad
ac98ds0 2 ItemsAdded {“Items_Id” : “cflsk” … }
ld035bp5 2 ItemsAdded {“Items_Id” : “csldk” … }
ac98ds0 3 ItemsDeleted {“Items_Id” : “cflsk” … }
이벤트 소싱
Event Sourcing
𝑆𝑡𝑎𝑡𝑒 𝑛 = ෍
𝑖=1
𝑛
𝐸𝑣𝑒𝑛𝑡𝑖
이벤트 소싱
Event Sourcing
어딘가 낯 익은 데..?
“집합체”와 “이벤트 소싱”
집합체와 이벤트 소싱
Aggregate using Event Sourcing
Reservation
Raise
Event
Commands 유효성
검사
Valid
예외
Invalid
Event
Handler
State
Event
Store
Events
Events
<< Save >>
<< Restore >>
집합체와 이벤트 소싱
Aggregate using Event Sourcing
Reservation
Raise
Event
Commands 유효성
검사
Valid
예외
Invalid
Event
Handler
State
Event
Store
Events
Events
<< Save >>
<< Restore >>
public void Cancel(DateTime now)
{
AssertCanCancel(now);
RaiseEvent(new ReservationCanceled());
}
private void AssertCanCancel(DateTime now)
{
if (CanCancel(now))
{
string message = "Cannot cancel because of cancel time limits over";
throw new InvariantException(message, now);
}
}
private bool CanCancel(DateTime now)
=> now > _movieTime.AddMinutes(20);
집합체와 이벤트 소싱
Aggregate using Event Sourcing
Reservation
Raise
Event
Commands 유효성
검사
Valid
예외
Invalid
Event
Handler
State
Event
Store
Events
Events
<< Save >>
<< Restore >>
private void RaiseEvent(DomainEvent domainEvent)
{
EnqueueEvent(domainEvent);
HandleEvent(domainEvent);
}
private void EnqueueEvent(DomainEvent domainEvent)
{
_pendingEvents.Add(domainEvent);
}
private void HandleEvent(DomainEvent domainEvent)
{
Func<object> handler = FindEventHandler(domainEvent.GetType());
handler.Invoke(domainEvent);
}
private void ReservationCanceledEventHandler(ReservationCanceled reservationCanceled)
{
_status = Status.Canceled;
}
집합체와 이벤트 소싱
Aggregate using Event Sourcing
Reservation
Raise
Event
Commands 유효성
검사
Valid
예외
Invalid
Event
Handler
State
Event
Store
Events
Events
<< Save >>
<< Restore >>
public static Reservation Restore(IEnumerable<DomainEvent> pastEvents)
{
var reservation = new Reservation();
foreach (DomainEvent domainEvent in pastEvents)
{
reservation.HandleEvent(domainEvent);
}
return reservation;
}
private void HandleEvent(DomainEvent domainEvent)
{
Func<object> handler = FindEventHandler(domainEvent.GetType());
handler.Invoke(domainEvent);
}
private void ReservationCanceledEventHandler(ReservationCanceled reservationCanceled)
{
_status = Status.Canceled;
}
이벤트 소싱, “그리고 더 ….”
객체 관계형 임피던스 불일치
The object-relational impedance mismatch is
a set of conceptual and technical difficulties
that are often encountered
when a relational database management system (RDBMS) is being served
by an application program (or multiple application programs)
written in an object-oriented programming language or style,
particularly because objects or class definitions
must be mapped to database tables defined by a relational schema.
이벤트는 관계가 없는 단순한 구성을 가진다
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
𝑆𝑡𝑎𝑡𝑒 𝑛 = ෍
𝑖=1
𝑛
𝐸𝑣𝑒𝑛𝑡𝑖
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
𝑆𝑡𝑎𝑡𝑒 𝑛 = 𝑆𝑡𝑎𝑡𝑒 𝑚 + ෍
𝑖=𝑚+1
𝑛
𝐸𝑣𝑒𝑛𝑡𝑖
1 ≤ 𝑚 ≤ 𝑛
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
롤링 스냅샷
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
UI
데이터베이스
모델
전통적 방식
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
UI
조회모델
데이터 베이스
명령모델
데이터 베이스
조회모델
명령모델
CQRSCommand Query Responsibility Segregation
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
내가 겪은 Domain-Driven-Design
장점
도메인 모델에 대한 이해
단점
가파른 학습 곡선
작업의 우선 순위 결정
이벤트 소싱, 그리고 더 …
Event Sourcing, And more …
내가 겪은 Event-Sourcing
장점
신뢰 가능한 시스템 기록
단점
가파른 학습 곡선
마이그레이션비즈니스의 추적 기록 요구
CQRS 필수도메인 모델의 풍부한 코드 표현
DDD와 이벤트소싱

DDD와 이벤트소싱

  • 3.
  • 4.
    Eric Evans의 책에서처음 소개된 설계법 복잡한 도메인을 해결하는 목적의 소프트웨어를 우선순위로 해결해나가는 방법 도메인 주도 설계 Domain-Driven Design
  • 5.
    도메인 주도 설계프로세스 Domain-Driven Design Process 도메인 분석 Bounded Context 엔터티, 집합체, 서비스 등 정의 계층 설계 도메인 모델 Bounded Context 엔터티 사용자 인터페이스 유비쿼터스 언어 Context map 값 객체 Value Object 응용 프로그램 Shared Kernel 집합체 도메인 계층 기타 서비스 인프라 기타
  • 6.
    도메인의 구성요소를 개념적으로표현한 것 SW 전문가와 도메인 전문가가 만드는 것 도메인에 대한 이해가 필수! 어떤 특정한 다이어그램이 아니라 다이어그램이 전달하고자 하는 아이디어 내적 일관성이 없는 모델은 아무런 의미가 없다 도메인 모델 Domain Model
  • 7.
    도메인 모델 Domain Model 예시:영화 예매 시스템 Reservation 영화 예매 정보 Movie 영화 정보 Screening 상영 정보 AudienceName 관객이름 ReservationItem 예매 상품 정보 영화 예매 정보는 영화 정보ID, 상영 정보, 관객이름, 예매상품 정보를 갖는다
  • 8.
    도메인 모델 Domain Model ReservationModel (이거보다 훨씬 풍성해져야 한다) Reservation ID MovieID ScreeningID AudienceName ReservationItems
  • 9.
  • 10.
    엔터티 Entity 소프트웨어가 여러 과정을 거치는동안에도 동일한 값을 유지하는 식별자를 지닌 유형의 객체 빌딩 블록 Building Block 값 객체 Value object 개념적 식별성이 없는, 어떤 특징을 묘사하는 객체 한번 만들어 지면 바뀌지 않는 객체
  • 11.
    집합체 Aggregate 생명주기를 공유하는데이터 집합 일관성을 유지해야 될 객체들을 묶어 놓은 것 빌딩 블록 Building Block Root Entity 접근 범위에 있는 가장 상위 Entity Aggregate은 Root Entity를 통해서만 외부에서 접근 할 수 있다
  • 12.
    빌딩 블록 Building Block 집합체의중요성 연관 관계를 줄이면서 복잡도가 감소한다 많은 도메인 모델을 간단하고 이해 가능한 수준으로 만들어 줄 수 있다
  • 13.
    빌딩 블록 Building Block MovieAggregate <<Entity>> (Root) Movie Id: Guid Title: string Screenings : Screening[] <<Entity>> Screening Id: Guid TheaterId: Guid Seats: Seat[] ScreeningTime: DateTime DefaultFee: Decimal ChildrenFee: Decimal <<Value Object>> Seat Row: int Column: int IsReserved: bool
  • 14.
    빌딩 블록 Building Block ReservationAggregate <<Entity>> (Root) Reservation Id: Guid MovieId: Guid ScreeningId: Guid AudienceName: string Items : Array<ReservationItem> <<Value Object>> ReservationItem …
  • 15.
  • 16.
    Capture all changesto an application state as sequence of events. - Martin Fowler 이벤트 소싱 Event Sourcing Event sourcing is all about the storing of facts. - Greg Young
  • 17.
    전통적 저장 방식 TraditionalStore 저장소 Cart_id User_id 1 3 2 5 … Cart_id Item_id Count 1 3 1 1 2 1 1 10 1 <Cart> <CartItem>
  • 18.
    이벤트 소싱 Event Sourcing 이벤트저장소 이벤트 CartCreated ItemsAdded ItemsDeleted CartOrdered ……
  • 19.
    이벤트 소싱 Event Sourcing 이벤트구성 Key Value ObjectId EventType Version Serialized PayLoad
  • 20.
    이벤트 소싱 Event Sourcing 이벤트저장소 구현 예시 ReservationId Version EventType PayLoad ac98ds0 2 ItemsAdded {“Items_Id” : “cflsk” … } ld035bp5 2 ItemsAdded {“Items_Id” : “csldk” … } ac98ds0 3 ItemsDeleted {“Items_Id” : “cflsk” … }
  • 21.
    이벤트 소싱 Event Sourcing 𝑆𝑡𝑎𝑡𝑒𝑛 = ෍ 𝑖=1 𝑛 𝐸𝑣𝑒𝑛𝑡𝑖
  • 22.
  • 23.
  • 24.
    집합체와 이벤트 소싱 Aggregateusing Event Sourcing Reservation Raise Event Commands 유효성 검사 Valid 예외 Invalid Event Handler State Event Store Events Events << Save >> << Restore >>
  • 25.
    집합체와 이벤트 소싱 Aggregateusing Event Sourcing Reservation Raise Event Commands 유효성 검사 Valid 예외 Invalid Event Handler State Event Store Events Events << Save >> << Restore >>
  • 26.
    public void Cancel(DateTimenow) { AssertCanCancel(now); RaiseEvent(new ReservationCanceled()); } private void AssertCanCancel(DateTime now) { if (CanCancel(now)) { string message = "Cannot cancel because of cancel time limits over"; throw new InvariantException(message, now); } } private bool CanCancel(DateTime now) => now > _movieTime.AddMinutes(20);
  • 27.
    집합체와 이벤트 소싱 Aggregateusing Event Sourcing Reservation Raise Event Commands 유효성 검사 Valid 예외 Invalid Event Handler State Event Store Events Events << Save >> << Restore >>
  • 28.
    private void RaiseEvent(DomainEventdomainEvent) { EnqueueEvent(domainEvent); HandleEvent(domainEvent); } private void EnqueueEvent(DomainEvent domainEvent) { _pendingEvents.Add(domainEvent); } private void HandleEvent(DomainEvent domainEvent) { Func<object> handler = FindEventHandler(domainEvent.GetType()); handler.Invoke(domainEvent); } private void ReservationCanceledEventHandler(ReservationCanceled reservationCanceled) { _status = Status.Canceled; }
  • 29.
    집합체와 이벤트 소싱 Aggregateusing Event Sourcing Reservation Raise Event Commands 유효성 검사 Valid 예외 Invalid Event Handler State Event Store Events Events << Save >> << Restore >>
  • 30.
    public static ReservationRestore(IEnumerable<DomainEvent> pastEvents) { var reservation = new Reservation(); foreach (DomainEvent domainEvent in pastEvents) { reservation.HandleEvent(domainEvent); } return reservation; } private void HandleEvent(DomainEvent domainEvent) { Func<object> handler = FindEventHandler(domainEvent.GetType()); handler.Invoke(domainEvent); } private void ReservationCanceledEventHandler(ReservationCanceled reservationCanceled) { _status = Status.Canceled; }
  • 31.
  • 32.
    객체 관계형 임피던스불일치 The object-relational impedance mismatch is a set of conceptual and technical difficulties that are often encountered when a relational database management system (RDBMS) is being served by an application program (or multiple application programs) written in an object-oriented programming language or style, particularly because objects or class definitions must be mapped to database tables defined by a relational schema. 이벤트는 관계가 없는 단순한 구성을 가진다 이벤트 소싱, 그리고 더 … Event Sourcing, And more …
  • 33.
    𝑆𝑡𝑎𝑡𝑒 𝑛 =෍ 𝑖=1 𝑛 𝐸𝑣𝑒𝑛𝑡𝑖 이벤트 소싱, 그리고 더 … Event Sourcing, And more …
  • 34.
    𝑆𝑡𝑎𝑡𝑒 𝑛 =𝑆𝑡𝑎𝑡𝑒 𝑚 + ෍ 𝑖=𝑚+1 𝑛 𝐸𝑣𝑒𝑛𝑡𝑖 1 ≤ 𝑚 ≤ 𝑛 이벤트 소싱, 그리고 더 … Event Sourcing, And more … 롤링 스냅샷
  • 35.
    이벤트 소싱, 그리고더 … Event Sourcing, And more … UI 데이터베이스 모델 전통적 방식
  • 36.
    이벤트 소싱, 그리고더 … Event Sourcing, And more … UI 조회모델 데이터 베이스 명령모델 데이터 베이스 조회모델 명령모델 CQRSCommand Query Responsibility Segregation
  • 37.
    이벤트 소싱, 그리고더 … Event Sourcing, And more … 내가 겪은 Domain-Driven-Design 장점 도메인 모델에 대한 이해 단점 가파른 학습 곡선 작업의 우선 순위 결정
  • 38.
    이벤트 소싱, 그리고더 … Event Sourcing, And more … 내가 겪은 Event-Sourcing 장점 신뢰 가능한 시스템 기록 단점 가파른 학습 곡선 마이그레이션비즈니스의 추적 기록 요구 CQRS 필수도메인 모델의 풍부한 코드 표현