<commit_before><commit_msg>ddd init<commit_after>---
layout: post
title:  "DDD 입문 @ZUM"
date:   2017-05-18 08:40:00 -0500
categories: 세미나
fb_title: ddd
---

# 도메인 모델

- 소프트웨어로 해결할 문제 영역

- 도메인 모델
  - 도메인의 구성요소를 개념적으로 표현


  - 정적 모델
    - 클래스, ER
  - 동적 모델
    - 커뮤니케이션, 시퀀스, 상태

- 단순 데이터 모델
  - 단순 속성 나열
  - 반쪽짜리 모델
    - Action이 없음(?)

- 도메인 모델에 필요한거
  - 표현력
    - 불피요한 번역 /해석이 필요하지 않도록 (코드를 보고 알아야...)
  - 기능
    - 객체 모델로 표현
  - 동적 측면 / 제약 조건 표현
    - 메소드를 잘활용하면 제약조건 표현에 좋다.(네이밍으로 표현(?))

  - 정적 : 모델링 할때 모델(도메인)에 상태와 행위를 같이 표현해야 보기 좋다.


# DDD

  - 모델 구성요소
    - 기본모델
      - 엔티티, 밸류
    - 묶음
      - 에그리거트
    - 기능
      - 객체 모델
      - 서비스
    - 영속
      - 레파지 토리


  - 엔티티 중심 모델 만들기
     - 식별자 생성
      - 특정 규칙, UUID, 시스템 식별자, 일려번호 등...

  - 밸류 : 개념적으로 하나의 값
    - 주소, 수신자등의 값을 ShippingInfo라는 Value로 표현

  - 모델에 기능 넣기
    - https://wckhg89.github.io/archivers/oop
    - 메소드로 기능과 제약 표현
      - 해당 메소드 이름만 보고 모델이 어떤 일을 하는지 알기 좋다
    - How ?
      - 가능하면 public set 메소드를 쓰지말자
        - 도메인의 의도를 사라지게 하는 효과가 있다.
      - get도 웬만하면 쓰지말자
        - 도메인에 getter setter를 넣으면 절차지향적인 개발이 되기 쉽다.

      - DTO 영역 경계 간 데이터를 전달하기 위한 DTO와는 구분

    - 주의사항
      - 모든 엔티티들에게 연관관계를 맺지 말자 (연관관계 최소화)
        - n+1 problem을 야기하기가 쉽다.


    - 개발 코드와 상황에 대한 불일치를 계속해서 네이밍을 바꾸면서 발전 시켜야한다.

# 애그리거트
  - 복잡해지는 모델의 경계를 잘 정해야 한다.
  - 개별 모델을 상위 수준에서 적당하게 묶어주는 단위

  - 유사한 라이프 사이클을 가지는 단위 (한 애그리거트에 묶일 가능성이 높음)

  - 한 애그리거트는 다른 애그리거트에 있는 객체와 엮이지 않음
    - 주문 1 애그리거트, 주문 2 애그리거트는 엮이지 않음

  - 애그리거트 루트
    - 애그리거트의 모든 객체는 루트에 직/간접적으로 속한다.
    - **애그리거트에 속한 객체의 상태를 바꿀 수 있는것은 애그리거트 루트를 통해서만 가능하다.**

  - 애그리거트의 트랜잭션
    - 범위는 자기자신의 애그리거트로 제한해야한다.

  - 애그리거트의 크기 경계
    - 상품 (1) : 리뷰 (N)
      - 상품과 리뷰는 함꼐 바뀌지 않음 (라이프 사이클이 다름)
      - 리뷰의 관리 주체(리뷰를 다는사람)와 상품의 관리 주체(관리자)가 다름

# 아키텍처

- DIP (의존관계 역전의 원칙)
  - 고수준 모듈 / 저수준 모듈

  - 고수준 : 가격할인 계산 (고객정보를 구함 / 룰을 이용해서 할인 금액 구함) (더 상위 수준)

  - 저수준 : RDMS JPA / Drools로 룰을 적용 (더 저수준)

  - 의존의 방향 (고수준 -> 저수준)
    - 저수준 고수준이 섞여 있으면 저수준의 로직 변화에 고수준이 영향을 받게 된다.

    - DIP 적용으로 방지 할 수 있다.
      - 전략 패턴(?)
      - 인터페이스를 활용하여 구현체를 따로 두면 저수준의 구현이 바뀌더라도 다른 구현체로 갈아 끼워주면 된다.
      - 인터페이스의 네이밍은 고수준 관점에서의 네이밍 혹은 기능을 정의 하는게 좋다.

  - 영역 (패키지 구성(?))
    - 표현 (컨트롤러)
    - 응용 서비스
      - 사용자의 요청을 처리할 기능을 구현
      - 처리 흐름을 구현!
      - 도메인 로직은 도메인 영역에 위임

      - **도메인에 역할을 위임을 잘 할 수록** 더 짧은 코드가 작성된다.
    - 도메인
    - 인프라 스트럭쳐
      - 응용서비스 혹은 도메인에서 사용하는 실제 구현

- 응용 서비스의 입력과 출력
  - 입력
    - 필요한 파라미터만 넘기자
  - 출력
    - 조회전용 모델 (CQRS)
  - 트랜잭션
    - Transaction 단위가 된다.
  - 응용 서비스에 도메인 로직을 넣지 않기

- 표현영역 (Controller)
  - 사용자에게 화면을 제공하고 사용 흐름 제어
  - 사용자 요청을 응용 서비스에 전달
  - 세션 관리

- 몇가지 고민거리
  - 서비스의 크기 어디까지
  - 인터페이스를 구지 가져야하나?

  - 구현의 편의성을 우선으로 생각하는 편이십니당.
{'fraction_non_alphanumeric': 0.09049943672549755, 'fraction_numerical': 0.009012392039053699, 'mean_word_length': 1.4462809917355373, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '887661', 'n_tokens_mistral': 2336, 'n_tokens_neox': 3160, 'n_words': 447}