Upgrade to Pro — share decks privately, control downloads, hide ads and more …

たのしいドメイン駆動設計: 序 / Enjoy domain driven design : ZYO

たのしいドメイン駆動設計: 序 / Enjoy domain driven design : ZYO

自分の開発に対する姿勢を根本的に変えたドメイン駆動設計(DDD)。ぜひみんなにもその面白さを知ってもらいたい!と思い社内向け資料を作成、さらにSpeakerDeckにて公開としました。
たのしんでご覧ください!

関連note記事はこちら:https://note.com/jgc_parallel/n/n17db4b63affe

JGC Parallel Technologies

September 19, 2023
Tweet

Other Decks in Programming

Transcript

  1. 目次 • はじめに • ドメイン駆動設計とは? • 現実世界の “モデル” をつくる •

    コーディングによる実装例 • 世界を “表現” する開発手法 2
  2. はじめに • 自分の開発に対する姿勢を根本的に変えたドメイン駆動設計 (DDD)。 ぜひみんなにもその面白さを知ってもらいたい! • DDDはもとより、一人でも多くの社員に設計やオブジェクト指向の面白さ、 便利さ、奥深さを知ってもらいたい。 (特にWeb系のメンバー) •

    今回は触りにあたるので、具体的な実装方法はざっと紹介するに留める。 • 前提知識として、オブジェクト指向に関する入門程度の知識は理解してい るものとする。 • 「Dogクラスに“わんわん” と出力するBarkメソッドを実装すると、『”わんわん”と吠 える振る舞いを持つ犬』のモデルが定義できる」みたいな概念がわかればOK。 4
  3. • 「ドメイン駆動設計」= Domain-Driven Design (DDD) • ソフトウェア開発において、ドメインの知識を中心に置く設計手法。 • 「ドメイン」は日本語で「分野」「領域」の意味。 DDDではソフトウェアが扱う「業務分野に関する分野・領域」を指す。

    • 銀行のシステムだと、口座・預金・振込といったモノやコトの概念。 • 日揮の建設に関するシステムだと、各種の業務コードや図面に関する概念。 ドメイン駆動設計とは?
  4. 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 境界づけられたコンテキストの内部におけるユビキタス言語を用いること
  5. 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
  6. ここに普通の大学ノートが一冊ある。 このノートはどんな意味を持っているだろうか? 一冊のノートが持つ意味 罫線はズレてないか? 全部のページがしっかり綴 じられているか? 傷や汚れはないか? 価格はどれくらいか? 在庫量はどれくらいか? どこの棚に何冊並べるか?

    中にどんな内容が書かれて いるか? いつ書かれたノートか? 誰が書いたノートか? 製造者は 品質に関する情報に 着目する 小売店は 商品としての情報に 着目する 利用者は どのように 使われているかに 着目する
  7. モノやコトは様々な意味を持つ • 一冊のどこにでもあるノートにさえ、多くの意味や解釈 が生じうる。 • これは何をするためのモノか? • (自分にとって) どんな属性や情報を持っているか? •

    誰が・どのように・いつ関わったモノか? • 同じモノやコトでも、扱う人間が関わる領域によって、 どの部分に着目するか・どんな意味を見出すかは異なる。 • モノやコトの意味を規定する領域 (文脈) を分析すると、 DDDにおいて核となるドメイン知識 が見えてくる。 13
  8. ドメイン知識を “モデル” にする • 先に挙げたノートにはたくさんの解釈がありうるが、 ノート自体はあくまで「記号」に過ぎず、意味付けする文脈が必要。 • 極端な話、猫はノートをノートとして解釈しない。 (解釈できる猫もいるかもしれないが……) •

    関心事の文脈が定まってないままだと、モノやコトが持つ意味は曖昧になってし まう。曖昧なままだとソフトウェアでは扱えない。 • DDDでソフトウェアを作る際、まずはユーザーの関心事の領域 (ドメイン) に応じ てモノやコトに関する情報を取捨選択し、概念として一般化する必要がある。 • ドメインに応じて抽象化された知識の概念を ドメインモデル と呼ぶ。 14
  9. ドメインモデルを作ってみる • このノートを「文房具店から見た一商品」として見て、商品の在庫状況のデータを管理す るソフトウェアを想定したい。 • 実際に現場の店舗で働く担当者 (≒ドメインエキスパート) から話を聞き出した結果、 商品の在庫状況について以下のような情報を扱いたいことがわかった。 15

    • 倉庫内に商品の在庫がどれだけあるかを知りたい。 • 複数の棚や倉庫に保管されているケースもありうる。 • 商品がどの陳列棚にどれだけあるかを知りたい。 • 複数の場所や店舗に陳列されているケースもありうる。 • お取り寄せ商品の場合、自分の店舗に届く予定日も知りたい。 • 他の店舗や倉庫に在庫がある場合、発送元の拠点エリアをもとに計算したお届け予定 日を知りたい。 • どの拠点にもない場合、現時点の入荷予定日をもとにした情報を知りたい。 • どの商品が・いつ・どの倉庫に到着予定なのかも確認できれば嬉しい。
  10. この要件を構成するドメインを「在庫管理ドメイン」としてモデル化してみる。 16 在庫管理のドメインモデル 在庫管理ドメイン 入荷予定品目 注文コード 到着予定日 商品 商品コード 商品名

    価格 カテゴリ 在庫状況 数量 保管場所 棚番号 倉庫 陳列状況 数量 陳列棚 棚番号 店舗 拠点エリア 都道府県 注: あくまでざっくりとした例なので、要件と比べて不十分なところがあっても大目に見てください><
  11. ドメインモデルからドメインオブジェクトへ • ドメインモデルを作ることで、ドメインに存在するモノやコトの 関係性についての知識を表現できた。 • このモデルを実際に動くコードとして表現したものを ドメインオブジェクト と呼ぶ。 • ドメインオブジェクトの設計モデルは、UML図などで表現される

    クラス同士の関係図などによって表現できる。 この段階から実装に関する関心事を意識することになる。 • DB設計と混同されやすいが、ドメインオブジェクトの設計と DB設計は必ずしも一致するとは限らないので注意。 • 例: コードで表現するドメインオブジェクトは同一でも、 性能重視 or 安全性重視、RDB or NoSQL……などの選択によって、 その下部にあるDBの設計は違ってくる。 17
  12. • 先の例をもとにして、簡易的に 商品の出庫記録の登録処理 を組んでみる。 • 実装には 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
  13. 何も考えずに組むと… (手続き型・技術駆動開発) 業務ロジックの流れが 本来業務知識とは関係がない FWの事情に依存している (生SQLなども直接書けてしまう!) 業務ロジックの処理が DBやFWが絡む処理と 密結合になっている 関心事の種類が違う処理同士が

    同じメソッドの内部でだらだらと 書かれている 入力値の検証手順をはじめとして 業務知識がベタ書きされている 似たような処理を至る所に書きがち どこに何が書かれているか分かりにくい デバッグや仕様変更の際、問題の切り分けや修正箇所の見極めが難しい 改修しようとすると変更範囲が無駄に広くなり、バグが出やすい テストコードが書きにくい(書けない)
  14. DDDで組むと、こんなに変わる! 23 内部のデータは 現実世界の業務知識に対応した モデルにカプセル化されている 入力値の検証をはじめとして モノやコトを表すクラス自体が 意味のある振る舞いを持つ インターフェイスや例外を使って 業務フローとは直接関係のない

    FWやDB周りの関心事を 別の層に委譲している (疎結合) 作業記録日など、他のモジュール でも再利用可能なドメインオブ ジェクトを定義して使っている コード自体が業務フローを説明するドキュメントになっている 問題の切り分けや修正箇所の見極めが容易 改修の際に変更範囲が絞りやすく、バグも出にくい テストコードが書きやすい
  15. 今回使った実装パターンについて • 今回のコーディング例では、DDDでよく使われる下記のパターンを使用した。 • エンティティ: リポジトリに出し入れする単位となるモノやコトのオブジェクト • 値オブジェクト: ドメインモデルに対応する振る舞いや意味を持つオブジェクト •

    リポジトリ: ドメインオブジェクトと外部のデータストア (DB, ファイルストレージ, Web APIなど) の間を繋ぐ橋渡し役 • アプリケーションサービス: ユースケースに対応した処理全体の流れを定義するモジュール • オニオンアーキテクチャ: ドメイン層を核として、システム全体を役割に応じた複数の層に分ける枠組み • 具体的な実装方法について、今回は割愛する。次回のLT以降で解説予定。 • まだ細かいことは分からなくても 「現実世界のモノやコトの概念を反映した上で、分かりやすいコードを書ける」 という効果さえ理解しておけばOK! 24
  16. 現実世界を映し出す設計 • DDDによって、ソフトウェアのコードは現実世界のドメインをより忠実に記述す るモデルとなっていく。 • 単なるデータ置き場+操作処理から、データ自体が振る舞いや判断基準を持つ設計に変化し、 現実世界における意味が反映されたモデルとなる。 • 知識・モデル・コードが、お互いにフィードバックしあって成長していく。 •

    現実世界のドメインの変化に応じて、ドメインモデルやコードが成長して深まっていく。 • 開発者がドメイン知識をモデルやコードにする過程で、顧客が気づかなかった新たなドメイン 知識が生まれてくることも。 • 技術ではなくドメインを中心に考えるため、要件や仕様の変更に強く、開発者と 非開発者との間のコミュニケーションもシームレスになっていく。 28
  17. 文芸的プログラミングとしてのDDD • ここ一年ほどDDDでシステムを組む中で、改めて実感したこと: 「プログラミングは、芸術であり、文学である。」 (Donald E. Knuthによる『文芸的プログラミング』のコンセプト) • 絵画・小説・映画・音楽などの芸術は、 造り手の感性で世界を分析・解釈し、その解釈をメディアに応じて表現し、

    鑑賞者に影響を与える。 • DDDに基づいて作られたソフトウェアは、 顧客や開発者の視点で世界を分析・解釈し、そのモデルを動くコードとし て表現し、利用者と開発者の双方に影響を与える。 • 技術はもちろん、技術以外でも自分が学んだ知識が実際に動く コードに埋め込まれ、影響を与えることができるという実感。 ⇒ものづくりの楽しさや、知的好奇心への刺激も感じる! 29