domain-driven-design
ビジネスドメインを中心に、境界づけられたコンテキスト・集約・ユビキタス言語を用いてソフトウェアをモデリングするスキルです。「ドメインモデリング」「集約ルート」「腐敗防止層」「コンテキストマッピング」「ドメインイベント」などに言及したとき、またはモノリスをサービスに分割したりマイクロサービスの境界を定義する際にトリガーされます。エンティティと値オブジェクトの使い分け、ドメインイベントの設計、コンテキストマッピング戦略をカバーします。
description の原文を見る
Model software around the business domain using bounded contexts, aggregates, and ubiquitous language. Use when the user mentions "domain modeling", "bounded context", "aggregate root", "ubiquitous language", "anti-corruption layer", "context mapping", "domain events", or "strategic design". Also trigger when splitting a monolith into services, defining microservice boundaries, or aligning code structure with business processes. Covers entities vs value objects, domain events, and context mapping strategies. For architecture layers, see clean-architecture. For complexity, see software-design-philosophy.
SKILL.md 本文
ドメイン駆動設計フレームワーク
ソフトウェアの複雑性に対処するために、コードをビジネスドメインを中心にモデル化するフレームワークです。基本的な真実に基づいています。ソフトウェアの最大のリスクは技術的な失敗ではなく、ビジネスの実際の動作を反映していないモデルを構築することです。
コアの原則
モデルはコードであり、コードはモデルです。 ソフトウェアは、ビジネスドメインに対する深く、共有された理解を体現すべきです。ドメインエキスパートと開発者が同じ言葉を話し、その言葉がコードベースに直接表現されているとき、複雑性は管理可能になり、要件は正確に捉えられ、システムはビジネスの変化に応じて優雅に進化します。
スコアリング
ゴール: 10/10。 ドメインモデルをレビューまたは作成するときは、以下の原則への準拠に基づいて 0~10 でスコアを付けます。10/10 はすべてのガイドラインと完全に一致していることを意味します。下のスコアはアドレスすべきギャップを示します。常に現在のスコアと 10/10 に到達するために必要な具体的な改善を提供してください。
フレームワーク
1. ユビキタス言語
コアコンセプト: 開発者とドメインエキスパート間の共有され、厳密な言語で、会話、ドキュメント、コード全体で一貫して使用されます。言語が変わるとコードが変わります。コードが不適切な命名を明らかにするとき、言葉が改善されます。
なぜそれが機能するのか: 曖昧さはモデリング失敗の根本原因です。開発者が「注文」と言い、ドメインエキスパートが「購買リクエスト」を意味するとき、バグは避けられません。ユビキタス言語は整合性を強制するため、すべてのクラス、メソッド、変数名が、ビジネスが認識し検証する概念にマップされます。
重要な洞察:
- 言語は事後に追加された用語集ではなく、深いコラボレーションから生まれます
- 概念に名前を付けるのが難しい場合、モデルはおそらく間違っています。命名の困難さは設計シグナルです
- 技術用語の代わりにドメイン用語を使用しないコード (例:
DataProcessorvs.ClaimAdjudicator) はドメインロジックを隠します - コードで言語を実装する必要があります: クラス名、メソッド名、イベント名、モジュール名
- 異なるバウンデッドコンテキストが同じ言葉を異なる意味で使用する場合があります。これは問題ありません
コードアプリケーション:
| コンテキスト | パターン | 例 |
|---|---|---|
| クラス命名 | ドメインコンセプト後に名前を付ける | LoanApplication, RequestHandler ではなく |
| メソッド命名 | ビジネスが使用する動詞を使用 | policy.underwrite(), policy.process() ではなく |
| イベント命名 | 過去形のドメインアクション | ClaimSubmitted, DataSaved ではなく |
| モジュール構造 | ドメインコンセプトで構成 | shipping/, billing/, controllers/, services/ ではなく |
| コードレビュー | 技術的なのみの名前を拒否 | Manager, Helper, Processor, Utils を命名の匂いとしてフラグ |
参照: references/ubiquitous-language.md
2. バウンデッドコンテキストとコンテキストマッピング
コアコンセプト: バウンデッドコンテキストは、特定のドメインモデルが定義され、適用可能な明示的な境界です。同じ言葉 (例: 「顧客」) は、異なるコンテキストで異なる意味を持つことができます。コンテキストマップは、バウンデッドコンテキスト間の関係と翻訳戦略を定義します。
なぜそれが機能するのか: 単一の統一モデルを維持しようとする大規模システムは、必然的に矛盾に陥ります。バウンデッドコンテキストは、ビジネスの異なる部分が異なるモデルを持つことを受け入れ、境界を明示的にします。コンテキストマップは、各コンテキストが内部の矛盾を保持するように統合を管理します。
重要な洞察:
- バウンデッドコンテキストはマイクロサービスではなく、複数のサービスを含むことができる言語とモデルの境界です
- コンテキスト境界は、しばしばチーム境界と一致します (コンウェイの法則)
- 9つのコンテキストマッピングパターンは、チーム間の政治的および技術的な関係を説明します
- アンチコラプションレイヤーは最も重要な防御パターンです。外部モデルがコアドメインに漏れさせないでください
- 共有カーネルは危険です。2つのチームを結合し、小さく、明示的に統制されるべきです
- 既存のものをマッピングすることから始めます (Big Ball of Mud)、その後、ターゲット境界を定義します
コードアプリケーション:
| コンテキスト | パターン | 例 |
|---|---|---|
| サービス統合 | アンチコラプションレイヤー | 外部 API レスポンスを境界でドメインオブジェクトに翻訳 |
| チーム協業 | 共有カーネル | 2つのチームが小さな Money 値オブジェクトライブラリを共同所有 |
| レガシー移行 | 適合主義 / ACL | 自分のドメイン言語を話すアダプターの後ろにレガシーシステムをラップ |
| API設計 | オープンホストサービス + 公開言語 | 正式なスキーマを使った、文書化されたREST APIを公開 |
| モジュール境界 | コンテキストごとに別パッケージ | myapp.shipping と myapp.billing パッケージ、明示的な翻訳 |
参照: references/bounded-contexts.md
3. エンティティ、値オブジェクト、およびアグリゲート
コアコンセプト: エンティティは、状態変化を通じて永続する識別性を持ちます。値オブジェクトは、属性によってのみ定義され、不変です。アグリゲートは、エンティティと値オブジェクトのクラスタで、一貫性境界を強制する単一のルートエンティティを持ちます。
なぜそれが機能するのか: これらの区別がないシステムは、すべてを可変で識別性を持つオブジェクト (データベースレベルの関係を持つ) として扱い、もつれた状態、矛盾した更新、脆弱な同時実行につながります。アグリゲートは一貫性境界を描きます: 内側のすべては保証されてから一貫性があり、外側のすべては最終的に一貫性があります。
重要な洞察:
- エンティティ: 「すべての属性が変わった場合でも、私は同じもの?」 (人は名前、住所、仕事を変更しても、同じ人です)
- 値オブジェクト: 「私は属性によってのみ定義されていますか?」 (10ドル紙幣は他の10ドル紙幣と互換性があります)
- ドメインモデルのほとんどのものは、エンティティではなく値オブジェクトであるべきです。不変性を好みます
- アグリゲートルートは、単一のエントリーポイントです。外部オブジェクトはルートへの参照のみを保持できます
- アグリゲートを小さく保つ - 1つのルートエンティティと最小限の密接に関連したオブジェクトのクラスタ
- 他のアグリゲートを ID で参照してください。直接オブジェクト参照は参照しません
- アグリゲート間の最終的な整合性; アグリゲート内でのみ即座の整合性設計
コードアプリケーション:
| コンテキスト | パターン | 例 |
|---|---|---|
| 識別性追跡 | ID を持つエンティティ | Order は orderId で識別され、状態変化を継続 |
| 不変属性 | 値オブジェクト | Address(street, city, zip) - 置換、決して変更しない |
| 整合性境界 | アグリゲートルート | Order はルート; OrderLine アイテムはそれを通じてのみ存在 |
| クロスアグリゲート参照 | ID で参照 | Order は customerId を保存し、Customer オブジェクトは保存しません |
| 同時実行制御 | ルートの楽観的ロック | Order のバージョンフィールド; 2つの編集が競争した場合は競合 |
参照: references/building-blocks.md
4. ドメインイベント
コアコンセプト: ドメインイベントは、ドメインエキスパートが気に掛けるドメインで起こったことを捉えます。イベントは過去形 (OrderPlaced, PaymentReceived) で名前が付けられ、すでに発生した事実を表します。
なぜそれが機能するのか: ドメインイベントは原因と効果を分離します。OrderPlaced が公開されるとき、配送コンテキスト、課金コンテキスト、通知コンテキストは、注文コンテキストがそれらのいずれかを知ることなく、独立して反応できます。これにより、結合が低下し、最終的な一貫性が可能になり、自然な監査証跡が作成されます。
重要な洞察:
- イベントを過去形で名前を付ける: 起こったこと、起こるべきこと ではない
- イベントは不変の事実です - 公開されると、変更または取り消すことはできません
- ドメインイベントは統合イベントと異なります: ドメインイベントはバウンデッドコンテキストの内部。統合イベントは境界を超えます
- イベントは時間的な分離を有効にします: プロデューサーはコンシューマーを待ちません
- イベントソーシングは、イベントの完全な履歴を真実の出所として保存し、それらをリプレイして現在の状態を導出します
- すべての状態変化がイベントを必要とするわけではありません - ドメインが気に掛けるイベントのみを公開してください
コードアプリケーション:
| コンテキスト | パターン | 例 |
|---|---|---|
| 状態遷移 | ドメインアクション上でイベントを発生 | order.place() は OrderPlaced イベントを発生 |
| クロスコンテキスト統合 | 統合イベントを公開 | OrderPlaced は配送コンテキストで ShippingLabelRequested をトリガー |
| 監査証跡 | イベントを履歴として保存 | イベントログ: OrderPlaced -> PaymentReceived -> OrderShipped |
| 最終的な整合性 | 非同期イベントハンドラ | InventoryReserved ハンドラは OrderPlaced 後に株式を非同期で更新 |
| イベントソーシング | イベントから状態を再構築 | すべての Account* イベントをリプレイして現在のアカウント残高を導出 |
参照: references/domain-events.md
5. リポジトリとファクトリ
コアコンセプト: リポジトリは、メモリ内の集合という幻想を提供し、永続性の詳細を隠します。ファクトリは複雑なオブジェクト作成ロジックをカプセル化し、アグリゲートが常に有効な状態で作成されることを保証します。
なぜそれが機能するのか: ドメインロジックは、オブジェクトがどのように保存または構築されるかに依存しないはずです。リポジトリは SQL、ORM、データアクセスを抽象化し、ドメインコードがビジネスロジックのように読めるようにします。ファクトリは、アグリゲートが生まれた瞬間から不変量が満たされることを保証し、無効なオブジェクトが存在することを防ぎます。
重要な洞察:
- リポジトリインターフェースはドメイン層に属します。その実装はインフラストラクチャにあります
- リポジトリメソッドはユビキタス言語を話すべき:
findPendingOrders(),getByStatusCode(3)ではなく - コレクション指向のリポジトリは
add/removeをマネージ; 永続性指向のリポジトリはsaveを使用 - ファクトリは、オブジェクト作成が複雑なルール、条件付きロジック、または複数の部分の組み立てを含む場合に保証されます
- シンプルな作成 (2つのフィールドを持つ値オブジェクト) はファクトリを必要としません - コンストラクタで十分です
- 仕様パターンは、クエリ条件をドメインオブジェクトとしてカプセル化します:
OverdueInvoiceSpecification
コードアプリケーション:
| コンテキスト | パターン | 例 |
|---|---|---|
| データアクセス抽象化 | リポジトリインターフェース | ドメイン層の OrderRepository.findByCustomer(customerId) |
| 複雑な作成 | ファクトリメソッド | Order.createFromQuote(quote) はクォートから検証および組み立て |
| クエリカプセル化 | 仕様 | spec = OverdueBy(days=30); repo.findMatching(spec) |
| 再構成 | リポジトリは集計を読み込む | リポジトリは、DB 行から Order + OrderLines を完全なアグリゲートに組み立て |
| ポートおよびアダプタ | ドメインのインターフェース、インフラストラクチャの実装 | ドメインの interface OrderRepository; インフラストラクチャの PostgresOrderRepository |
参照: references/repositories-factories.md
6. 戦略的設計と蒸留
コアコンセプト: システムのすべての部分が等しく重要なわけではありません。戦略的設計は、競争上の優位性を提供するコアドメインを識別し、サポートサブドメイン (必要であるが差別化されていない) およびジェネリックサブドメイン (商品、購入またはオフザシェルフを使用) と区別します。
なぜそれが機能するのか: すべてのモジュールに同じ厳密さを適用するチームは、最高の才能を薄く広げ、商品機能を過度にエンジニアリングします。コアドメインを識別することで、組織は最高の開発者、最深のモデリング、最も慎重な設計を重要な場所に投資する一方、他の場所ではシンプルなアプローチまたはサードパーティソリューションを使用します。
重要な洞察:
- コアドメイン: 競争上の優位性が存在する場所。最高の人とそして最深のモデリングをここに投資
- サポートサブドメイン: ビジネスに必要であるが、差別化要因ではない。構築するが、過度にエンジニアリングしない
- ジェネリックサブドメイン: 商品機能 (認証、メール、支払い)。購入またはオープンソースを使用
- ドメイン蒸留は、周囲の複雑性からコアドメインを抽出し、強調します
- ドメインビジョンステートメントは、コアドメインの価値提案を説明する短いドキュメント (1ページ) です
- ハイライトされたコアは、最も重要なモデルの部分をマークしており、最も注意を受けるべきです
- ビジネスが進化するときに「コア」を再検討してください。今日の差別化要因は明日の商品になるかもしれません
コードアプリケーション:
| コンテキスト | パターン | 例 |
|---|---|---|
| 構築対購入決定 | サブドメインタイプを分類 | カスタム価格設定エンジンを構築 (コア); Stripe を支払い用に使用 (ジェネリック) |
| チーム配置 | コアドメインの最高の開発者 | シニアエンジニアはアンダーライティングルールをモデル化; ジュニアはメールサービスを統合 |
| コード構成 | コアをジェネリックから分離 | domain/pricing/ (ディープモデル) vs. infrastructure/email/ (シンアダプター) |
| 単純化 | コアコンセプトを蒸留 | モノリシック InsuranceService から PolicyRatingEngine を抽出 |
| ドキュメント | ドメインビジョンステートメント | 1ページのドキュメント: 「当社の競争上の優位性は、次を使用した リアルタイムリスクスコアリング...」 |
参照: references/strategic-design.md
よくある間違い
| 間違い | なぜ失敗するのか | 修正 |
|---|---|---|
| ドメイン言語の代わりに技術名を使用 | ドメインロジックは DataManager と ProcessorService の後ろに隠されています; 専門家はモデルを検証できません | ドメイン用語に名前を変更: ClaimAdjudicator, PolicyUnderwriter; ドメイン用語が存在しない場合、概念が間違っている可能性があります |
| 1つのモデルですべてを統治 | 課金、配送、マーケティングを提供する単一の Customer クラスが膨れ上がり、矛盾しています | バウンデッドコンテキストを定義; 各コンテキストは独自の Customer モデルを取得 (必要な属性のみ) |
| 多くのネストされたエンティティを持つ巨大なアグリゲート | 同時実行の競合、遅い読み込み、トランザクションボトルネック | アグリゲートを小さく保つ; 他のアグリゲートを ID で参照; アグリゲート間で最終的な整合性を使用 |
| 無い領域モデル (すべてのロジックはサービス内) | ドメインオブジェクトはデータバッグです。ビジネスルールはサービスクラス全体に分散。重複と矛盾 | 動作をエンティティと値オブジェクトに移動; サービスはオーケストレーション のみ、ドメインロジックは含まない |
| 統合ポイントにアンチコラプションレイヤーなし | 外部モデルはドメインに漏れます。コードは外部スキーマと命名と結合されます | 外部システムをユビキタス言語に変換する翻訳層でラップ |
| バウンデッドコンテキストをマイクロサービスとして扱う | 早期のサービス抽出; 利益なしで分散システムの複雑性 | バウンデッドコンテキストはモデル境界であり、デプロイメント単位ではありません。モノリス内のモジュールから開始 |
| ドメインエキスパートコラボレーションをスキップ | 開発者がビジネスの現実と一致していないモデルを発明。高コストな再作業 | ドメインエキスパートとの定期的なモデリングセッション; 専門家が「はい、それは動作方法です」と言うまでモデルを改良 |
クイック診断
| 質問 | いいえの場合 | アクション |
|---|---|---|
| ドメインエキスパートはクラス名を読み、それらを理解できますか? | コードは技術用語の代わりにドメイン言語を使用します | クラス、メソッド、イベントの名前をユビキタス言語を使用するように変更 |
| バウンデッドコンテキスト境界が明示的に定義されていますか? | モデルは境界を超えて出血します。同じ用語は異なる意味を持ちます | コンテキストマップを描く; 明示的な境界と翻訳戦略を定義 |
| アグリゲートは小さい (1つのルート + 最小限のクラスタ)? | アグリゲートは大きく、遅く、同時実行の問題があります | より小さなアグリゲートに分割; ID で参照; 最終的な整合性を受け入れる |
| ドメインオブジェクトはデータだけでなく動作を含みますか? | 無い領域モデル; ロジックはサービスクラスに分散 | ビジネスルールをエンティティと値オブジェクトに移動 |
| クロスアグリゲート通信にドメインイベントが使用されていますか? | アグリゲート間の密結合; 同期チェーン | ドメインイベントを導入; 非同期でアグリゲートをイベントに反応させる |
| すべての外部統合にアンチコラプションレイヤーはありますか? | 外部モデルはドメインを汚染します | 各統合境界で翻訳層を追加 |
| どのサブドメインがコアかを特定しましたか? | すべてに等しい努力; 最高の才能は薄く広がります | サブドメインを分類; コアドメインに深いモデリングを集中 |
リファレンスファイル
ubiquitous-language.md: 共有言語の構築、用語集メンテナンス、コード内の命名、言語進化bounded-contexts.md: コンテキスト境界、9つのマッピングパターン、チーム関係、統合戦略building-blocks.md: エンティティ、値オブジェクト、アグリゲート、アグリゲート設計ルール、整合性境界domain-events.md: イベント命名、イベントソーシング、イベント駆動アーキテクチャ、統合イベントrepositories-factories.md: リポジトリパターン、ファクトリパターン、仕様パターン、ポートとアダプタstrategic-design.md: コアドメイン、ジェネリックおよびサポートサブドメイン、蒸留、構築対購入
参考文献
このスキルは、Eric Evans によって開発されたドメイン駆動設計方法論に基づいています。完全な方法論、パターン、および深い洞察については、元のテキストを読んでください:
著者について
Eric Evans はソフトウェア設計コンサルタントであり、ドメイン駆動設計の創始者です。彼は金融、保険、物流を含む業界で大規模システムに取り組んでおり、DDD になったパターンとプラクティスを開発しました。彼の 2003 年の著書『Domain-Driven Design: Tackling Complexity in the Heart of Software』は、最も影響力のあるソフトウェアアーキテクチャの本の1つと広く見なされています。Evans は、複雑なソフトウェアプロジェクトに DDD を適用するのを支援するコンサルティング会社 Domain Language を設立しました。彼は、世界中のソフトウェアカンファレンスで頻繁なキーノートスピーカーであり、ワークショップ、コミュニティエンゲージメント、実践者とのコラボレーションを通じて DDD の概念を継続的に改善および進化させています。彼の作品は、マイクロサービス、イベントソーシング、戦略的なソフトウェア設計への現代的なアプローチを形成してきました。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- wondelai
- リポジトリ
- wondelai/skills
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/wondelai/skills / ライセンス: MIT
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。