20220312_アウトプット(ドメイン駆動設計)
ドメイン駆動設計の考え方、すごく面白い
- 最近ドメイン駆動設計(以下、DDD)を学びたくて色々読んでいる。
- 読み進めているもの
- ようやくの考え方が繋がり始めた気がする。
まず、DDDの単語の意味がわかった!
概念系
- ドメイン
- 領域という意味。システム化で解決したい要所はどの部分?
- ドメインモデル
- 解決したい要所の概念を抽象的に表現したもの
- なぜ?:プロダクトオーナー(ソフトウェアにしたい人)と開発者の共通認識・理解を深めるため
- 解決したい要所の概念を抽象的に表現したもの
- ドメインオブジェクト
- 解決したい要所の知識を具体的に表現したもの
- なぜ?:開発者が実際にコードに落とし込むため
- 解決したい要所の知識を具体的に表現したもの
- ユビキタス言語
- 境界づけられたコンテキスト
- モデルが適用される範囲を明示的に定義してそれぞれの中でモデル、言語の統一を目指すこと
- (例)”商品”という単語
- 販売者にとっての”商品”→商品名、価格、在庫数
- 配送者にとっての”商品”→商品名、配送先、配送状況
- (例)”商品”という単語
- モデルが適用される範囲を明示的に定義してそれぞれの中でモデル、言語の統一を目指すこと
感じたこと🌸
- 開発者は、プロダクトオーナーが普段どんな風に困っていてどんな部分を解決したいのかわからない。
- プロダクトオーナーは、普段行っている業務やサービスの中で、実は差別化につながっている知識(資産価値に繋がるもの)に気づかないことも多いだろう。
- だからこそ、開発者が対話を通じて引き出すの大事。「こういう意味ですか」って掘り下げるの大事。
- 具体化していくことで認識・方向性の改善が必要となり、徐々にドメインを育てていくため、テスト駆動開発やアジャイル開発と相性がいいのかと繋がった。
- 理想は1コンテキスト1アプリケーションなんだって(´-`).。oO(それ同士を同期or非同期で通信させる)確かにドメインぼやけるもんなあ。(理想と現実の最適解を探るの難しいけど面白そう)
DDDならではの単語系 〜値そのもの編〜
- 値オブジェクト
- システムに出てくる単位や値をオリジナルで定義すること
- ”不変”がポイントなので、交換はいいけれど、値そのものに代入して変更できないようにする
- (例)単価
- 0円以上1,000万以下の範囲に収まるシステムなので、その単価を設定する
- (例)単価
- エンティティ
- システムに出てくる値でもライフサイクルがあるもの(状態遷移)
- "可変"がポイントなので、振る舞いを通して、同一性を残したまま値を適切に変化させる
- (例)人
- 同じ「私」だけど、生まれた時からおばあちゃんになるまで変化がある
- (例)人
- ドメインサービス
- 値オブジェクトやエンティティに書いてしまうと不自然な操作だけを抜き取って定義すること
- (例)ユーザーの重複確認
- 値オブジェクト→自分自身に重複するユーザーがいないか聞く形となり不自然
- エンティティ→ユーザーを表すエンティティでありながらユーザーではなく不自然
- (例)ユーザーの重複確認
- 値オブジェクトやエンティティに書いてしまうと不自然な操作だけを抜き取って定義すること
- ファクトリ
感じたこと🌸
- ドメイン駆動設計の文脈で出てくる「エンティティ」は、永続化対象のデータをエンティティと呼ぶこととは別物とわかり超スッキリ。
- こうやって「同じ単語だけどドメイン駆動設計だと違う意味」が多いのでわかりづらいのかwww
- 「知らないところで値が変わることはない」「知らないところで状態が変わっていることはない」って保証するのって凄く大事だなと思った。なぜならば、それを前提で他を組み立てるため。
- 開発者同士がDDDを理解しドメイン知識はちゃんと大事にする!(値オブジェクトやエンティティは死守する!)という前提も大事だと感じた。
- ただのint型だと(最大値は2147483647、最小値は-2147483648)「そんなにいらんがな」ってなるところを、ちゃんとオリジナルの型で定義することで、不正な値を作らない”安全”にも繋がるし、コード自体に”100万以下なのね”と意味が生まれ可読性も上がるし、Goodだなあと思った。
DDDならではの単語系 〜値を成り立たせる編〜
- リポジトリ
- ユースケース/アプリケーション層
- 値オブジェクトやエンティティをまとめ上げて実際に機能として組み立てる層
- (例)ユーザー情報を登録する/変更する
- 値オブジェクトやエンティティをまとめ上げて実際に機能として組み立てる層
- 仕様
- あるオブジェクトが評価基準に達しているか判定するオブジェクトのこと
- 集約
- 必ず守りたい強い整合性を持ったオブジェクトのまとまりのこと(データの変更の単位)
- まとまりの中の親を「集約ルート」として、そこを起点にして集約同士でやり取りするようにする
- なぜ?:整合性を保つため
- まとまりの中の親を「集約ルート」として、そこを起点にして集約同士でやり取りするようにする
- 必ず守りたい強い整合性を持ったオブジェクトのまとまりのこと(データの変更の単位)
- 整合性(矛盾がない一貫性)を保つための方法(色々ある)
感じたこと🌸
- 「リポジトリ」何のためにあるんだろう??とずっと思っていたため”驚くほど柔軟性を与える”という言葉で「そういう役割だったのか!」と超スッキリ✨
- 整合性の部分は(実際の実装のところ)理解しきれない部分もあったので、その都度「絶対に必要なひとかたまりってどの範囲?」「実現するにはどの方法がベスト?」って調べようと思った。
(知らなかった)デメテルの法則
- オブジェクト操作において、メソッドを呼ぶオブジェクトは次の4つに限定されるよ
- (例)車を運転している時に、タイヤに直接命令しないのと同じように、それを保持するオブジェクトに対して命令を行うこと
(1)オブジェクト自身
(2)インスタンス変数
(3)引数として渡されたオブジェクト
(4)直接インスタンス化したオブジェクト
共通して大事なんだと感じたこと
DDDの意味がわかり始めてから「だから〇〇なのか!」と繋がったこと
- まず中心にドメインを作って(ドメイン層)、その周りにドメインを使った機能を作って(アプリケーション層/ユースケース層)、その周りに入出力・テスト・永続化の具体的方法・外部との連携(テスト/プレゼンテーション層/インフラ層)を作るオニオンアーキテクチャがGoodなのか!
- ドメイン知識となる部分=企業秘密になりうる部分なので、オープンソース上に少ないのか!
- 値単位で正確さを求めることから、静的型付言語との相性がいいのか!
- ドメインを表現するのが何よりの肝だから、ユビキタス言語などを通じてプロジェクトオーナーと開発者が対話するのが最重要なのか!
- DDDって「実はシンプルで当たり前のことを表現しているだけ」ってそういうことなのか
- 疎結合がもたらす恩恵ってそういうことなのか(例えばMySQLからPostgreSQLに変えるときインフラ層を直せば良いだけ)
- MVCとは全く別物なのか!(Railsのフレームワークを想像しながら読み進めると意味不明となる、全く別物、アーキテクチャの考えってそういうことなのか)
全体を通しての感想
- DDDを理解してからのオブジェクト指向の勉強がめちゃくちゃ面白い😭
- 今までは、クラスは〇〇、setterは〇〇など、単語の意味はわかるんだけど、それをどうやって活かしていくの?ってところが繋がっていなくて「こういうのどこまであるんだろう?覚えられないし辛い」って思ってた。
- でも「DDDの考え方ってこんなに面白いんだ!!」って思ってから、オブジェクト指向の単語を学び直したとき「DDDの中のここで使える引き出しが増えた」って感覚に変わって面白さを感じるようになった。
- 例えば、インターフェースってインターフェース自体はメソッド定義せず、
implement
したクラスが振る舞いを詳しく書くが、それをDDDで実現したい時に「リポジトリとインフラ層の実装をするときに活躍するのか!😍」って思えるようになった!(楽しいw)
- 例えば、インターフェースってインターフェース自体はメソッド定義せず、
- まだまだ途中なので読み進めていこう🔥
長くなりましたが読んでくれてありがとうございました!