---
# System prepended metadata

title: ドメイン駆動設計入門 1章 ~ 3章

---

# ドメイン駆動設計入門 1章 ~ 3章

### ドメイン駆動設計とは何か

何らかのシステムを作るときエンジニアは何かを新しく学ぶ。その分野に無知であるので。
例えば物流システムであれば、物流の業務の流れや登場人物

>開発者がソフトウェアを開発するために必要な知識と不要な知識を選り分けるに は何が必要でしょうか。当たり前のことですが、ソフトウェアの利用者を取り巻く 世界について知る必要があります。
>ソフトウェアの利用者にとって重要な知識が何であるのかは、その世界の有り様に左右されるのです。価値あるソフトウェアを構 築するためには利用者の問題を見極め、解決するための最善手を常に考えていく必 要があります。
>ドメイン駆動設計はそういった洞察を繰り返しながら設計を行い、 ソフトウェアの利用者を取り巻く世界と実装を結びつけることを目的としていま す。

### ２種類に分かれる

- ソフトウェアにとって重要な概念を抽出するための「モデリング」
- 概念を実装に 落とし込むための「パターン」

この本ではパターンに焦点を当てて進めています


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

ドメインは「領域」という意味。

例えば会計システムなら金銭や帳簿という概念が含まれ、物流システムならトラックやドライバーが概念として含まれている。

>ドメイン駆動設計では、ドメインの概念 をモデリングして得られたモデルをドメインモデルと呼びます

>ドメインモデルをソフトウェアで動作するモジュールとして表現したものがドメ インオブジェクトです。

>![](https://i.imgur.com/IjAntxG.png)

実際にコードで表現したものがドメインオブジェクト


## 本書で紹介されるパターン

- 知識を表現するパターン
    - 値オブジェクト
    - エンティティ
    - ドメインサービス  
- アプリケーションを実現するためのパターン
    - リポジトリ
    - アプリケーションサービス
    - ファクトリ
- 知識を表現する、より発展的なパターン
    - 集約
    - 仕様

>![](https://i.imgur.com/Fq3woyF.png)


## 値オブジェクト

フルネームから姓を取り出す場合

```csharp=
var fullName = "naruse masanobu";
var tokens = fullName.Split(' '); // ["naruse", "masanobu"] ➡ という配列に
var lastName = tokens[0];
Console.WriteLine(lastName); // naruse が表示される
```

このコードはこの場合はうまく動いてそうだが、

```csharp=
var fullName = "john smith";
var tokens = fullName.Split(' '); // ["john", "smith"] という配列に var lastName = tokens[0];
Console.WriteLine(lastName); // john が表示される
```

姓が後ろに記述される文化では動かない

一般的にはクラスで表現する
```csharp=

class FullName
{
  public FullName(string firstName, string lastName) {
    FirstName = firstName;
    LastName = lastName; 
  }
  
  public string FirstName { get; }
  public string LastName { get; }
}
```

>この例からわかることは、システムに最適な値が必ずしもプリミティブな値であ るとは限らないということです。
>システムには必要とされる処理にしたがって、そ のシステムならではの値の表現があるはずです


値オブジェクトとは

>- 不変である
>- 交換が可能である
>- 等価性によって比較される

硬貨がよく例として挙げられます。それぞれに当てはめると

#### 不変である

```csharp=
var coin = new Coin(100) // 100円玉
coin.changeAmount(500)
```

硬貨が途中で変化することは現実世界からは予想できず混乱させます

#### 交換が可能である

```csharp=
var myPocketCoin = new Coin(100) // 100円玉
myPocketCoin = new Coin(500) // 500円玉
```

変化はしないが、交換することは可能である

#### 価性によって比較される

```csharp=
var myPocketCoin1 = new Coin(100) // 100円玉
var myPocketCoin2 = new Coin(500) // 500円玉
Console.WriteLine(myPocketCoin1.amount === myPocketCoin2.amount);
```

不自然。

もしCoinに`equals()`メソッドが生えていた場合


```csharp=
public override bool Equals(object obj)
{
    return this.amount === object.amount
}

```

このように自然に書くことができる。

```csharp=
Console.WriteLine(myPocketCoin1 === myPocketCoin2);
```

これは自然である以外にも、属性が追加されても修正不要というメリットがある


### どこまで値オブジェクトにするか

コンテキストによるので一概には言えない

### 値オブジェクトにするモチベーション

利点

>- 表現力を増す

```csharp=
var modelNumber = "a20421-100-1";
var modelNumber = new ModelNumber("a20421-100-1")
```

>- 不正な値を存在させない

```csharp=
// passwordが文字列の場合、コントローラー内
var password = "hoge"
if (password.length < 8) {
   throw new Exception("異常な値です");
}

// passwordが値オブジェクトの場合
var password = new Password("hoge")  // この時点でthrowされる
```

>- 誤った代入を防ぐ
>- ロジックの散在を防ぐ

## エンティティ

値オブジェクトと対をなすドメインオブジェクト

>両者の違いは同一性によって識別されるか否かです

>- 可変である
>- 同じ属性であっても区別される
>- 同一性をもつ

例えば、人間がよく例に出されます

#### 可変である

身長や体重は生活のなかで変化します

```csharp=
var morifuji = new Person(170)  // 身長170cm
morifuji.changeHeight(170.5)
```

#### 同じ属性であっても区別される

例えば自分と同姓同名の人がいても、自分とは区別されます（されるべきです）。現実では自明ですが、システムの中では識別子というものを持ちます。


#### 同一性をもつ

身長が変わったとしても変化前と変化後で **識別子**をもつことによって同一性をもちます


### どこまでエンティティにするか

ドメインオブジェクトはどういう基準でエンティティまたは値オブジェクトとして定義するか

>ライフサイクルが存在し、そこに連続性が 存在するかというのは大きな判断基準になります。

>作成されて生を受け、削除されて死を迎える。まさにユーザはライフサイクルを もち、連続性のある概念です。ユーザはエンティティで間違いなさそうです。


逆に言うと、連続性のないものは値オブジェクトとして定義するとシステムがシンプルに保たれる

結局はこの基準もコンテキストに依存しており、**車のタイヤはドライバーからすると「値オブジェクト」。タイヤ工場からみると「エンティティ」になる**
