ddd-deeper-insight について
既に DDD に取り組むチームが、既存のドメインモデルを深めるためのスキルです。暗黙の概念の命名、意図を示すインターフェース、不変条件のコード化を通じて、理解の進展に合わせてモデルを磨きます。
主な機能
- 01暗黙のドメイン概念の特定と命名
- 02意図を示すインターフェースの設計
- 03アサーションによる不変条件のコード化
- 04ドメイン概念に沿った責務の分割
- 05純粋関数と不変値オブジェクトの活用
- 06クラス依存の削減と操作の合成
活用シーン
- 01動作するが扱いにくいモデルの改善
- 02継続的なモデリングによるドメイン言語の洗練
- 03責務が広いクラスや依存の多い設計の検討
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-deeper-insightインストール後、Claude Code で/ddd-deeper-insightを入力して読み込まれたか確認します。
詳細
1 行での概要
最初のモデルを超えて、より深い洞察は、モデルが隠している概念に名前を付け、意図を明らかにして誤用を防ぐインターフェースを設計することから生まれます。
このスキルを使う場面
- モデルは「動く」ものの、しっくりきません。コメントを読まないとわからないコード、パラメーターが多すぎるメソッド、ほぼ合っているものの少し違う名前などが見られます。
- 言語を毎週磨き続けているモデリングセッション。
- DDD をしばらく実践してきたチームが、明白なパターンを超えて、しなやかな設計を目指したい場合。
このスキルを使わない場面
- ゼロからの初期設計 →
ddd-designを使ってください。 - 明確で名前の付いた匂いがあり、既知の修正方法がある場合 → 直接
ddd-reviewとddd-refactorを使ってください。
主な内容
Evans の第 III 部のテクニックを要約したものです。モデルが必要としているときに、1 つずつ適用してください。どれも必須ではありません。
ブレークスルーは段階的に起こります。 モデルの最初のバージョンが最善であることはほとんどありません。「動く」ようになってもモデリングを続けてください。チームの理解が深まれば、それに合わせてモデルも改善されるべきです。
暗黙の概念を明示します。 ルールがコードコメントや散在する if 文に隠れている場合、それをドメインの概念として名付けます。Policy、Specification、Rate、EligibilityRule などです。名前そのものがユビキタス言語の一部です。逆に、コードが「実際には何を意味するのか」をコメントで説明しているなら、そのコメントが示す概念の名前が欠けています。
意図を明らかにするインターフェース。 メソッドには、実装の 方法 ではなく、ドメインの用語で達成する 内容 に基づいた名前を付けます。Account.withdraw(amount) は意図を明らかにしますが、Account.modifyBalance(-amount) は仕組みを説明しています。
副作用のない関数。 状態を変更するのではなく、新しい値オブジェクトを返す純粋関数に、可能な限り多くのロジックを移します。モデルの非変更部分は、最も推論しやすく、組み合わせやすい部分です。
アサーション。 不変条件をドキュメントだけでなく、コードに組み込みます。コンストラクターの事前条件、メソッドの事後条件、エンティティの状態に関する不変条件などです。不変条件が説明文だけにあると、実装とのずれが生じます。
概念の輪郭。 技術的な都合ではなく、ドメイン概念の自然な境界に沿ってクラスを分割します。2 つの振る舞いが異なる理由で変更されたり、異なる速度で進化したりするなら、それぞれ別の場所に置くべきです。
独立したクラス。 クラスから外部への依存を最小限にします。結合はモデリング上の匂いです。結合の強いクラスには、モデルがまだ分離できていない複数の概念が含まれていることがよくあります。
操作の閉包性。 入力と出力が同じ型を共有する操作は、すっきりと合成できます。Money.add(Money) → Money は合成できますが、Money.add(Amount) → BigDecimal はできません。閉包性によってモデルは代数的になり、操作を自然につなげられます。
判断のヒューリスティクス
- コメントがコードの「実際の意味」を説明しているなら、そのコメントが示す概念はおそらくモデルに欠けています。
- 純粋関数と不変の値オブジェクトを使うと、モデルについて推論しやすくなります。デフォルトではこれらを使い、エンティティのライフサイクル上必要な場合にのみ可変性を受け入れてください。
- 結合はコード品質だけでなく、モデリング上の匂いでもあります。クラスが多数のクラスに依存しているなら、モデリング上の責務が広すぎます。
- パターンを適用すること自体を目的にリファクタリングしないでください。本に載っているからではなく、ドメインが求めているときにこれらのテクニックを適用してください。
アンチパターン
- 構造や責務を変えずに、クラス名を「DDD らしく聞こえる」名前に変更する。
- ドメインが求めているからではなく、本に載っているからという理由で
PolicyやSpecificationクラスを導入する。 - 「操作の閉包性」の見せかけ。自然に型が異なる操作まで、無理に同じ型を共有させる。
- 目指す状態を決めずにリファクタリングする。しなやかな設計は目指す方向であり、チェックリストではありません。
関連項目
ddd-refactor— 実践面での対応項目であり、小さなステップを順に重ねます。ddd-value-object— 操作の閉包性と不変性が自然に活きる場所です。ddd-ubiquitous-language— 暗黙の概念に名前を付けることは、言語を育てることそのものです。
参考文献
- Evans, Domain-Driven Design(2003年)、第III部、第8〜13章(突破口、暗黙的な概念の明示化、しなやかな設計、分析パターン、デザインパターン、より深い洞察に向けたリファクタリング)。