92thunder's blog

ざっくりわかるドメイン駆動設計

Posted: May 31, 2020

2020/5/29に会社の勉強会で発表した内容をブログとしてまとめなおす

この時点で自分がDDDに知っていることをまとめてみる

経緯

ドメイン駆動設計=DDDとは

松岡さんのブログよりDomainlanguage.comの引用

  1. ドメインの中核となる複雑さと機会に焦点を当てる
    • これがもっとも重要な考え方。下はドメイン駆動設計で用いられる代表的なテクニック。
  2. ドメイン専門家とソフトウェア専門家のコラボレーションでモデルを探求する
  3. 明示的にそれらのモデルを表現するソフトウェアを書く
  4. 境界付けられたコンテキストの中のユビキタス言語で話す

ドメインとは

An image from Notion

よくわからんけど領域が近そう🤔

勤怠システムのドメイン(領域)にはこのような概念がある

テックタッチだと

ソフトウェアの目的は問題の解決

ドメイン駆動設計 = ドメインの知識に焦点を当てる設計手法

(なんでドメインって言うんだろうね…)

ドメインモデル、ドメインオブジェクトとは

ドメイン駆動設計では、ドメインの概念・ドメインモデル・ドメインオブジェクトを行き来しながらドメインの理解・ドメインの実装を繰り返す

戦略と戦術

軍事用語の戦略と戦術

戦略:戦いに勝つために兵力を総合的・効果的に運用する方法で、大局的・長期的な視点で策定する計画手段

戦術:戦いに勝つための戦地での兵士の動かし方など、実行上の方策

DDDの戦略と戦術

戦略:ドメインを理解し、それをモデルに落とし込む

戦術:具体的な実装パターン

軽量DDDとは

An image from NotionAn image from Notion

ユビキタス言語

ステークホルダー間で認識の齟齬や翻訳にコストをかけないために共通言語を使う

ユビキタス=いつでもどこにでも存在する

IoTのことユビキタスコンピューティングって呼んでる時代あったよね

ドメインエキスパート「ユーザを登録する」

開発者「ユーザを新規保存する」

ドメインエキスパートの言葉をそのまま使うということではない。

システムにもドメインにも寄り添ってユビキタス言語を作っていく

モデリング

一般的な昔ながらの方法

https://www.slideshare.net/koichiromatsuoka/202038

最近はRDRA2.0という手法が流行っているみたい

An image from Notion

ドメインオブジェクト

ValueObject 値オブジェクト

class FullName {
	constructor(fistName: string, lastName: string) {
    this.firstName = firstName
    this.lastName = lastName
  }

	equals(fullName: FullName) {
    return this.firstName === fullName.firstName && this.lastName === fullName.lastName
  }
}

Entity エンティティ

class User {
  id: string
  fullName: FullName
  
  constructor(fullName: FullName) {
		this.id = createId()
    this.fullName = fullName
  }

  changeName(fullName: FullName) {
    this.fullName = fullName
		// return new User(fullName)
  }

  equals(user: User) {
    return this.id === user.id
  }
}

リポジトリ

class UserRepository implements IUserRepository{
  find(name: string) {
    // SELECT * FROM USERS WHERE name....
  }
  
  save(user: User) {}
  delete(user: User) {}
}

なぜドメイン駆動でリポジトリが出てくる?

アプリケーションサービス

class UserService {
  repository: IUserRepository

	constructor(repository: IUserRepository) {
	  this.repository = repository  
	}

	register(name: string) {
    // ユーザ名の制約に引っかかると例外を投げる
		const user = new User(name)

		if (await this.repository.find(name)) {
			throw new Error('重複してます')
		}

		this.repository.save(user)
  }
}

アーキテクチャ

気持ち

参考資料