λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Programming Books/DDD START!

Chapter 1. 도메인 λͺ¨λΈ μ‹œμž‘

by IamBeau 2022. 8. 14.

도메인

πŸ‘€  λ„λ©”μΈμ΄λž€ ?

- μ†Œν”„νŠΈμ›¨μ–΄λ‘œ ν•΄κ²°ν•˜κ³ μž ν•˜λŠ” 문제 μ˜μ—­
  • 온라인 책을 νŒλ§€ν•˜λŠ” μ„œμ  μ‹œμŠ€ν…œμ„ κ΅¬ν˜„ν•˜κ³  ν•  λ•Œ, 도메인과 ν•˜μœ„ 도메인은 μ•„λž˜μ™€ 같이 λΆ„λ₯˜ν•  수 있음
    • 도메인 : 온라인 μ„œμ 
    • ν•˜μœ„ 도메인 : νšŒμ›, μƒν’ˆ, μ£Όλ¬Έ, 결제, 배솑, μ •μ‚°, 문의 λ“±
  • ν•œ ν•˜μœ„ 도메인은 λ‹€λ₯Έ ν•˜μœ„ 도메인과 μ—°λ™ν•˜μ—¬ μ™„μ „ν•œ κΈ°λŠ₯을 제곡
    • 물건 ꡬ맀 : μ£Όλ¬Έ, 결제, 배솑, μ •μ‚°
  • νŠΉμ • 도메인을 μœ„ν•œ μ†Œν”„νŠΈμ›¨μ–΄λΌκ³  ν•΄μ„œ 도메인이 μ œκ³΅ν•΄μ•Ό ν•  λͺ¨λ“  κΈ°λŠ₯을 직접 κ΅¬ν˜„ν•˜λŠ” 것은 μ•„λ‹˜
    • μ™ΈλΆ€ PG, μ™ΈλΆ€ μ±„νŒ… μ†”λ£¨μ…˜
  • 도메인 λ§ˆλ‹€ κ³ μ •λœ ν•˜μœ„ 도메인이 항상 μ‘΄μž¬ν•˜μ§€λŠ” μ•ŠμŒ
    • 도메인을 μ œκ³΅ν•  λŒ€μƒμ— 따라 달라지기도 함

 

도메인 λͺ¨λΈ

πŸ‘€  도메인 λͺ¨λΈμ΄λž€?

- νŠΉμ • 도메인을 κ°œλ…μ μœΌλ‘œ ν‘œν˜„ν•œ 것이고, 도메인 자체λ₯Ό μ΄ν•΄ν•˜κΈ° μœ„ν•œ κ°œλ… λͺ¨λΈ
  • λ„λ©”μΈμ˜ λͺ¨λ“  λ‚΄μš©μ„ λ‹΄κ³  μžˆμ§€λŠ” μ•Šμ§€λ§Œ, μ—¬λŸ¬ κ°œλ°œμžλ“€μ΄ λ™μΌν•œ λͺ¨μŠ΅μœΌλ‘œ 도메인 이해 및 도메인 지식을 κ³΅μœ ν•˜λŠ”λ° 도움이 됨
  • 도메인을 μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„œ ν‘œν˜„λ°©μ‹μ€ λ‹€μ–‘ν•  수 있음

 

도메인 λͺ¨λΈ μ’…λ₯˜ μ˜ˆμ‹œ

  • 클래슀 λ‹€μ΄μ–΄κ·Έλž¨ : κΈ°λŠ₯κ³Ό 데이터λ₯Ό ν•¨κ»˜ λ³΄μ—¬μ€Œ

클래슀 λ‹€μ΄μ–΄κ·Έλž¨

 

  • μƒνƒœ λ‹€μ΄μ–΄κ·Έλž¨ : νŠΉμ • λ„λ©”μΈμ˜ μƒνƒœμ „μ΄λ₯Ό λ‚˜νƒ€λƒ„

μƒνƒœ λ‹€μ΄μ–΄κ·Έλž¨

 

도메인 λͺ¨λΈ  νŒ¨ν„΄

πŸ‘€  도메인 λͺ¨λΈ νŒ¨ν„΄μ΄λž€?

-  λ„메인 κ·œμΉ™μ„ 객체 지ν–₯ κΈ°λ²•μœΌλ‘œ κ΅¬ν˜„ν•˜κ³ , ν•΄λ‹Ή μ½”λ“œλ₯Ό 도메인 계측에 μœ„μΉ˜μ‹œν‚΄

  • Presentation(ν‘œν˜„)
    • μ‚¬μš©μžμ˜ μš”μ²­μ„ μ²˜λ¦¬ν•˜κ³  μ‚¬μš©μžμ—κ²Œ 정보λ₯Ό λ³΄μ—¬μ€Œ
  • Application(μ‘μš©)
    • μ‚¬μš©μžκ°€ μš”μ²­ν•œ κΈ°λŠ₯을 μ‹€ν–‰
    • 업무 λ‘œμ§μ„ 직접 κ΅¬ν˜„ν•˜μ§€ μ•ŠμœΌλ©° 도메인 계측을 μ‘°ν•©ν•΄μ„œ κΈ°λŠ₯을 μ‹€ν–‰
  • Domain(도메인)
    • μ‹œμŠ€ν…œμ΄ μ œκ³΅ν•  λ„λ©”μΈμ˜ κ·œμΉ™μ„ κ΅¬ν˜„
  • Intrastructure(μΈν”„λΌμŠ€νŠΈλŸ­μ³)
    • μ™ΈλΆ€ μ‹œμŠ€ν…œκ³Όμ˜ 연동을 처리(DB, Messaging λ“±)

 

 

EX) 주문에 κ΄€ν•œ 도메인 λͺ¨λΈ νŒ¨ν„΄μ„ μ μš©ν•œ μ½”λ“œ (μš”κ±΄ : 좜고 μ „ 배솑지 λ³€κ²½ κ°€λŠ₯)

public class Order {
	private OrderStatus status;
	private ShippingInfo shippingInfo;

    //좜고 전에 배솑지λ₯Ό λ³€κ²½ν•  수 있음 (λŒ€κΈ° 쀑 : PAYMENT_WAITING, μ€€λΉ„ 쀑 : PREPARING)
	public void changeShippingInfo(ShippingInfo newShippingInfo) {
		if (!status.isShippingChangeable()) {
			throw new IllegalStateException();
		}
        
		this.shippingInfo = newShippingInfo;
	}
}

public enum OrderStatus {
	PAYMENT_WAITING {
		public boolean isShippingChangeable() {
			return true;
		}
	},
	PREPARING {
		public boolean isShippingChangeable() {
			return true;
		}
	},
	
	SHIPPED, DELIVERING, DELIVERY_COMPLETED;

	public boolean isShippingChangeable() {
		return false;
	}
}

 

핡심 κ·œμΉ™μ„ κ΅¬ν˜„ν•œ μ½”λ“œκ°€ 도메인 λͺ¨λΈμ—λ§Œ μœ„μΉ˜ν•˜κΈ° λ•Œλ¬Έμ—, κ·œμΉ™μ΄ λ°”λ€Œκ±°λ‚˜ κ·œμΉ™μ„ ν™•μž₯ν•΄μ•Ό ν•  λ•Œ λ‹€λ₯Έ μ½”λ“œμ— 영ν–₯을 덜 μ£Όκ³  λ³€κ²½ 내역을 λͺ¨λΈμ— λ°˜μ˜ν•  수 있게 됨

 

도메인 λͺ¨λΈ μž‘μ„± μœ μ˜μ‚¬ν•­

πŸ‘€  μ²˜μŒμ—λŠ” κ°œμš” μˆ˜μ€€μ˜ κ°œλ… λͺ¨λΈμ„ μž‘μ„±ν•˜μ—¬ 도메인에 λŒ€ν•œ 전체 μœ€κ³½μ„ μ΄ν•΄ν•˜λŠ”λ° μ§‘μ€‘ν•˜κ³ , κ΅¬ν˜„ν•˜λŠ” κ³Όμ •μ—μ„œ κ°œλ… λͺ¨λΈμ„ κ΅¬ν˜„ λͺ¨λΈλ‘œ μ μ§„μ μœΌλ‘œ λ°œμ „
  • κ°œλ… λͺ¨λΈμ„ λ§Œλ“€λ•Œ μ²˜μŒλΆ€ν„° μ™„λ²½ν•˜κ²Œ 도메인을 ν‘œν˜„ν•˜λŠ” λͺ¨λΈμ„ λ§Œλ“œλŠ” μ‹œλ„λ₯Ό ν•  수 μžˆμ§€λ§Œ μ‹€μ œλ‘œ μ΄λŠ” λΆˆκ°€λŠ₯에 κ°€κΉŒμ›€
  • μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό κ°œλ°œν•˜λŠ” λ™μ•ˆ 도메인을 점점 더 μ΄ν•΄ν•˜κ²Œ 되기 λ•Œλ¬Έμ—, μ‹œκ°„μ΄ μ§€λ‚˜κ°μ— 따라 λͺ¨λΈμ„ μˆ˜μ •ν•˜λŠ” κ²½μš°κ°€ 많기 λ•Œλ¬Έ (지식이 μŒ“μ΄λ©΄μ„œ μ™„μ „νžˆ λ‹€λ₯Έ 의미둜 ν•΄μ„λ˜μ–΄μ§€λŠ” 상황도 쑴재)

 

도메인 λͺ¨λΈ λ„μΆœ

πŸ‘€  도메인을 λͺ¨λΈλ§ν•  λ•Œ 기본이 λ˜λŠ” μž‘μ—…μ€? 

μš”κ΅¬μ‚¬ν•­μœΌλ‘œ λΆ€ν„° μ•„λž˜μ˜ μš”μ†Œλ“€μ„ 찾아야함
1. 핡심 κ΅¬μ„±μš”μ†Œ
2. κ·œμΉ™
3. κΈ°λŠ₯
  • μš”κ΅¬μ‚¬ν•­μ„ 톡해 μ œκ³΅ν•΄μ•Ό ν•˜λŠ” κΈ°λŠ₯을 λ„μΆœ κ°€λŠ₯
    • 좜고 μƒνƒœλ‘œ λ³€κ²½
    • 배솑지 정보 λ³€κ²½
  • μš”κ΅¬μ‚¬ν•­μ„ 톡해 νŠΉμ • ν•­λͺ©μ΄ μ–΄λ–€ λ°μ΄ν„°λ‘œ κ΅¬μ„±λ˜μ–΄μ•Ό ν•˜λŠ”μ§€ μ•Œ 수 있음
    • ν•œ μƒν’ˆμ„ ν•œκ°œ 이상 μ£Όλ¬Έ
    • 각 μƒν’ˆμ˜ ꡬ맀 가격 ν•© = (μƒν’ˆ 가격 * ꡬ맀 개수)
  • μš”κ΅¬μ‚¬ν•­μ„ 톡해 각 ν•­λͺ©κ°„μ˜ 관계λ₯Ό μ•Œ 수 있음
    • 주문은 μ΅œμ†Œ ν•œ μ’…λ₯˜ μ΄μƒμ˜ μƒν’ˆμ„ 포함 ν•΄μ•Ό 함
  • μš”κ΅¬μ‚¬ν•­μ— 따라 νŠΉμ • μ‘°κ±΄μ΄λ‚˜ μƒνƒœμ— 따라 μ œμ•½μ΄ κ·œμΉ™μ΄ 달리 μ μš©λ˜λŠ” 경우
    • 좜고λ₯Ό ν•˜λ©΄ 배솑지 정보λ₯Ό λ³€κ²½ν•  수 μ—†μŒ
    • 좜고 전에 주문을 μ·¨μ†Œν•  수 있음
    • 고객이 결제 μ™„λ£Œν•˜κΈ° μ „μ—λŠ” μƒν’ˆμ„ μ€€λΉ„ν•˜μ§€ μ•ŠμŒ

 

도메인 λͺ¨λΈ λ¬Έμ„œν™” 및 곡유

πŸ‘€ μ „λ°˜μ μΈ κΈ°λŠ₯ λͺ©λ‘μ΄λ‚˜ λͺ¨λ“ˆ κ΅¬μ‘°λŠ” μƒμœ„ μˆ˜μ€€μ—μ„œ μ •λ¦¬λœ λ¬Έμ„œλ₯Ό μ°Έμ‘°ν•˜λŠ” 것이 μ†Œν”„νŠΈμ›¨μ–΄ μ „λ°˜μ„ λΉ λ₯΄κ²Œ 이해 ν•˜λŠ”λ° 도움

더 깊게 이해가 ν•„μš”κ°€ μžˆλŠ” 뢀뢄은 μ½”λ“œλ‘œ λΆ„μ„ν•˜κ³ , 도메인 지식이 잘 λ¬»μ–΄λ‚˜λ„λ‘ μ½”λ“œ μžμ²΄λ„ λ¬Έμ„œν™”μ˜ λŒ€μƒ

 

엔티티와 λ°Έλ₯˜

πŸ‘€ λͺ¨λΈμ€ 크게 엔티티와 λ°Έλ₯˜λ‘œ ꡬ뢄
λΆ„λ₯˜ DTO VO Entity
μ •μ˜ 각 계측간 데이터 전솑 κ°’ ν‘œν˜„μš© DB ν…Œμ΄λΈ” λ§€ν•‘μš©
μ‹λ³„μž 포함 μ—¬λΆ€ X X O
μƒνƒœ λ³€κ²½ κ°€λŠ₯ μ—¬λΆ€ κ°€λ³€ / λΆˆλ³€ λΆˆλ³€ κ°€λ³€ / λΆˆλ³€
Business 둜직 포함 μ—¬λΆ€ X O O
Getter 포함 μ—¬λΆ€ O O O
Setter 포함 μ—¬λΆ€ O X O
equals & hashCode κ΅¬ν˜„ μ—¬λΆ€ X O O

DTO

  • 각 계측간 데이터 κ΅ν™˜μ„ μœ„ν•œ 객체
  • Business λ‘œμ§μ€ ν¬ν•¨ν•˜μ§€ μ•ŠμŒ
  • getter / setter λͺ¨λ‘ κ°€μ§ˆ 수 있음

VO

  • κ°œλ…μ μœΌλ‘œ μ™„μ „ν•œ ν•˜λ‚˜λ₯Ό ν‘œν˜„ν•  λ•Œ μ‚¬μš©
    • 우편번호, μ£Όμ†Œ, μƒμ„Έμ£Όμ†Œ → μ£Όμ†Œ (λ¬Άμ–΄μ„œ ν‘œν˜„)
public class ShippingInfo {
    ...
    private Address address;
    ...
}

public class Address {
	private String postalCode;
	private String address;
	private String addressDetail;
}
  • 보닀 λͺ…ν™•ν•˜κ²Œ ν‘œν˜„ν•  수 있게되고, μ½”λ“œμ˜ 가독성도 올라감
    • μ‹λ³„μžμ˜ 의미λ₯Ό 보닀 λͺ…ν™•ν•˜κ²Œ λͺ…μ‹œν•˜κΈ° μœ„ν•΄μ„œ μ‚¬μš© 
public class Order {
    private OrderNo id;
    
   ...
   
   public OrderNo getId() {
      return id;
   }
}
  • μž„μ˜μ˜ 두 VO의 μ£Όμ†Œκ°€ 달라도, λ‚΄μš©μ΄ λ™μΌν•˜λ‹€λ©΄ 두 VO λŠ” λ™μΌν•˜λ‹€κ³  νŒλ‹¨
    • equals / hashCodeλ₯Ό κ΅¬ν˜„

Entity

  • 각 Entity λŠ” κ³ μœ ν•œ μ‹λ³„μžλ₯Ό 가지고 있음
    • 생성방법
      • UUID
      • νŠΉμ •ν•œ κ·œμΉ™ : ν˜„μž¬ μ‹œκ°„κ³Ό λ‹€λ₯Έ 값을 μ‘°ν•©ν•˜μ—¬ μ‚¬μš©
      • κ°’ 직접 μž…λ ₯ : νšŒμ› ID, Email
      • 일련번호 : DB Auto Increment
  • μž„μ˜μ˜ 두 Entity의 μ‹λ³„μžκ°€ κ°™μœΌλ©΄ 두 EntityλŠ” λ™μΌν•˜λ‹€κ³  νŒλ‹¨
    • equals / hashCodeλ₯Ό μ‹λ³„μžλ₯Ό κΈ°μ€€μœΌλ‘œ κ΅¬ν˜„

도메인 λͺ¨λΈμ— Setterλ₯Ό μΆ”κ°€ν•œλ‹€λ©΄?

  • λ„λ©”μΈμ˜ 핡심 κ°œλ…μ΄λ‚˜ μ˜λ„λ₯Ό μ½”λ“œμ—μ„œ μ‚¬λΌμ§€κ²Œ 함
  • 도메인 객체λ₯Ό 생성할 λ•Œ μ™„μ „ν•œ μƒνƒœκ°€ μ•„λ‹μˆ˜λ„ 있게 λ§Œλ“¬
    • 도메인 객체가 λΆˆμ™„μ „ν•œ μƒνƒœλ‘œ μ‚¬μš©λ˜λŠ”κ²ƒμ„ λ§‰μœΌλ €λ©΄ μƒμ„±μ‹œμ μ— ν•„μš”ν•œ 것을 λͺ¨λ‘ μ „λ‹¬ν•΄μ€˜μ•Ό 함

 

πŸ“• equals / hashCode λž€?

* equals : λ‘κ°œμ˜ 객체가 λ‚΄μš©μ΄ 같은지 확인
→ 두 Object == 비ꡐλ₯Ό λ„˜μ–΄, 값이 같은지 λΉ„κ΅ν•˜λ €λ©΄ equals()λ₯Ό @Override

* hashCode : λ‘κ°œμ˜ 객체가 같은 객체인지 확인
→ equals()κ°€ true인 두 Objectλ₯Ό HashMap에 put을 ν•  λ•Œ λ™μΌν•œ Key둜 μΈμ‹ν•˜κ³  싢은 κ²½μš°μ— hashCode()λ₯Ό @Override

 

도메인 μš©μ–΄

πŸ‘€ 도메인 μš©μ–΄λ₯Ό μ½”λ“œμ— λ°˜μ˜ν•˜μ§€ μ•ŠμœΌλ©΄?

- κ°œλ°œμžκ°€ μ½”λ“œμ˜ 의미λ₯Ό 해석해야 ν•˜λŠ” 뢀담이 생김
// BAD
public enum OrderStatus {
    STEP1, STEP2, STEP3, STEP4 ..
}

// GOOD
public enum OrderStatus {
    PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING ..
}
  • 각각의 STEP이 μ–΄λŠ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ”μ§€ μ§κ΄€μ μœΌλ‘œ 보이지 μ•Šμ•„ νŒŒμ•…μ΄ νž˜λ“¬
  • νŒŒμ•…ν•˜λ”λΌλ„ κ·Έ μƒνƒœλ‘œ 맀번 λ¨Έλ¦Ώμ†μœΌλ‘œ λ³€ν™˜ν•˜λŠ” 과정이 μΆ”κ°€
  • 도메인 μš©μ–΄λ₯Ό μ½”λ“œμ— 직접 μ‚¬μš©ν•΄μ„œ 이런 λΆˆν•„μš”ν•œ 과정을 쀄이고, μ½”λ“œκ°€ λ°”λ‘œ 이해될 수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” 것이 μ’‹μŒ

μ΅œλ²”κ·  μž‘κ°€λ‹˜μ˜ DDD START! 1μž₯을 μš”μ•½ν–ˆμŠ΅λ‹ˆλ‹€.

 

 

 

 

'Programming Books > DDD START!' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Chapter 2. μ•„ν‚€ν…μ²˜ κ°œμš”  (0) 2022.08.15

λŒ“κΈ€