Somurie Engineer's Blog

書籍「ドメイン駆動設計入門」をKotlin+TDDで試してみた感想

はじめに 成瀬さんの書籍「ドメイン駆動設計入門」を読んで気づいた点、ポイントをまとめました。 自分用メモなので新たに気づいた点や忘れかけていた点を洗い出しています。 実装に関してはKotlinとTDDを初めて使ってみました。普段はJavaがメインですが、Kotlinを使ってみての感想も後ろにまとめてあります。 書籍を読んで気づいた点・ポイント ドメイン駆動設計を選ぶ理由 ドメイン駆動設計は初期開発速度は劣るが、サービスの変化、開発途中における要件の変化などへの対応が柔軟。長期目線で見たときにドメイン駆動設計の優位性がある。 値オブジェクト 値オブジェクトの分割基準として、ドメイン内で分ける必要がある単位で分割する。ルールを作成する必要がある単位など、取り扱ううえでまとめる必要があるかがポイント。 細かくしすぎるとメンテナンス性が低くなる。 ある程度、不変性を保つことができる範囲で作成する。 値オブジェジェクトを使用することで使用法に強制力を持たせるため、バグ混入を防ぐことに繋がる。また、ロジックを1箇所に集めることになるため、メンテナンス性も高い。 エンティティ DB設計時にER図でエンティティという名が用いられるがドメイン駆動では別の意味を表している。 エンティティには値オブジェクトにはないライフサイクルの概念が存在する。すなわちエンティティはシステム利用中に値が変化したり削除されたりする。 ドメインサービス ドメイン駆動設計で表されるサービスはドメインサービスとアプリケーションサービスの2つ。明確に分ける必要がある。(エヴァンス本ではサービスは1括りである) ドメインサービスには値オブジェクトやエンティティに書くと不自然になるものを記述する。 値オブジェクトやエンティティと異なり自身のふるまいを変更する記述は書かれず、複数のドメインオブジェクト(エンティティ及び値オブジェクト)を横断して操作する処理を記述する。 エンティティに書くことができる処理をドメインサービスに書いてしまうとドメイン欠乏症に陥る。エンティティの責務をドメインサービスが奪わないようにする。 命名規則としては「ドメイン名 + Service」が良さそう。自分の知っているプラクティスではパッケージによってdomainやserviceを分けているが、本書ではXxxDomain.Services.XxxServiceのようにドメイン単位でサービスを分けてることを例に挙げている。 リポジトリ リポジトリはドメイン駆動設計以外でも頻繁に目にする考え方。オブジェクトの永続化、再構築を行う。 重複確認existsメソッドはリポジトリではなくドメインサービスに実装すべき。何をもって重複とするかはドメインの責務。 永続化する単位で処理を行う。一部しかupdateしない場合でも永続化単位を引数として受け取る。 リポジトリクラスを切り替えることでインメモリのDBを使用し、テストを行う記述があったがコーディング量が多くなるため接続先DBを切り替えるだけの方が実用的な気がした。 アプリケーションサービス ユースケースを実現するオブジェクト。メソッド1つがふるまい1つを表すイメージ。 アプリケーションの返り値がドメインの場合、プレゼンテーション層でドメインを操作される可能性がある。返り値は画面表示用のクラスにするなど、境界を保つことも検討する(クリーンアーキテクチャのイメージ)。開発コストや規模との兼ね合い。 updateのように何かしら命令を送る場合、引数を修正することを避けるためにcommandクラスというDTOを引数とすると疎結合になる。 凝集度を測る指標としてLCOMがある。インスタンス変数が全てのメソッドで使用されているかを基に測る指標。 インスタンス変数を使用しているメソッドが偏っている場合はクラス分割を検討する一因となる。 サービスとはクライアントのために何かを行うもの。自身のふるまいを持たない。 ドメインにおける活動をドメインサービス、アプリケーションとして成り立たせるためのサービスをアプリケーション・サービスといった形で領域を明確に分けする。 ファクトリ IDの採番はどこの責務か。DBをの自動採番、ファクトリ、リポジトリの3つが挙がっているが、自動採番することを開発者内の暗黙の了解とするのが最適としている。 著者はリポジトリの責務は永続化と再生成が主と考えているためリポジトリ内の採番を推奨していない。。 ドメインオブジェクトがふるまいとして定義できるようであればあるドメインオブジェクトが他のドメインオブジェクトを生成するようにファクトリをメソッドとして定義することができる。 データの整合性を保つ 整合性を保つための手段として特定の技術基盤に依存することは避けるべき。DBに頼った場合、整合性の条件変更の対応が漏れる可能性がある(例えばテーブル内のユニーク条件が変化した場合、プログラム上の記載がなくDBのユニークキー設定変更は漏れやすい) アプリケーションサービスでトランザクション管理をすると、RDBに依存していることになる。JavaのSpring上の実現方法としては、AOPを実現する@Transactionalアノテーションを付与することでメソッド内のトランザクション整合性を担保することができる。 アプリケーションを1から組み立てる 集約 DomainのクラスをRepositoryで永続化に使用するDataClassに変換する際、Domainのフィールドを直接取得するのではなく通知オブジェクトを経由してDataClassを生成するパターンがある。Domainのフィールドに直接アクセスさせないための強制力がかなり強い。 Scalaだとフィールドのアクセス権限をInterface単位で設定でき、Interfaceを実装するクラスからのアクセスのみを許可することができる。 リポジトリは集約の単位で作成する。永続化の単位が集約であるため。 集約の単位でデータをロックしてしまうため、大きすぎる集約は厳禁。 仕様 仕様を全てDomainクラスに盛り込んでしまうと肥大化してしまい変化が容易ではなくなる。 仕様クラス(〜Specificationクラス)として括りだすことで扱いやすくなる。(リポジトリに仕様クラスの処理を移譲するとパフォーマンス上の問題もある) 検索に関わる複雑・特殊な条件の場合はリポジトリを使わない方法もとり得る。ドメインの防衛を第一に考えず、アプリケーションの猟奇はプレゼンテーション(利用者の利便性)を第一に考える。例えばドメイン内の操作でN+1問題が発生しそうだったりページング処理などがあれば1回のSQLクエリで取得できるようにするなど、例外的な対応も検討する。 アーキテクチャ アーキテクチャはドメイン知識が流出しないように記述すべき箇所を示す方針。 レイヤードアーキテクチャはオブジェクトを4つの層(プレゼンテーション・アプリケーション・インフラストラクチャ・ドメイン)に分け、それぞれの層が責務を持つ。また、記載した4つの層の順に上位層から下位層へ依存が存在し、逆の依存は許されない。 ヘキサゴナルアーキテクチャはアプリケーションに対するその他のインターフェース・保存媒体を取り外しできるようにすることがコンセプト。インターフェースを利用して依存性逆転の原則を実現するため、レイヤードアーキテクチャとは依存関係が異なる。 クリーンアーキテクチャのコンセプトはヘキサゴナルアーキテクチャと同じ。ビジネスルールをカプセル化したモジュールを中心に据え、依存関係を制御する。加えて、具体的な実装方法を明示している。 アーキテクチャを適用することで開発方針が決まるため、システム開発中に考える問題を少なくすることができるため有用。 ドメイン駆動設計の扉を開こう ユビキタス言語を使う。updateなのかchangeなのか、システマチックな言葉ではなくドメインエキスパートが使う言葉に合わせる。 同じ言葉でも視点が変わることにより必要な属性は異なる。境界づけられたコンテキストを適用し、別のエンティティを作る方が賢明。大規模になればなるほど同一のエンティティで全ての動きを賄うことは困難。 Kotlinで試し書きした感想 総じて書きやすかったです。Javaよりコード記述量が少なく、nullSafeな書き方ができる点がDDDに向いているなと思います。 nullSafeだとコンパイルエラーとしてnull混入を防ぐことができる点は本当に助かります。 nullSafeな言語は記述量がかなり少ない。DDDに向いている 値オブジェクト書きやすい。プライマリコンストラクタが便利 safe call (?

BPStudy#141〜DDD(Domain Driven Design)実践の現場に参加してきた(DDD初研修)

参加背景 今月に入って本格的にDDDを学習中なのですが、対面で増田さんの話を聞いてみたく参加してみました。 進捗としては「現場で役立つシステム設計の原則」と「エヴァンス本」共に2〜3割程度を読み終えたところで、まだまだDDD初心者です笑 DDD初セミナーでテンション上がってるのでまとめ記事書いてみました。 研修概要 19時半から21時半のセミナーでした。会場は総武線千駄ヶ谷と代々木駅の間にあるpixiv社でした(社内の環境良くて羨ましかった) 概要は以下の通りの2部構成でした。 セミナーページ 第1部 ドメイン駆動設計の正しい歩き方~どこに焦点をあわせ、どう実践するか 増田亨 氏 第2部 モデル駆動型開発によるビジネスをソフトウェアに落し込む1つのやり方 株式会社アクティア 高崎健太郎 氏 (ちなみに会場は満員御礼のようでした!すごい人気!) 第1部 ドメイン駆動設計の正しい歩き方 プレゼン資料は こちらです。 プレゼンで気になった点 内容は上記スライドの通りですが、気になった内容は以下の通りです。 最近はドメイン駆動設計を試したアウトプットが増えてきた なんでもドメイン駆動設計と照らしてしまっている気がする。設計の一般論だったり、ドメイン駆動設計ではないような内容もある ビジネスがそもそも複雑。システム化すると複雑になる。ビジネスの複雑さが根本原因 核心にある複雑さを解くと周辺が自然に明確になる。入出力はフレームワーク等により自然になる 核心にフォーカスを当てると全体が綺麗になるので意識的に見た方が良い マイクロサービスでもドメイン駆動設計の言葉が出てきた。コンテキストマップやサブドメインなど 開発者がビジネスの活動を継続的に学び続けることが大切。深く洞察していないとどこがコアかわからない チームメンバー全体で行動原理の意識付けが必要 パフォーマンス・チューニングで盛り上がった時などに行動原理から外れてしまうことがある ビジネスを多少学んでビジネス用語をある程度使えるようになった時は要注意。ビジネスの複雑さはそんなものではないため、よりビジネスを継続に学び続けることが必要 1つのテーブルだけで答えが出るようなものはコアドメインではない。そんなに複雑ではない ドメイン駆動のモデルと実装は、どろどろした切り離せないもの実装したら微妙だったからモデルを見直すこともある。モデルと実装は密に結合している 技術的に無理やりシステム間を連携させることもできるかもしれないが、シンプルでスマートな方法を常に検討する。考えるか考えないかで出来上がるものが変わる 例題の宿泊予約システム料金計算について 料金計算については画面もDBも関係ない。ドメイン層として独立させる(ドメイン層だけで開発してテストできる)(ドメインを隔離するの原題はisolating the domain) モデルを仮に作成し、コーディングする。しっくり来なかったらモデルを回収する。モデルを綺麗に作成してそれをコード化するわけではなく往復する コアはスコープ次第で変わる。システム全体か、料金計算の中かで異なる シーズンか特別室か一般室かなど軸は色々試してみる。主軸の選び方を絵だけではなくコーディングまでして確認する。3択あるのであれば3つとも多少書いてみて追っかけやすさなどを確認する 歯抜けの仕様書をもらった時に埋められるほどのビジネス知識になったらベスト。POの変更要件に対してどこを修正すべきかがわかるようになると良い ドメイン駆動言語に最適なのはJava。Pythonも良いが、Javaが良い。動的な言語だけではわからないことがあるため静的な言語をちゃんとやった方が良い 結局現場に導入するには、DDDの体験的な習得が必要。エヴァンス本は即効性はないがジワジワ効いてくる。着目点など、設計の質が変わってくる。読みにくい本なので注意 エヴァンス本の読み方コツ エヴァンスの読み方としては、体験的に習得し、想定読者条件をクリアしてから読むのが良い 2003年ごろのオブジェクト指向モデリングの本は読まない方が良い。顧客クラスや商品クラスといったモデリングはDDD的に意味がない。DBとテーブルをJavaのクラスに当てはめているだけのアプローチであり意味がない オブジェクト指向設計の文書(ワークスブラックのオブジェクトデザイン、バートアンドメイヤーのオブジェクト指向入門(ドンキの2冊)、ラーマンの実践UML)※スペルが間違えているかも 「現場で役立つシステム設計の原則」は日本語で翻訳ではなく読みやすい書籍 QA ビジネスルールを引き出すにはどうしたら良いか。間違えていても仮のビジネスルールを持っていって訂正してもらう。営業はわかっていない。あと、興味ない分野には手を出さない方が良い。モチベーションが上がらない -ドメインマスターが捕まらない場合はどうしたら良いか。 DDDにより変更要件を仮実装するハードルが低くなる。痛みがなく暫定的な実装ができるため -なぜビジネスルールは複雑なのか。「 ビジネスルールの複雑さに立ち向かう」というSlideShareにまとめてある 所感 ビジネスの活動を継続的に学ぶことは避けられないんだろうなと。フリーランスで対象のシステムが不定期に変化する場合はどうなのだろうか 例題として上がった宿泊予約システムの料金計算は大変勉強になった。具体例があるのは本当に助かる モデルと実装を往復する。試しに実装してみるという考えが大切という考えに至らなかった。目からうろこ。 エヴァンス本は読みにくいと思っていたがやはり読みにくいらしい笑。まだ読み始めのため読み方のコツが聞けて助かった エヴァンス本は紙で買うべきだった。Kindleで読みにくい・・・ 自らの著書「現場で役立つシステム設計の原則」を推していたが、仰る通りエヴァンス本と比較して日本人にわかりやすくて余計なことを書いていない。エヴァンス本より前に読むべき。 オブジェクト指向設計の書籍はハードルが高そうだが読まないと。。 宿泊システムのモデルになった宿の裏設定もあってリアルさに笑った笑。こういった背景を理解すると複雑なビジネスロジックになる理由がよくわかる(背景をわかっていないとストレスになるんだなと)。 ちなみに宿の裏設定は以下のようなもの 標高2000mにあるホテル 人材・食材の調達コストが高い 客が入らない場合に販促活動が必要 ちなみに「現場で役立つシステム設計の原則」は こちらで紹介されています。