Slide 1

Slide 1 text

たのしいドメイン駆動設計: 序 ソフトウェアで “現実世界を表現” しよう! 日揮パラレルテクノロジーズ Webアプリエンジニア Harakazu 2023/9/4 JPT LT会

Slide 2

Slide 2 text

目次 • はじめに • ドメイン駆動設計とは? • 現実世界の “モデル” をつくる • コーディングによる実装例 • 世界を “表現” する開発手法 2

Slide 3

Slide 3 text

はじめに 3

Slide 4

Slide 4 text

はじめに • 自分の開発に対する姿勢を根本的に変えたドメイン駆動設計 (DDD)。 ぜひみんなにもその面白さを知ってもらいたい! • DDDはもとより、一人でも多くの社員に設計やオブジェクト指向の面白さ、 便利さ、奥深さを知ってもらいたい。 (特にWeb系のメンバー) • 今回は触りにあたるので、具体的な実装方法はざっと紹介するに留める。 • 前提知識として、オブジェクト指向に関する入門程度の知識は理解してい るものとする。 • 「Dogクラスに“わんわん” と出力するBarkメソッドを実装すると、『”わんわん”と吠 える振る舞いを持つ犬』のモデルが定義できる」みたいな概念がわかればOK。 4

Slide 5

Slide 5 text

ドメイン駆動設計とは? 5

Slide 6

Slide 6 text

• 「ドメイン駆動設計」= Domain-Driven Design (DDD) • ソフトウェア開発において、ドメインの知識を中心に置く設計手法。 • 「ドメイン」は日本語で「分野」「領域」の意味。 DDDではソフトウェアが扱う「業務分野に関する分野・領域」を指す。 • 銀行のシステムだと、口座・預金・振込といったモノやコトの概念。 • 日揮の建設に関するシステムだと、各種の業務コードや図面に関する概念。 ドメイン駆動設計とは?

Slide 7

Slide 7 text

DDDの四大原則 DDDの提唱者であるEric Evansが DDDの四大原則 を示している: 7 • Focus on the core complexity and opportunity in the domain ドメインにおいて核となる複雑さや機会に向き合うこと • Explore models in a collaboration of domain experts and software experts ドメインエキスパートとソフトウェアエキスパートのコラボレーションの中で モデルを探求すること • Write software that expresses those models explicitly 探求されたモデルを正確に表現するソフトウェアを書くこと • Use a ubiquitous language inside a bounded context 境界づけられたコンテキストの内部におけるユビキタス言語を用いること

Slide 8

Slide 8 text

……って言われても、ぜんぜんわからん!!! • ドメインの複雑さ?ドメインエキスパート?モデルの探求? 境界づけられたコンテキスト?ユビキタス言語? • DDDには独特の用語や概念が多数存在するが、いきなり全部覚える必要はない。 • 原典であるエヴァンスのDDD本もかなり難解。 (実のところ、発表者自身も長い間積読中だったりする) • でも、実際噛み砕けばそこまで怖くない (はず)! DDDに入門するなら、まずはやさしい入門向けの本や記事から始めましょう。 8

Slide 9

Slide 9 text

DDD入門におすすめの本/Webサイト • 成瀬 允宣. 「ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の 基本」 • https://www.amazon.co.jp/dp/479815072X • 増田 亨. 「現場で役立つシステム設計の原則 変更を楽で安全にするオブジェクト 指向の実践技法」 • https://www.amazon.co.jp/dp/477419087X • 松岡さん (@little_hand_s) のブログやYouTube • ブログ (little hands’ lab): https://little-hands.hatenablog.com/ • YouTube: https://www.youtube.com/channel/UCbHtbIUxtfGjrDy1WcqxExw 9

Slide 10

Slide 10 text

DDDの四大原則 (超訳版) 10 • ユーザーの活動や関心事が存在するドメインに対する理解を深めよう。 • 業務知識の専門家と協力してドメインを日々分析し、ソフトウェアに用い るモデルの構想を継続的に練り続けよう。 • 得られたモデルをもとにして、ドメイン知識を実際に動くコードに反映し よう。 • 得られたモデルをもとにして、開発者・専門家・顧客の全員に通じる共通 の用語集を作ろう。 その共通用語を普段のやり取りやコーディング時の命名に使おう。

Slide 11

Slide 11 text

現実世界の “モデル”をつくる 11

Slide 12

Slide 12 text

ここに普通の大学ノートが一冊ある。 このノートはどんな意味を持っているだろうか? 一冊のノートが持つ意味 罫線はズレてないか? 全部のページがしっかり綴 じられているか? 傷や汚れはないか? 価格はどれくらいか? 在庫量はどれくらいか? どこの棚に何冊並べるか? 中にどんな内容が書かれて いるか? いつ書かれたノートか? 誰が書いたノートか? 製造者は 品質に関する情報に 着目する 小売店は 商品としての情報に 着目する 利用者は どのように 使われているかに 着目する

Slide 13

Slide 13 text

モノやコトは様々な意味を持つ • 一冊のどこにでもあるノートにさえ、多くの意味や解釈 が生じうる。 • これは何をするためのモノか? • (自分にとって) どんな属性や情報を持っているか? • 誰が・どのように・いつ関わったモノか? • 同じモノやコトでも、扱う人間が関わる領域によって、 どの部分に着目するか・どんな意味を見出すかは異なる。 • モノやコトの意味を規定する領域 (文脈) を分析すると、 DDDにおいて核となるドメイン知識 が見えてくる。 13

Slide 14

Slide 14 text

ドメイン知識を “モデル” にする • 先に挙げたノートにはたくさんの解釈がありうるが、 ノート自体はあくまで「記号」に過ぎず、意味付けする文脈が必要。 • 極端な話、猫はノートをノートとして解釈しない。 (解釈できる猫もいるかもしれないが……) • 関心事の文脈が定まってないままだと、モノやコトが持つ意味は曖昧になってし まう。曖昧なままだとソフトウェアでは扱えない。 • DDDでソフトウェアを作る際、まずはユーザーの関心事の領域 (ドメイン) に応じ てモノやコトに関する情報を取捨選択し、概念として一般化する必要がある。 • ドメインに応じて抽象化された知識の概念を ドメインモデル と呼ぶ。 14

Slide 15

Slide 15 text

ドメインモデルを作ってみる • このノートを「文房具店から見た一商品」として見て、商品の在庫状況のデータを管理す るソフトウェアを想定したい。 • 実際に現場の店舗で働く担当者 (≒ドメインエキスパート) から話を聞き出した結果、 商品の在庫状況について以下のような情報を扱いたいことがわかった。 15 • 倉庫内に商品の在庫がどれだけあるかを知りたい。 • 複数の棚や倉庫に保管されているケースもありうる。 • 商品がどの陳列棚にどれだけあるかを知りたい。 • 複数の場所や店舗に陳列されているケースもありうる。 • お取り寄せ商品の場合、自分の店舗に届く予定日も知りたい。 • 他の店舗や倉庫に在庫がある場合、発送元の拠点エリアをもとに計算したお届け予定 日を知りたい。 • どの拠点にもない場合、現時点の入荷予定日をもとにした情報を知りたい。 • どの商品が・いつ・どの倉庫に到着予定なのかも確認できれば嬉しい。

Slide 16

Slide 16 text

この要件を構成するドメインを「在庫管理ドメイン」としてモデル化してみる。 16 在庫管理のドメインモデル 在庫管理ドメイン 入荷予定品目 注文コード 到着予定日 商品 商品コード 商品名 価格 カテゴリ 在庫状況 数量 保管場所 棚番号 倉庫 陳列状況 数量 陳列棚 棚番号 店舗 拠点エリア 都道府県 注: あくまでざっくりとした例なので、要件と比べて不十分なところがあっても大目に見てください><

Slide 17

Slide 17 text

ドメインモデルからドメインオブジェクトへ • ドメインモデルを作ることで、ドメインに存在するモノやコトの 関係性についての知識を表現できた。 • このモデルを実際に動くコードとして表現したものを ドメインオブジェクト と呼ぶ。 • ドメインオブジェクトの設計モデルは、UML図などで表現される クラス同士の関係図などによって表現できる。 この段階から実装に関する関心事を意識することになる。 • DB設計と混同されやすいが、ドメインオブジェクトの設計と DB設計は必ずしも一致するとは限らないので注意。 • 例: コードで表現するドメインオブジェクトは同一でも、 性能重視 or 安全性重視、RDB or NoSQL……などの選択によって、 その下部にあるDBの設計は違ってくる。 17

Slide 18

Slide 18 text

コーディングによる 実装例 18

Slide 19

Slide 19 text

• 先の例をもとにして、簡易的に 商品の出庫記録の登録処理 を組んでみる。 • 実装には C# ^10.0 + ASP.NET Core (Web API) + EFCore + SQL Serverを用いる。 • ユーザーからの入力値は、商品コード・出入庫の数量・保管場所(=棚番号と倉庫のIDのセット)。 • 商品コードはURL内のスラッグに、それ以外はPOST時のBodyに入力される。 • DB設計は下記のER図に従う。 実際に組んでみよう 在庫管理テーブル Product Id : int «generated» ProductCode : string Name : string Price : int Outbound Id : int «generated» ProductId : int «FK» StockRackId : int «FK» Quantity : int ShippedAt : DateTime Inbound Id : int «generated» ProductId : int «FK» StockRackId : int «FK» Quantity : int StockedAt : DateTime StockRack Id : int «generated» RackCode : string WarehouseId : int «FK» Warehouse Id : int «generated» Name : string

Slide 20

Slide 20 text

何も考えずに組むと… (手続き型・技術駆動開発) 業務ロジックの流れが 本来業務知識とは関係がない FWの事情に依存している (生SQLなども直接書けてしまう!) 業務ロジックの処理が DBやFWが絡む処理と 密結合になっている 関心事の種類が違う処理同士が 同じメソッドの内部でだらだらと 書かれている 入力値の検証手順をはじめとして 業務知識がベタ書きされている 似たような処理を至る所に書きがち

Slide 21

Slide 21 text

何も考えずに組むと… (手続き型・技術駆動開発) 業務ロジックの流れが 本来業務知識とは関係がない FWの事情に依存している (生SQLなども直接書けてしまう!) 業務ロジックの処理が DBやFWが絡む処理と 密結合になっている 関心事の種類が違う処理同士が 同じメソッドの内部でだらだらと 書かれている 入力値の検証手順をはじめとして 業務知識がベタ書きされている 似たような処理を至る所に書きがち どこに何が書かれているか分かりにくい デバッグや仕様変更の際、問題の切り分けや修正箇所の見極めが難しい 改修しようとすると変更範囲が無駄に広くなり、バグが出やすい テストコードが書きにくい(書けない)

Slide 22

Slide 22 text

DDDで組むと、こんなに変わる! 22 内部のデータは 現実世界の業務知識に対応した モデルにカプセル化されている 入力値の検証をはじめとして モノやコトを表すクラス自体が 意味のある振る舞いを持つ インターフェイスや例外を使って 業務フローとは直接関係のない FWやDB周りの関心事を 別の層に委譲している (疎結合) 作業記録日など、他のモジュール でも再利用可能なドメインオブ ジェクトを定義して使っている

Slide 23

Slide 23 text

DDDで組むと、こんなに変わる! 23 内部のデータは 現実世界の業務知識に対応した モデルにカプセル化されている 入力値の検証をはじめとして モノやコトを表すクラス自体が 意味のある振る舞いを持つ インターフェイスや例外を使って 業務フローとは直接関係のない FWやDB周りの関心事を 別の層に委譲している (疎結合) 作業記録日など、他のモジュール でも再利用可能なドメインオブ ジェクトを定義して使っている コード自体が業務フローを説明するドキュメントになっている 問題の切り分けや修正箇所の見極めが容易 改修の際に変更範囲が絞りやすく、バグも出にくい テストコードが書きやすい

Slide 24

Slide 24 text

今回使った実装パターンについて • 今回のコーディング例では、DDDでよく使われる下記のパターンを使用した。 • エンティティ: リポジトリに出し入れする単位となるモノやコトのオブジェクト • 値オブジェクト: ドメインモデルに対応する振る舞いや意味を持つオブジェクト • リポジトリ: ドメインオブジェクトと外部のデータストア (DB, ファイルストレージ, Web APIなど) の間を繋ぐ橋渡し役 • アプリケーションサービス: ユースケースに対応した処理全体の流れを定義するモジュール • オニオンアーキテクチャ: ドメイン層を核として、システム全体を役割に応じた複数の層に分ける枠組み • 具体的な実装方法について、今回は割愛する。次回のLT以降で解説予定。 • まだ細かいことは分からなくても 「現実世界のモノやコトの概念を反映した上で、分かりやすいコードを書ける」 という効果さえ理解しておけばOK! 24

Slide 25

Slide 25 text

現実世界を表現するオブジェクト指向 • DDDには難解な概念や考え方が多いのも事実だが、技術的な観点で言うと、その 狙いはとてもシンプルである。 ⇒「モノやコトの性質・関係性に着目してコードを表現する」という オブジェクト指向の思想を現実世界のドメインに適用する手法の体系と言える。 • ドメイン層からDBやFWといった特定の技術由来の要素を廃するのも、この思想 に基づいたアプローチと言える。 ソフトウェアの存在があろうとなかろうと、業務のドメイン自体は現実の世界に存在する。 当然ながら、現実世界のドメインには「システムのデータがどのように・どこに保存されるのか」 といった知識は含まれていない。 そのような関心事は、ドメインが表現される層とは別の層に切り分けて配置されることが望ましい。 25

Slide 26

Slide 26 text

世界を “表現” する 開発手法 26

Slide 27

Slide 27 text

私がドメイン駆動設計を推す理由 ドメイン駆動設計の面白さは、 多様な姿を見せる現実世界を分析し、 動くコードとして「表現」する過程 にある!

Slide 28

Slide 28 text

現実世界を映し出す設計 • DDDによって、ソフトウェアのコードは現実世界のドメインをより忠実に記述す るモデルとなっていく。 • 単なるデータ置き場+操作処理から、データ自体が振る舞いや判断基準を持つ設計に変化し、 現実世界における意味が反映されたモデルとなる。 • 知識・モデル・コードが、お互いにフィードバックしあって成長していく。 • 現実世界のドメインの変化に応じて、ドメインモデルやコードが成長して深まっていく。 • 開発者がドメイン知識をモデルやコードにする過程で、顧客が気づかなかった新たなドメイン 知識が生まれてくることも。 • 技術ではなくドメインを中心に考えるため、要件や仕様の変更に強く、開発者と 非開発者との間のコミュニケーションもシームレスになっていく。 28

Slide 29

Slide 29 text

文芸的プログラミングとしてのDDD • ここ一年ほどDDDでシステムを組む中で、改めて実感したこと: 「プログラミングは、芸術であり、文学である。」 (Donald E. Knuthによる『文芸的プログラミング』のコンセプト) • 絵画・小説・映画・音楽などの芸術は、 造り手の感性で世界を分析・解釈し、その解釈をメディアに応じて表現し、 鑑賞者に影響を与える。 • DDDに基づいて作られたソフトウェアは、 顧客や開発者の視点で世界を分析・解釈し、そのモデルを動くコードとし て表現し、利用者と開発者の双方に影響を与える。 • 技術はもちろん、技術以外でも自分が学んだ知識が実際に動く コードに埋め込まれ、影響を与えることができるという実感。 ⇒ものづくりの楽しさや、知的好奇心への刺激も感じる! 29

Slide 30

Slide 30 text

世界を “表現” するソフトウェア開発 30 ドメイン駆動設計を学ぶと、 ソフトウェア開発は 「世界を表現するアート」になる!

Slide 31

Slide 31 text

参考記事一覧 • ドメイン駆動設計とは何なのか? ユーザーの業務知識をコードで表現する開発手 法について • https://codezine.jp/article/detail/11968 • DDDを実践するための手引き(概論・導入編) • https://zenn.dev/kohii/articles/b96634b9a14897 • DDD Europe 2016 • https://www.zweitag.de/en/blog-article/ddd-europe-2016 31