$30 off During Our Annual Pro Sale. View Details »

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

    View Slide

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

    View Slide

  3. はじめに
    3

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  7. 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
    境界づけられたコンテキストの内部におけるユビキタス言語を用いること

    View Slide

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

    View Slide

  9. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  19. • 先の例をもとにして、簡易的に 商品の出庫記録の登録処理 を組んでみる。
    • 実装には 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  31. 参考記事一覧
    • ドメイン駆動設計とは何なのか? ユーザーの業務知識をコードで表現する開発手
    法について
    • 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

    View Slide