ドメイン駆動設計入門を読んで 前半
株式会社ネクストビートで「おもてなしHR」という地方創生に関わる、宿泊業界に特化した転職支援プロダクトの開発をしております、清水琢巳と申します。
今回は弊社の夕学という制度を活用して、「ドメイン駆動設計入門」を学んだので、そのことについて、ブログ2本立てで、まとめたいと思います。
ちなみに、夕学とは株式会社ネクストビートの開発部に整備されている福利厚生の一つで、エンジニアが業務時間内に自己学習できる時間です。個人学習の時間がメインですが、不定期で勉強会も開催されています。
アジェンダ
- ドメイン駆動設計とは
- 大切な3つの概念
- 値オブジェクト
- エンティティ
- ドメインサービス
- まとめ
- 参考文献
- 告知
1. ドメイン駆動設計とは
ドメイン駆動設計とは「ソフトウェア利用者を取り巻く環境と実装を結びつけることを目的として考えられた設計手法」です。
とはいっても、とても抽象的でわかりにくいと思いますので、一つ一つ紐解いていきます。
2. 大切な3つの概念
まずドメイン駆動設計における大切な3つの概念について説明します。
その概念とは「ドメイン」「モデル」「ドメインモデル」の3つです。
ドメイン駆動設計は「ドメイン」(ソフトウェア利用者を取り巻く環境)を理解し、現実世界の「モデル」を実装に落とし込むため「ドメインモデル」(ドメインによってモデリングされたモデル)に変換することから始まります。
それにより、一つ一つの概念の責務が明確になり、整理されたコードを書くことができるようになります。
2.1. ドメインとは
1つ目の「ドメイン」とは「プログラムを適用する対象となる領域」のことを指します。
私の開発している「おもてなしHR」であれば、「宿泊業界を専門とした就職・転職に関わる領域」がドメインになります。
2.2. モデルとは
2つ目の「モデル」とは「現実の事象や概念を抽象化した概念」のことを指します。
こちらは名詞になっているものを思い浮かべるとわかりやすいです。「車・ペン・人」のように言葉だけで何を指しているかわかりますよね。これらが「モデル」になります。
2.3. ドメインモデルとは
3つ目の「ドメインモデル」とは「ドメインの概念からモデリングされたモデル」のことを指します。
前述のモデルの「ペン」という概念を取り上げて説明すると、小説家にとって「ペン」は、「小説を書く道具」になりますが、文具屋にとっては「一つの商品」です。はたまた僕の大好きなスプラトゥーンでは「一つの武器」として扱われます。このようにそれぞれの領域によって違った概念でモデリングされるものが「ドメインモデル」になります。
3. 値オブジェクト
値オブジェクトとは、システム固有の値を指します。
例えば氏名を一つの値で表すか、姓と名を分けてそれぞれ一つの値として扱うかはシステムによって異なります。このように概念は同じでもその値の扱い方はシステムによって違うことがあります。このようにそのシステムで利用される固有の値を「値オブジェクト」と呼びます。
3.1 値オブジェクトの性質
値オブジェクトには以下の3つの性質があります。
- 不変である
- 交換が可能である
- 等価性によって比較される
3.1.1. 不変である
値が自由に変更できてしまうことは、開発者は安心してその値を使用できないことにつながります。「山田」という人がある時突然「佐藤」という名前に変わってしまったら混乱を引き起こすことになります。もちろん可変のプログラムを書くことも可能ですが、可変の値を使用する場合は十分に注意するべきです。そのため値は不変であることが求められ、不変だからこそ安全に利用することができます。
3.1.2. 交換が可能である
先ほど不変の話をしておいて次は、交換という話になり、矛盾を感じるかもしれませんがこれも大切な性質の一つです。開発者は値を交換するときに代入という表現手法を用いています。
しかし「不変」の性質を持つ値はそれ自体を変更することはできません。そのため値を変更する場合は代入を用いて変更するわけです。
値が不変になっていることで、代入以外の手法では値を変更することができなくなっている点がこの性質の重要なポイントです。
3.1.3. 等価性によって比較される
数字や文字、同じ性質を持った値は以下のように比較することができます。
値オブジェクトを比較する場合は比較する基準を設けることで、比較できるようにします。Nameクラスが同じかどうか比較したい場合は、姓と名がそれぞれ同じ文字列を使用している場合にtrueを返すメソッドを設けることで、比較を可能にします。
3.2. 値オブジェクトを使用するメリット
値オブジェクトを使用することで以下のメリットが享受されます。
- 表現力が増す
- 不正な値を存在させない
- 誤った代入を防ぐ
- ロジックの散在を防ぐ
例えば表現力に関しては、先ほどから使用しているNameクラスのように氏名という値を表現するとき、姓と名に分けて表現することや、電話番号を080 + 1234 + 5678の3つのブロックに分けて表現することなどが挙げられます。
不正な値を存在させないことはクラスにガード節を記載することで、クラス生成時に不正な値を弾くことができます。
誤った代入を防ぐことに関しては、値オブジェクトという形で、値に対して型を定義することで、違う型を代入できなくすることができます。
ロジックの散在は、値オブジェクトを定義しておくことで、その値オブジェクトへの関心ごとはその値オブジェクトに持たせるようになり、一ヶ所に関心事を集約させることができます。もし値オブジェクトがなければ、無秩序に使用箇所ごとにロジックが定義されてしまい管理が難しくなってしまいますからね。
3.3. 値オブジェクトまとめ
値オブジェクトは、それを定義することでそれ自身がどのような値なのか主張できます。また値オブジェクトにルールや振る舞いをまとめることで、保守やメンテナンスがしやすくなり、結果的にコード自体・値オブジェクト自体が、ドキュメントとして機能するようになります。僕はこの値オブジェクトが、ドメイン駆動設計を考える上で初めの一歩となる概念であると思いました。
4. エンティティ
エンティティはドメインモデルを実装したドメインオブジェクトの一種です。
ただ、3.で解説した「値オブジェクト」もドメインモデルを実装したドメインオブジェクトです。両者の違いは「同一性(identity)」によって識別されるか否かです。
例えば値オブジェクトで取り上げた名前は、姓と名で構成されており、どちらかが変われば名前自体も別物となります。この様に値が変われば、そのもの自体も変わるものは、同一性では評価されないため、値オブジェクトです。
しかしながら、ユーザーという概念は如何でしょうか。年齢や、電話番号、emailなどそのユーザーを表す要素はたくさんありますが、その値が変更されてもそのユーザー自体は変わりません。この様にユーザーという概念は、同一性で評価されるため「エンティティ」に属します。
値オブジェクトとエンティティは概念として、とてもよく似ているものなので、同一性で識別されるか否かと言っても、悩むことは多いです。そんな時はもう一つの判断基準を用いるのも良いと思います。それは「ライフサイクル」があるかどうかです。ユーザーは、登録や退会など時間の流れによってユーザーの状態が変わります。
この様に2つほど判断基準は存在するのですが、それでもその概念がどちらに属するのかはっきりしない場合は、値オブジェクトとして扱い不変にしておくことです。その理由はエンティティは作成されてから削除されるまで、変化する可能性があるためバグの原因となりやすいからです。それを防ぐためにも、初めは値オブジェクトとし、シンプルなコード(概念)として扱うべきです。
5. ドメインサービス
ドメインサービスとは、「値オブジェクトやエンティティに定義すると不自然な振る舞いを記述するオブジェクト」です。
例えばユーザーというエンティティがある時、ユーザー名の文字数の上限や下限はエンティティの振る舞いとして定義しても違和感はありません。しかし、ユーザー名の重複を許さないとしたときに、そのユーザー名の重複をチェックする振る舞いをエンティティに持たせるというのは違和感があります。こういった違和感のある振る舞いを持たせるのがドメインサービスになります。
ただドメインサービスはとても汎用的なため次の点に注意が必要です。全ての振る舞いはドメインサービスに記述できてしまうため、値オブジェクトやエンティティに対して定義するべき振る舞いまでまとめて定義できてしまう点です。
ただ、それでは値オブジェクトやエンティティに対するドメインのルールがわからなくなり、オブジェクト指向からも外れることになってしまうため、あくまで、値オブジェクトやエンティティに定義すると不自然な振る舞いのみをドメインサービスに記述するように意識してください。振る舞いの定義場所に迷った場合は、値オブジェクトやエンティティに定義するようにしておくと、振る舞いが散在せずに関連するルールをまとめておくことができます。
6. まとめ
今回はドメイン駆動設計入門を読んで学んだことの50%をまとめてみました。まだまだ設計に関する知識は浅い部分はありますが、ドメイン駆動設計の概念を理解することでかなりコードを書くスピードや、レビューの精度が向上したと感じています。また、そんな知識が浅い私でも理解しながら読み進めることができた本がこちらの「ドメイン駆動設計入門」です。ドメイン駆動設計ってなに?聞いたことない!という方にはとてもお勧めの1冊ですので、ぜひご一読を!
後半もお楽しみに!
7. 参考文献
ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本 成瀬允宣著
8. 告知
We are hiring!
本記事をご覧いただき、ネクストビートの技術や組織についてもっと話を聞いてみたいと思われた方、カジュアルにお話しませんか?
・今後のキャリアについて悩んでいる
・記事だけでなく、より詳しい内容について知りたい
・実際に働いている人の声を聴いてみたい
など、まだ転職を決められていない方でも、ネクストビートに少しでもご興味をお持ちいただけましたら、ぜひカジュアルにお話しましょう!
🔽申し込みはこちら
https://hrmos.co/pages/nextbeat/jobs/1000008
また、ネクストビートについてはこちらもご覧ください。