SlideShare a Scribd company logo
DDD 준비 @서문래
최범균(madvirus@madvirus.net), 2017-01-20
발표자
• 최범균,madvirus@madvirus.net
• 주로자바로먹고살며,잡다한분야에관심
• 코딩잘하고,글잘쓰고싶은개발자
2DDD 소개@서문래
내용
• 내용
• 언어,모델
• 아키텍처
• DDD소개
• 대상
• DDD에관심있는개발자
3DDD 소개@서문래
# 언어와 모델
• 언어
• 도메인
• 모델
4DDD 소개@서문래
언어
• 언어매우중요
• 일관되지않은언어사용개발지옥
• 완전히다른단어,(거의)같은것
• (거의)같은 단어,미세한의미차이
• 일관된사용해석불필요비용감소
• 코드,문서,대화에서일관된언어사용
• 유비쿼터스언어(UbiquitousLanguage)
5DDD 소개@서문래
이해하기 쉬운 용어
• 향후코드이해에유리한용어선택
• 가능하면간결한단어
• 어려운영어,모호한영어<발음대로영어표기
• 예:CivilAppeal<Minwon
• 예:Kind,Type,Class,…<Gubun
6DDD 소개@서문래
언어 = 도메인, 컨텍스트
• 언어는특정도메인이나컨텍스트에서의미
• 같은대상도도메인에따라다른용어
• 카탈로그의고객,주문의구매자
• 같은용어도도메인에따라다른의미
• 배송의상품은실물,카탈로그의상품은정보
• 도메인에맞는용어선택에는노력필요
• 도메인전문과와의대화
• 대화에출현한단어와(레거시)코드가불일치하면바꾸는노력
7DDD 소개@서문래
언어의 발전
• 도메인에대한새로운이해
• 코드에반영,언어에반영
public class Order {
public voidchangeShippingInfo(
ShippingInfonewShippingInfo){
if (state== OrderState.PAYMENT_WAITING||
state== OrderState..PREPARING){
this.shippingInfo= newShippingInof;
} else {
thrownew IllegalStateException();
}
}
public class Order {
public voidchangeShippingInfo(
ShippingInfonewShippingInfo){
verifyNotYetShipped();
this.shippingInfo = newShippingInof;
}
public voidcancel() {
verifyNotYetShipped();
this.state= OrderState.CANCELED;
}
privatevoid verifyNotYetShipped(){
if (state!= OrderState.PAYMENT_WAITING&&
state!= OrderState.PREPARING)
throw new IllegalStateException();
}
"결제대기거나물건준비중일때"
배송지를변경할수있다.
"배송을아직하지않았으면"
배송지를변경할수있다,주문을취소할수있다.
8DDD 소개@서문래
추상화
• 개념이나표현을정의하는과정
• 구체적인용어
• 요구사항과대화속에서도출
• 이해가깊어지면새로운개념발견
• 추상화언어정의
• 알맞은언어선택을할수있도록도와줌
9DDD 소개@서문래
도메인Domain
소프트웨어로 해결할 문제 영역
온라인 쇼핑
10DDD 소개@서문래
도메인 모델
• 도메인의구성요소를개념적으로표현한것
• 도메인의이해를바탕으로만들어짐
• 구현과정에서점진적으로상세화
• 소프트웨어모델
• 다양한관점에서의모델
• 정적인모델
• 클래스다이어그램,ER다이어그램
• 동적인모델
• 커뮤니케이션다이어그램,시퀀스다이어그램
• 상태다이어그램
11DDD 소개@서문래
단순 데이터 모델
• 일부개념이사라짐
• 단순속성나열
• 반쪽
• 중요도메인기능/제약
이드러나지않음
Order
------------------------
-id:String
-state:String
-totalAmounts:int
-receiverName:String
-receiverPhoneNumber;String
-shipAddr1:String
-shipAddr2:String
-shipZipcode:String
-ordererName:String
-ordererId:String
Product
--------------
-id:String
-listPrice:int
12DDD 소개@서문래
도메인 모델에 필요한 것
• 표현력
• 최대한중요개념이드러나도록
• 도메인용어를최대한모델에반영
• 불필요한번역/해석이발생하지않도록모델구축
• 기능
• 객체모델,함수
• 동적측면/제약조건표현
• 상태다이어그램등을활용
13DDD 소개@서문래
도메인 모델 예
14DDD 소개@서문래
도메인 모델 예
15DDD 소개@서문래
# 아키텍처
• 영역
• DIP
• 인프라
16DDD 소개@서문래
연통 배관 * 계층 구조
UI 서비스 DAO
UI 서비스 DAO
UI 서비스 DAO
• 참고 자료: http://www.slideshare.net/gyumee/ss-55616001
17DDD 소개@서문래
고수준 모듈, 저수준 모듈
• 고수준모듈
• 어떤의미있는
단일기능을
제공하는모듈
• 저수준모듈
• 고수준모듈의
기능을구현하기
위해필요한
하위기능의
실제구현
18DDD 소개@서문래
의존의 방향
• 고수준저수준으로의존
• 저수준의변경에따라고수준이영향을받을수있음
19DDD 소개@서문래
DIP(Dependency Inversion Principle)
• 고수준모듈이저수준모듈에의존하지않고
저수준모듈이고수준모듈에의존함
• 의존방향을"고수준저수준"에서
"저수준고수준"으로변경
고수준
저수준
20DDD 소개@서문래
DIP 주의사항
21DDD 소개@서문래
(DDD의) 영역
영역 설명
표현(UI) 사용자의 요청을 해석해서 다른 영역에 처리를
위임하고, 결과를 사용자에 알맞게 변환해서
전달한다.
사용자에게 보여지는 흐름을 제어한다.
응용 사용자의 요청을 처리할 기능을 구현한다. 처
리 흐름을 구현하며, 도메인 로직은 도메인 영
역에 위임한다.
도메인 도메인 로직을 구현한다. 엔티티, 밸류, 애그리
거트, 리포지토리, 도메인 서비스가 위치한다.
인프라스트럭처 DBMS 연동, REST 클라이언트와 같은 구현 기
술을 다룬다. DIP 구조에서 저수준 모듈이 이
영역에 위치한다.
22DDD 소개@서문래
아키텍처에서의 고수준/저소준
23DDD 소개@서문래
DIP와 DDD의 하위 도메인 간 연결
도메인 인프라UI/응용
도메인 인프라UI/응용
24DDD 소개@서문래
인프라스트럭처
• 기반구현기술제공
• 응용서비스나도메인서비스구현
• 외부시스템과의연동이나특정기술에기반한구현
• 리포지토리구현
• 외부RESTAPI연동구현
• 메일클라이언트연동구현
• DIP고려
• 응용이나도메인에위치할인터페이스를구현관점에서
작성하지않도록함
25DDD 소개@서문래
# DDD 소개
• 도메인모델구성요소
26DDD 소개@서문래
세 개의 축
Language
Bounded
Context
Tactical
Pattern
27DDD 소개@서문래
DDD의 모델 구성 요소
• 기본모델
• 엔티티
• 밸류
• 모델의묶음
• 애그리거트
• 기능
• 객체모델
• 도메인서비스
• 영속
• 리포지토리
28DDD 소개@서문래
엔티티로 중심 모델 만들기
• 엔티티의특징
• 식별자(ID)를가짐
• 식별자는바뀌지않음
• 데이터/상태를가짐
• 자기만의라이프사이클을가짐
• (주로)엔티티의상태에따라다르게동작함
• (주로)DB테이블과1대1관계를가짐
• 대표적인예
• 주문,회원,제품
29DDD 소개@서문래
밸류로 모델 표현력 증가하기
• 개념적으로하나인데이터집합을표현
• 예,주소,배송지,돈
Order
------------------------
-id:String
-state:String
-totalAmounts:int
-receiverName:String
-receiverPhoneNumber;String
-shipAddr1:String
-shipAddr2:String
-shipZipcode:String
-ordererName:String
-ordererId:String
Address
------------------------
-addr1:String
-addr2:String
-zipcode:String
Receiver
------------------------
-name:String
-phoneNumber;StringShippingInfo
-------------------
-receiver:Receiver
-address:Address
Order
------------------------
-id:String
-state:String
-totalAmounts:Money
-shippingInfo:ShippingInfo
-orderer:Orderer
Money
----------
-value:int
Orderer
----------
-name:String
-id:String
30DDD 소개@서문래
모델에 기능 넣기
• 메서드로기능과제약표현
public class Order {
public void changeShippingInfo(ShippingInfo newShippingInfo) {
verifyNotYetShipped();
setShippingInfo(newShippingInfo);
}
private void verifyNotYetShipped() {
if (state != OrderState.PAYMENT_WAITING || … )
throw new IllegalArgumentException("already shipped");
}
private void setShippingInfo(ShippingInfo si) {
this.shippingInfo = si;
}
…
31DDD 소개@서문래
도메인 모델의 공개 set 메서드 없애기
• 도메인코드의공개set/get메서드는
• 핵심개념이나의도를사라지게만듬
• completePayment()vssetOrderState()
• 절차지향이되기쉬움
• verifyNotYetShipped()vsgetOrderState()!=WAITING_PAYMENT
• set/get메서드기능/제약을표현하는메서드
• 필요한경우get과is같은데이터제공메서드사용
• 영역경계간데이터를전달하기위한DTO와구분
32DDD 소개@서문래
# 애그리거트
• 애그리거트란
• 애그리거트크기,경계
33DDD 소개@서문래
애그리거트Aggregate로 모으기
• 개별모델을상위수준에서묶어주는단위
34DDD 소개@서문래
애그리거트
• 상위수준에서모델을이해하는데도움
• 도메인규칙/일관성을관리하는단위
• 복잡한도메인을단순화
• 한애그리거트에속한객체는유사한라이프사이클
• 특히,함께생성되고함께삭제됨
35DDD 소개@서문래
애그리거트와 경계
• 한애그리거트에속한객체는다른애그리거트에속
하지않음
• 함께변경되는객체는한애그리거트에속할가능성높음
• 예,배송지주소,주문정보(주문개수)
• 한애그리거트는자기자신만관리
• 다른애그리거트를직접변경하지않음
• 예,주문애그리거트에서회원애그리거트를변경하지않음
36DDD 소개@서문래
애그리거트 루트
• 애그리거트의책임자
• 애그리거트에속한
객체가일관된상태를
유지하도록관리하는
책임을가진객체
• 애그리거트의
모든객체는루트에
직/간접적으로속함
37DDD 소개@서문래
애그리거트 루트
• 도메인규칙과일관성을유지하는주체
• 애그리거트루트를통해서만애그리거트내부상태변경
• 애그리거트외부에기능을제공
public class Order {
public void changeShippingInfo(ShippingInfo newShippingInfo) {
verifyNotYetShipped();
setShippingInfo(newShippingInfo);
}
private void verifyNotYetShipped() {
if (state != OrderState.PAYMENT_WAITING || … )
throw new IllegalArgumentException("already shipped");
}
private void setShippingInfo(ShippingInfo si) {
this.shippingInfo = si;
}
…
38DDD 소개@서문래
애그리거트 루트
• 애그리거트에속한객체를
이용해서기능구현
• 애그리거트에속한다른
객체에위임
• 애그리거트에속한다른
객체의상태를조회
• 밸류객체는객체자체를
교체하는방법이쉬움
public class Member {
private Password password;
public void changePassword(
String curPw,
String newPw) {
if (!password.match(curPw)) { // 위임
throw new NotMatchingException();
}
// 상태 변경
this.password = new Password(newPw);
}
…
39DDD 소개@서문래
애그리거트의 크기, 경계
• 주로한개엔티티와소수의밸류객체로구성
• N개엔티티객체로구성되는경우는흔치않음
• has로보이는1-N관계는서로다른애그리거트인지
확인필요
• M-N관계는연관객체가어느애그리거트에속하는
지확인필요
40DDD 소개@서문래
# 리포지토리
• 리포지토리
• 스펙
• 리포지토리와애그리거트간연관
41DDD 소개@서문래
리포지토리 인터페이스
• 리포지토리는애그리거트(루트)단위로존재
• OrderOrderRepository,MemberMemberRepository
• 테이블단위로존재하는것이아님
• 리포지토리의주요메서드
• save(Userorder)
• UserfindOne(Stringemail)
• List<User>findByJoinDateBetween(Datefrom,Dateto)
• List<User>findBySpec(Specificationspec)
• Page<User>findByName(Stringname)
• voidremove(Useruser)
42DDD 소개@서문래
리포지토리 구현 기술: JPA
• 애그리거트를RDBMS와매핑하기에무난한기술
• 애노테이션기반설정(XML보다자바설정선호)
• 밸류에대한매핑설정/확장지원
• @Embeddable
• AttributeConverter
• 콜렉션지원
• 엔티티간1-1,1-N,N-M지원
• 연관엔티티에대한영속성전파
43DDD 소개@서문래
Spring Data JPA
• 반복작업제거
• 인터페이스만만들면구현객체는런타임에생성
• 정해진규칙에따라인터페이스정의
• JPQL,네이티브쿼리실행가능
• 페이징,스펙(+QueryDSL)지원
44DDD 소개@서문래
스펙
• 검색조건을표현
• 개별검색조건을하나의스펙으로표현
• 검색조건의의미가잘드러남
• And,Or를이용한스펙조합
• 주로조회기능에서활용
• SpringDataJPA스펙지원
• 설명:http://goo.gl/7R4SYO
Specification<OnlineTest> nameSpec = nameLike("중간고사");
Specification<OnlineTest> yearSpec = yearBetween(2011, 2016);
Specifications<OnlineTest> specs = where(nameSpec);
specs = specs.and(yearBetween);
List<OnlineTest> test = onlineRepository.findAll(specs);
45DDD 소개@서문래
애그리거트는 완전체
• 리포지토리는완전한애그리거트를다룸
• 로딩시점에애그리거트에속한모든연관객체로딩
• 즉,엔티티나콜렉션에대해EAGER로딩기본사용
• 기능구현에따라안전한경우에한해LAZY로딩
• 저장시점에애그리거트에속한모든연관객체저장
• 삭제시점에애그리거트에속한모든연관객체삭제
save(onlineTest) 
 find(id)
46DDD 소개@서문래
애그리거트 간 연관
• 애그리거트간연관:애그리거트루트를참조
• 직접참조보다는ID참조선호
• 몇가지이유
• 편한탐색오용방지
• 성능에대한고민제거
• 시스템확장시유리
public class Reserve {
private Customer reserver;
…
public class Reserve {
private CustomerId reserverId;
…
47DDD 소개@서문래
애그리거트 간 연관: ID 참조
• 연관된애그리거트와의조합이필요한기능
• 상태변경기능
• 응용서비스에서조합처리
• 도메인서비스고려
• 여러애그리거트함께조회
• 조회전용DAO고려
48DDD 소개@서문래
사고 방식 추가
• 조인,데이터애그리거트,기능
• 애그리거트단위로기능구현
• 기능에서객체의상태를변경
• 루트에서다른객체에위임
• 한개모델조회,명령
• CQRS
• 조회전용DTO/DAO
49DDD 소개@서문래
# 응용 서비스
50DDD 소개@서문래
응용 서비스
• 사용자가요청한기능을실행하고결과를리턴
• 일종의입력과출력을가진프로시저
• 도메인을사용해서기능구현
• 도메인영역과표현영역을연결해주는창구
51DDD 소개@서문래
응용 서비스의 구현
• 도메인객체를사용한기능구현
• 리포지토리에서애그리거트루트를구하고
• 애그리거트루트의기능을실행
@Service
public class ActivateOperatorService {
private OperatorRepository operatorRepository;
@Transactional
public void activate(String operatorId) {
// 애그리거트 루트를 구하고
Operator operator = operatorRepository.findOne(operatorId);
if (operator == null)
throw new OperatorNotFoundException();
// 도메인 기능을 실행
operator.activate();
}
52DDD 소개@서문래
응용 서비스의 입력과 출력
• 메서드파라미터
• 기능을수행하는데필요한데이터
public class ChangePasswordService {
public void changePassword(
String id,
String curPw,
String newPw) {
Member member = findMember(id);
member.changePassword(curPw, newPw);
}
...
public class PlaceOrderService {
public OrderNo placeOrder(OrderRequest req) {
OrderNo id = createNextOrderNo();
Order order = createOrder(id, req);
orderRepository.save(order);
return id;
}
...
* 도메인의 엔티티를 서비스의 파라미터로 사용하지 말 것
* 딱 들어맞는 경우로만 제한
53DDD 소개@서문래
응용 서비스의 입력과 출력
• 리턴
• 요청처리결과를사용자에게보여줄경우응답제공
• 예,새로생성한주문의ID,주문목록
• 고민거리
• 도메인객체리턴vsUI에노출할데이터만담은객체리턴
• 구현편의성,팀표준,성능등고려
• 조회전용모델검토
• 익셉션은실패를의미
• 응용서비스나도메인에서발생
54DDD 소개@서문래
응용 서비스와 트랜잭션
• 트랜잭션담당
public class ChangePasswordService {
@Transactional
public void changePassword(ChangePasswordRequest request) {
Member member = findExistingMember(request.getMemberId());
member.changePassword(
request.getCurrentPassword(),
request.getNewPassword());
}
...
* 고민거리 : Open Session In View
55DDD 소개@서문래
응용 서비스에 도메인 로직 넣지 않기
• 도메인로직이나제약을구현하면안됨!
public class ActivateOperatorService {
private OperatorRepository operatorRepository;
@Transactional
public void activate(String operatorId) {
Operator operator = operatorRepository.findOne(operatorId);
if (operator == null)
throw new OperatorNotFoundException();
if (operator.isDeleted() || operator.isActivated()) {
throw new RuntimeException();
}
operator.setActivated(true);
// operator.activate()에 들어가야 할 제약 검사
}
56DDD 소개@서문래
몇 가지 고민할 것
• 서비스
• 크기
• 도메인단위로기능몰아넣기vs기능군별로서비스구분
• 인터페이스필요여부
• 인터페이스 +구현클래스
• 그냥클래스만
• 서비스vs표현vs도메인
• 값검증
• 권한검사
57DDD 소개@서문래
# BOUNDED CONTEXT
58DDD 소개@서문래
BOUNDED CONTEXT
• 모델경계=언어경계
• 문백안에서의미
• 논리적인언어경계선
• 기능을제공하는물리
적인시스템
• 조직구조를따라하위
도메인에매핑
59DDD 소개@서문래
BOUNDED CONTEXT의 구조
60DDD 소개@서문래
BC 간 관계
• 서비스공급자,고객
• 상류,하류
• 공개호스트서비스
OpenHostService
• 안티코럽션레이어
AnticorruptionLayer
• 공유커널
SharedKernel
• 독립방식
SeparateWay
61DDD 소개@서문래
컨텍스트 맵
62DDD 소개@서문래
# 정리
63DDD 소개@서문래
끝
최범균 | madvirus@madvirus.net | http://javacan.tistory.com
64DDD 소개@서문래

More Related Content

PDF
DDD로 복잡함 다루기
PDF
도메인구현 KSUG 20151128
PDF
ドメイン駆動設計という仕事の流儀
PDF
ドメインオブジェクトの見つけ方・作り方・育て方
PDF
ドメイン駆動設計のための Spring の上手な使い方
PDF
ドメイン駆動設計のためのオブジェクト指向入門
PDF
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
PDF
ドメイン駆動設計 の 実践 Part3 DDD
DDD로 복잡함 다루기
도메인구현 KSUG 20151128
ドメイン駆動設計という仕事の流儀
ドメインオブジェクトの見つけ方・作り方・育て方
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のためのオブジェクト指向入門
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメイン駆動設計 の 実践 Part3 DDD

What's hot (20)

PDF
서버 성능에 대한 정의와 이해
PDF
Fault Tolerance 소프트웨어 패턴
PDF
Riverpodでテストを書こう
ODP
SPAのルーティングの話
PDF
実践 NestJS
PPTX
Behavior driven development (bdd)
PDF
ドメイン駆動設計サンプルコードの徹底解説
PDF
[수정본] 우아한 객체지향
PDF
ドメインオブジェクトの設計ガイドライン
PPTX
CloudFront経由でのCORS利用
PDF
게임 서버 성능 분석하기
PDF
React for Beginners
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PPTX
Spring boot 勉強会
PDF
Angular - Chapter 4 - Data and Event Handling
PPTX
FiNC DDD第一回勉強会
PDF
ソフトウェア開発のやり方の改善
PPTX
Spring data jpa
PDF
実践的な設計って、なんだろう?
PPTX
SQLチューニング入門 入門編
서버 성능에 대한 정의와 이해
Fault Tolerance 소프트웨어 패턴
Riverpodでテストを書こう
SPAのルーティングの話
実践 NestJS
Behavior driven development (bdd)
ドメイン駆動設計サンプルコードの徹底解説
[수정본] 우아한 객체지향
ドメインオブジェクトの設計ガイドライン
CloudFront経由でのCORS利用
게임 서버 성능 분석하기
React for Beginners
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
Spring boot 勉強会
Angular - Chapter 4 - Data and Event Handling
FiNC DDD第一回勉強会
ソフトウェア開発のやり方の改善
Spring data jpa
実践的な設計って、なんだろう?
SQLチューニング入門 入門編
Ad

Viewers also liked (20)

PDF
keras 빨리 훑어보기(intro)
PDF
Ddd start 부록 지앤선&ksug
PDF
Tensorflow regression 텐서플로우 회귀
PDF
모델링 연습 리뷰
PDF
DDD 구현기초 (거의 Final 버전)
PDF
MVP 패턴 소개
PDF
Spring Boot 소개
PDF
간단 Ip 필터 구현 이야기
PDF
자바8 스트림 API 소개
PDF
Event source 학습 내용 공유
PPTX
파이썬 언어 기초
PPTX
Ddd start! 6장. 응용 서비스와 표현 영역
PPTX
Git 사용 가이드
PDF
자바8 람다식 소개
PDF
스프링 시큐리티 구조 이해
PPTX
7가지 동시성 모델 - 6장. 순차 프로세스 통신
PDF
도메인 주도 설계의 본질
PDF
PDF
우리가 모르는 노드로 할 수 있는 몇가지
PDF
We are now Sentiance.
keras 빨리 훑어보기(intro)
Ddd start 부록 지앤선&ksug
Tensorflow regression 텐서플로우 회귀
모델링 연습 리뷰
DDD 구현기초 (거의 Final 버전)
MVP 패턴 소개
Spring Boot 소개
간단 Ip 필터 구현 이야기
자바8 스트림 API 소개
Event source 학습 내용 공유
파이썬 언어 기초
Ddd start! 6장. 응용 서비스와 표현 영역
Git 사용 가이드
자바8 람다식 소개
스프링 시큐리티 구조 이해
7가지 동시성 모델 - 6장. 순차 프로세스 통신
도메인 주도 설계의 본질
우리가 모르는 노드로 할 수 있는 몇가지
We are now Sentiance.
Ad

Similar to DDD 준비 서문래 (20)

PDF
MSA_기초자료.pdf
PPTX
DDD Start! - 2장 아키텍처 개요
PPT
Daejeon IT Developer Conference Hibernate3
PPTX
도메인주도설계
PDF
Jpa 쿼리 포함 자료
PDF
Jpa 쿼리 포함 자료
PDF
Bounded Context
PPTX
Event Storming and Implementation Workshop
PPT
Daejeon IT Developer Conference Hibernate3
PDF
Domain-Driven-Design 정복기 1탄
PDF
Domain-Driven-Design 정복기 1탄
PPTX
Hibernate 기초
PDF
Event Storming(이벤트 스토밍)
PPTX
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
PDF
DDD start 1장
PPTX
DDD 그게 뭔데 (개념 찍먹편)
PPTX
반복적인 코드 작업 자동화, Codebone으로 손쉽게
PDF
[아꿈사/110903] 도메인주도설계 4장
PDF
지금 당장 (유사) DDD 시작하기
PDF
Ksug2015 - JPA2, JPA 기초와매핑
MSA_기초자료.pdf
DDD Start! - 2장 아키텍처 개요
Daejeon IT Developer Conference Hibernate3
도메인주도설계
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
Bounded Context
Event Storming and Implementation Workshop
Daejeon IT Developer Conference Hibernate3
Domain-Driven-Design 정복기 1탄
Domain-Driven-Design 정복기 1탄
Hibernate 기초
Event Storming(이벤트 스토밍)
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
DDD start 1장
DDD 그게 뭔데 (개념 찍먹편)
반복적인 코드 작업 자동화, Codebone으로 손쉽게
[아꿈사/110903] 도메인주도설계 4장
지금 당장 (유사) DDD 시작하기
Ksug2015 - JPA2, JPA 기초와매핑

More from beom kyun choi (17)

PDF
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
PDF
TDD 발담그기 @ 공감세미나
PDF
ALS WS에 대한 이해 자료
PDF
Ji 개발 리뷰 (신림프로그래머)
PDF
리뷰의 기술 소개
PDF
Zookeeper 소개
PDF
하둡2 YARN 짧게 보기
PDF
차원축소 훑어보기 (PCA, SVD, NMF)
PDF
객체 지향 발담그기 JCO 컨퍼런스 14회
PDF
Storm 훑어보기
PDF
Hive 입문 발표 자료
PDF
HBase 훑어보기
PDF
Flume 훑어보기
PDF
하둡 맵리듀스 훑어보기
PDF
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
PDF
하둡 HDFS 훑어보기
PDF
하둡 (Hadoop) 및 관련기술 훑어보기
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
TDD 발담그기 @ 공감세미나
ALS WS에 대한 이해 자료
Ji 개발 리뷰 (신림프로그래머)
리뷰의 기술 소개
Zookeeper 소개
하둡2 YARN 짧게 보기
차원축소 훑어보기 (PCA, SVD, NMF)
객체 지향 발담그기 JCO 컨퍼런스 14회
Storm 훑어보기
Hive 입문 발표 자료
HBase 훑어보기
Flume 훑어보기
하둡 맵리듀스 훑어보기
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
하둡 HDFS 훑어보기
하둡 (Hadoop) 및 관련기술 훑어보기

DDD 준비 서문래

  • 3. 내용 • 내용 • 언어,모델 • 아키텍처 • DDD소개 • 대상 • DDD에관심있는개발자 3DDD 소개@서문래
  • 4. # 언어와 모델 • 언어 • 도메인 • 모델 4DDD 소개@서문래
  • 5. 언어 • 언어매우중요 • 일관되지않은언어사용개발지옥 • 완전히다른단어,(거의)같은것 • (거의)같은 단어,미세한의미차이 • 일관된사용해석불필요비용감소 • 코드,문서,대화에서일관된언어사용 • 유비쿼터스언어(UbiquitousLanguage) 5DDD 소개@서문래
  • 6. 이해하기 쉬운 용어 • 향후코드이해에유리한용어선택 • 가능하면간결한단어 • 어려운영어,모호한영어<발음대로영어표기 • 예:CivilAppeal<Minwon • 예:Kind,Type,Class,…<Gubun 6DDD 소개@서문래
  • 7. 언어 = 도메인, 컨텍스트 • 언어는특정도메인이나컨텍스트에서의미 • 같은대상도도메인에따라다른용어 • 카탈로그의고객,주문의구매자 • 같은용어도도메인에따라다른의미 • 배송의상품은실물,카탈로그의상품은정보 • 도메인에맞는용어선택에는노력필요 • 도메인전문과와의대화 • 대화에출현한단어와(레거시)코드가불일치하면바꾸는노력 7DDD 소개@서문래
  • 8. 언어의 발전 • 도메인에대한새로운이해 • 코드에반영,언어에반영 public class Order { public voidchangeShippingInfo( ShippingInfonewShippingInfo){ if (state== OrderState.PAYMENT_WAITING|| state== OrderState..PREPARING){ this.shippingInfo= newShippingInof; } else { thrownew IllegalStateException(); } } public class Order { public voidchangeShippingInfo( ShippingInfonewShippingInfo){ verifyNotYetShipped(); this.shippingInfo = newShippingInof; } public voidcancel() { verifyNotYetShipped(); this.state= OrderState.CANCELED; } privatevoid verifyNotYetShipped(){ if (state!= OrderState.PAYMENT_WAITING&& state!= OrderState.PREPARING) throw new IllegalStateException(); } "결제대기거나물건준비중일때" 배송지를변경할수있다. "배송을아직하지않았으면" 배송지를변경할수있다,주문을취소할수있다. 8DDD 소개@서문래
  • 9. 추상화 • 개념이나표현을정의하는과정 • 구체적인용어 • 요구사항과대화속에서도출 • 이해가깊어지면새로운개념발견 • 추상화언어정의 • 알맞은언어선택을할수있도록도와줌 9DDD 소개@서문래
  • 10. 도메인Domain 소프트웨어로 해결할 문제 영역 온라인 쇼핑 10DDD 소개@서문래
  • 11. 도메인 모델 • 도메인의구성요소를개념적으로표현한것 • 도메인의이해를바탕으로만들어짐 • 구현과정에서점진적으로상세화 • 소프트웨어모델 • 다양한관점에서의모델 • 정적인모델 • 클래스다이어그램,ER다이어그램 • 동적인모델 • 커뮤니케이션다이어그램,시퀀스다이어그램 • 상태다이어그램 11DDD 소개@서문래
  • 12. 단순 데이터 모델 • 일부개념이사라짐 • 단순속성나열 • 반쪽 • 중요도메인기능/제약 이드러나지않음 Order ------------------------ -id:String -state:String -totalAmounts:int -receiverName:String -receiverPhoneNumber;String -shipAddr1:String -shipAddr2:String -shipZipcode:String -ordererName:String -ordererId:String Product -------------- -id:String -listPrice:int 12DDD 소개@서문래
  • 13. 도메인 모델에 필요한 것 • 표현력 • 최대한중요개념이드러나도록 • 도메인용어를최대한모델에반영 • 불필요한번역/해석이발생하지않도록모델구축 • 기능 • 객체모델,함수 • 동적측면/제약조건표현 • 상태다이어그램등을활용 13DDD 소개@서문래
  • 14. 도메인 모델 예 14DDD 소개@서문래
  • 15. 도메인 모델 예 15DDD 소개@서문래
  • 16. # 아키텍처 • 영역 • DIP • 인프라 16DDD 소개@서문래
  • 17. 연통 배관 * 계층 구조 UI 서비스 DAO UI 서비스 DAO UI 서비스 DAO • 참고 자료: http://www.slideshare.net/gyumee/ss-55616001 17DDD 소개@서문래
  • 18. 고수준 모듈, 저수준 모듈 • 고수준모듈 • 어떤의미있는 단일기능을 제공하는모듈 • 저수준모듈 • 고수준모듈의 기능을구현하기 위해필요한 하위기능의 실제구현 18DDD 소개@서문래
  • 19. 의존의 방향 • 고수준저수준으로의존 • 저수준의변경에따라고수준이영향을받을수있음 19DDD 소개@서문래
  • 20. DIP(Dependency Inversion Principle) • 고수준모듈이저수준모듈에의존하지않고 저수준모듈이고수준모듈에의존함 • 의존방향을"고수준저수준"에서 "저수준고수준"으로변경 고수준 저수준 20DDD 소개@서문래
  • 22. (DDD의) 영역 영역 설명 표현(UI) 사용자의 요청을 해석해서 다른 영역에 처리를 위임하고, 결과를 사용자에 알맞게 변환해서 전달한다. 사용자에게 보여지는 흐름을 제어한다. 응용 사용자의 요청을 처리할 기능을 구현한다. 처 리 흐름을 구현하며, 도메인 로직은 도메인 영 역에 위임한다. 도메인 도메인 로직을 구현한다. 엔티티, 밸류, 애그리 거트, 리포지토리, 도메인 서비스가 위치한다. 인프라스트럭처 DBMS 연동, REST 클라이언트와 같은 구현 기 술을 다룬다. DIP 구조에서 저수준 모듈이 이 영역에 위치한다. 22DDD 소개@서문래
  • 24. DIP와 DDD의 하위 도메인 간 연결 도메인 인프라UI/응용 도메인 인프라UI/응용 24DDD 소개@서문래
  • 25. 인프라스트럭처 • 기반구현기술제공 • 응용서비스나도메인서비스구현 • 외부시스템과의연동이나특정기술에기반한구현 • 리포지토리구현 • 외부RESTAPI연동구현 • 메일클라이언트연동구현 • DIP고려 • 응용이나도메인에위치할인터페이스를구현관점에서 작성하지않도록함 25DDD 소개@서문래
  • 26. # DDD 소개 • 도메인모델구성요소 26DDD 소개@서문래
  • 28. DDD의 모델 구성 요소 • 기본모델 • 엔티티 • 밸류 • 모델의묶음 • 애그리거트 • 기능 • 객체모델 • 도메인서비스 • 영속 • 리포지토리 28DDD 소개@서문래
  • 29. 엔티티로 중심 모델 만들기 • 엔티티의특징 • 식별자(ID)를가짐 • 식별자는바뀌지않음 • 데이터/상태를가짐 • 자기만의라이프사이클을가짐 • (주로)엔티티의상태에따라다르게동작함 • (주로)DB테이블과1대1관계를가짐 • 대표적인예 • 주문,회원,제품 29DDD 소개@서문래
  • 30. 밸류로 모델 표현력 증가하기 • 개념적으로하나인데이터집합을표현 • 예,주소,배송지,돈 Order ------------------------ -id:String -state:String -totalAmounts:int -receiverName:String -receiverPhoneNumber;String -shipAddr1:String -shipAddr2:String -shipZipcode:String -ordererName:String -ordererId:String Address ------------------------ -addr1:String -addr2:String -zipcode:String Receiver ------------------------ -name:String -phoneNumber;StringShippingInfo ------------------- -receiver:Receiver -address:Address Order ------------------------ -id:String -state:String -totalAmounts:Money -shippingInfo:ShippingInfo -orderer:Orderer Money ---------- -value:int Orderer ---------- -name:String -id:String 30DDD 소개@서문래
  • 31. 모델에 기능 넣기 • 메서드로기능과제약표현 public class Order { public void changeShippingInfo(ShippingInfo newShippingInfo) { verifyNotYetShipped(); setShippingInfo(newShippingInfo); } private void verifyNotYetShipped() { if (state != OrderState.PAYMENT_WAITING || … ) throw new IllegalArgumentException("already shipped"); } private void setShippingInfo(ShippingInfo si) { this.shippingInfo = si; } … 31DDD 소개@서문래
  • 32. 도메인 모델의 공개 set 메서드 없애기 • 도메인코드의공개set/get메서드는 • 핵심개념이나의도를사라지게만듬 • completePayment()vssetOrderState() • 절차지향이되기쉬움 • verifyNotYetShipped()vsgetOrderState()!=WAITING_PAYMENT • set/get메서드기능/제약을표현하는메서드 • 필요한경우get과is같은데이터제공메서드사용 • 영역경계간데이터를전달하기위한DTO와구분 32DDD 소개@서문래
  • 33. # 애그리거트 • 애그리거트란 • 애그리거트크기,경계 33DDD 소개@서문래
  • 35. 애그리거트 • 상위수준에서모델을이해하는데도움 • 도메인규칙/일관성을관리하는단위 • 복잡한도메인을단순화 • 한애그리거트에속한객체는유사한라이프사이클 • 특히,함께생성되고함께삭제됨 35DDD 소개@서문래
  • 36. 애그리거트와 경계 • 한애그리거트에속한객체는다른애그리거트에속 하지않음 • 함께변경되는객체는한애그리거트에속할가능성높음 • 예,배송지주소,주문정보(주문개수) • 한애그리거트는자기자신만관리 • 다른애그리거트를직접변경하지않음 • 예,주문애그리거트에서회원애그리거트를변경하지않음 36DDD 소개@서문래
  • 37. 애그리거트 루트 • 애그리거트의책임자 • 애그리거트에속한 객체가일관된상태를 유지하도록관리하는 책임을가진객체 • 애그리거트의 모든객체는루트에 직/간접적으로속함 37DDD 소개@서문래
  • 38. 애그리거트 루트 • 도메인규칙과일관성을유지하는주체 • 애그리거트루트를통해서만애그리거트내부상태변경 • 애그리거트외부에기능을제공 public class Order { public void changeShippingInfo(ShippingInfo newShippingInfo) { verifyNotYetShipped(); setShippingInfo(newShippingInfo); } private void verifyNotYetShipped() { if (state != OrderState.PAYMENT_WAITING || … ) throw new IllegalArgumentException("already shipped"); } private void setShippingInfo(ShippingInfo si) { this.shippingInfo = si; } … 38DDD 소개@서문래
  • 39. 애그리거트 루트 • 애그리거트에속한객체를 이용해서기능구현 • 애그리거트에속한다른 객체에위임 • 애그리거트에속한다른 객체의상태를조회 • 밸류객체는객체자체를 교체하는방법이쉬움 public class Member { private Password password; public void changePassword( String curPw, String newPw) { if (!password.match(curPw)) { // 위임 throw new NotMatchingException(); } // 상태 변경 this.password = new Password(newPw); } … 39DDD 소개@서문래
  • 40. 애그리거트의 크기, 경계 • 주로한개엔티티와소수의밸류객체로구성 • N개엔티티객체로구성되는경우는흔치않음 • has로보이는1-N관계는서로다른애그리거트인지 확인필요 • M-N관계는연관객체가어느애그리거트에속하는 지확인필요 40DDD 소개@서문래
  • 41. # 리포지토리 • 리포지토리 • 스펙 • 리포지토리와애그리거트간연관 41DDD 소개@서문래
  • 42. 리포지토리 인터페이스 • 리포지토리는애그리거트(루트)단위로존재 • OrderOrderRepository,MemberMemberRepository • 테이블단위로존재하는것이아님 • 리포지토리의주요메서드 • save(Userorder) • UserfindOne(Stringemail) • List<User>findByJoinDateBetween(Datefrom,Dateto) • List<User>findBySpec(Specificationspec) • Page<User>findByName(Stringname) • voidremove(Useruser) 42DDD 소개@서문래
  • 43. 리포지토리 구현 기술: JPA • 애그리거트를RDBMS와매핑하기에무난한기술 • 애노테이션기반설정(XML보다자바설정선호) • 밸류에대한매핑설정/확장지원 • @Embeddable • AttributeConverter • 콜렉션지원 • 엔티티간1-1,1-N,N-M지원 • 연관엔티티에대한영속성전파 43DDD 소개@서문래
  • 44. Spring Data JPA • 반복작업제거 • 인터페이스만만들면구현객체는런타임에생성 • 정해진규칙에따라인터페이스정의 • JPQL,네이티브쿼리실행가능 • 페이징,스펙(+QueryDSL)지원 44DDD 소개@서문래
  • 45. 스펙 • 검색조건을표현 • 개별검색조건을하나의스펙으로표현 • 검색조건의의미가잘드러남 • And,Or를이용한스펙조합 • 주로조회기능에서활용 • SpringDataJPA스펙지원 • 설명:http://goo.gl/7R4SYO Specification<OnlineTest> nameSpec = nameLike("중간고사"); Specification<OnlineTest> yearSpec = yearBetween(2011, 2016); Specifications<OnlineTest> specs = where(nameSpec); specs = specs.and(yearBetween); List<OnlineTest> test = onlineRepository.findAll(specs); 45DDD 소개@서문래
  • 46. 애그리거트는 완전체 • 리포지토리는완전한애그리거트를다룸 • 로딩시점에애그리거트에속한모든연관객체로딩 • 즉,엔티티나콜렉션에대해EAGER로딩기본사용 • 기능구현에따라안전한경우에한해LAZY로딩 • 저장시점에애그리거트에속한모든연관객체저장 • 삭제시점에애그리거트에속한모든연관객체삭제 save(onlineTest)   find(id) 46DDD 소개@서문래
  • 47. 애그리거트 간 연관 • 애그리거트간연관:애그리거트루트를참조 • 직접참조보다는ID참조선호 • 몇가지이유 • 편한탐색오용방지 • 성능에대한고민제거 • 시스템확장시유리 public class Reserve { private Customer reserver; … public class Reserve { private CustomerId reserverId; … 47DDD 소개@서문래
  • 48. 애그리거트 간 연관: ID 참조 • 연관된애그리거트와의조합이필요한기능 • 상태변경기능 • 응용서비스에서조합처리 • 도메인서비스고려 • 여러애그리거트함께조회 • 조회전용DAO고려 48DDD 소개@서문래
  • 49. 사고 방식 추가 • 조인,데이터애그리거트,기능 • 애그리거트단위로기능구현 • 기능에서객체의상태를변경 • 루트에서다른객체에위임 • 한개모델조회,명령 • CQRS • 조회전용DTO/DAO 49DDD 소개@서문래
  • 50. # 응용 서비스 50DDD 소개@서문래
  • 51. 응용 서비스 • 사용자가요청한기능을실행하고결과를리턴 • 일종의입력과출력을가진프로시저 • 도메인을사용해서기능구현 • 도메인영역과표현영역을연결해주는창구 51DDD 소개@서문래
  • 52. 응용 서비스의 구현 • 도메인객체를사용한기능구현 • 리포지토리에서애그리거트루트를구하고 • 애그리거트루트의기능을실행 @Service public class ActivateOperatorService { private OperatorRepository operatorRepository; @Transactional public void activate(String operatorId) { // 애그리거트 루트를 구하고 Operator operator = operatorRepository.findOne(operatorId); if (operator == null) throw new OperatorNotFoundException(); // 도메인 기능을 실행 operator.activate(); } 52DDD 소개@서문래
  • 53. 응용 서비스의 입력과 출력 • 메서드파라미터 • 기능을수행하는데필요한데이터 public class ChangePasswordService { public void changePassword( String id, String curPw, String newPw) { Member member = findMember(id); member.changePassword(curPw, newPw); } ... public class PlaceOrderService { public OrderNo placeOrder(OrderRequest req) { OrderNo id = createNextOrderNo(); Order order = createOrder(id, req); orderRepository.save(order); return id; } ... * 도메인의 엔티티를 서비스의 파라미터로 사용하지 말 것 * 딱 들어맞는 경우로만 제한 53DDD 소개@서문래
  • 54. 응용 서비스의 입력과 출력 • 리턴 • 요청처리결과를사용자에게보여줄경우응답제공 • 예,새로생성한주문의ID,주문목록 • 고민거리 • 도메인객체리턴vsUI에노출할데이터만담은객체리턴 • 구현편의성,팀표준,성능등고려 • 조회전용모델검토 • 익셉션은실패를의미 • 응용서비스나도메인에서발생 54DDD 소개@서문래
  • 55. 응용 서비스와 트랜잭션 • 트랜잭션담당 public class ChangePasswordService { @Transactional public void changePassword(ChangePasswordRequest request) { Member member = findExistingMember(request.getMemberId()); member.changePassword( request.getCurrentPassword(), request.getNewPassword()); } ... * 고민거리 : Open Session In View 55DDD 소개@서문래
  • 56. 응용 서비스에 도메인 로직 넣지 않기 • 도메인로직이나제약을구현하면안됨! public class ActivateOperatorService { private OperatorRepository operatorRepository; @Transactional public void activate(String operatorId) { Operator operator = operatorRepository.findOne(operatorId); if (operator == null) throw new OperatorNotFoundException(); if (operator.isDeleted() || operator.isActivated()) { throw new RuntimeException(); } operator.setActivated(true); // operator.activate()에 들어가야 할 제약 검사 } 56DDD 소개@서문래
  • 57. 몇 가지 고민할 것 • 서비스 • 크기 • 도메인단위로기능몰아넣기vs기능군별로서비스구분 • 인터페이스필요여부 • 인터페이스 +구현클래스 • 그냥클래스만 • 서비스vs표현vs도메인 • 값검증 • 권한검사 57DDD 소개@서문래
  • 58. # BOUNDED CONTEXT 58DDD 소개@서문래
  • 59. BOUNDED CONTEXT • 모델경계=언어경계 • 문백안에서의미 • 논리적인언어경계선 • 기능을제공하는물리 적인시스템 • 조직구조를따라하위 도메인에매핑 59DDD 소개@서문래
  • 61. BC 간 관계 • 서비스공급자,고객 • 상류,하류 • 공개호스트서비스 OpenHostService • 안티코럽션레이어 AnticorruptionLayer • 공유커널 SharedKernel • 독립방식 SeparateWay 61DDD 소개@서문래
  • 64. 끝 최범균 | madvirus@madvirus.net | http://javacan.tistory.com 64DDD 소개@서문래