Token导航 LogoToken导航TokenDH.com
研究检索权限需确认github未标认证来源可访问许可证需确认审计通过

cross-aggregate-constraints交叉聚合约束

Agent Skill

cross-aggregate-constraints 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

768

周安装

32

GitHub Stars

75

下载量

256
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:cross-aggregate-constraints(交叉聚合约束)
来源仓库:https://github.com/j5ik2o/okite-ai
仓库路径:skills/cross-aggregate-constraints
安装命令:
npx skills add https://github.com/j5ik2o/okite-ai --skill cross-aggregate-constraints
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/j5ik2o/okite-ai --skill cross-aggregate-constraints

简介

cross-aggregate-constraints 分析微服务架构中跨聚合的业务约束与技术权衡。

  • 适用于 DDD 建模阶段识别实体间依赖关系与删除/更新限制。
  • 提供逻辑删除、条件放宽等替代方案以减少硬耦合检查。
  • 强调先质疑业务必要性再设计技术实现,避免过度工程。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

集約間の制約チェック

集約間の制約に直面したら、まず要件を疑い、次に技術的制約を理解し、最後に覚悟を決める。

典型的な問題

「集約Aのユースケースで集約Bの状態を確認したい」という要求が発生する。

例: 「一つでも商品が紐づいているブランドは削除できない」

  Brand集約(削除したい)←── 制約チェック ──→ Product集約(紐づき確認)

この種の要求に対して、安易に技術的解決策に飛びつくべきではない。

ステップ1: 要件を疑う

技術の前に、ビジネス要件自体を問い直す。

問い直しのフレームワーク

その制約は本当に必要か?
    ↓
ライフサイクル全体で考えるとどうなるか?
    ↓
実運用では実質的にどういう制約になるか?
    ↓
複雑な実装に見合うビジネス価値があるか?

具体例: ブランド削除制約

「一つでも商品が紐づいているブランドは削除できない」を問い直す:

観点分析
初期状態ブランド登録時は商品ゼロ。削除可能
運用中ほとんどのブランドに何かしらの商品が紐づく
実質的な制約「ブランドは削除できない」と同義になる
結論複雑な制約チェック機構を作る意味があるか再検討すべき

要件緩和の選択肢

緩和案説明
論理削除ブランドを「非アクティブ」にする。商品紐づきチェック不要
制約の廃止ブランド削除自体を禁止し、制約チェックを不要にする
条件の変更「N日以上商品が紐づいていないブランドのみ削除可」等
許容紐づき先のないゴミデータの存在を受け入れる

ステップ2: そもそもモデリングの問題ではないか

集約間の制約が必要に見える場合、集約の境界が間違っている可能性がある。

トランザクションは複数のエンティティにまたがりますか? この質問の答えがイエスならば、間違った集約ルートを持っていると言えるでしょう。 --- Lightbend Academy

関係性に基づく判断フロー

2つの「集約」を常に一緒に操作する必要がある場合:

A : B の関係は?
    ├─ 1:1 → 同一集約に統合を検討
    │         例: Task(report: TaskReport)
    │         → 1トランザクションで不変条件を維持できる
    │
    ├─ 1:N(少量) → 要件調整で小規模化できないか検討
    │         → 可能なら同一集約に統合
    │
    ├─ 1:N(大量) → 別集約 + 結果整合性
    │         → ドメインイベントで連携
    │
    └─ Bは純粋なクエリ要件か?
          ├─ YES → CQRSのリードモデル(プロジェクション)で対応
          │         → Bは集約ではなくビューとして構築
          └─ NO → ドメイン知識を持つ → 独立集約 + 結果整合性

具体例: Task と TaskReport

「TaskReportの作成を忘れるとまずい」ならば、両者は独立できない可能性が高い。

// 1:1なら同一集約に統合
class Task private constructor(
    val id: TaskId,
    val name: TaskName,
    val report: TaskReport  // 集約内に含める
) {
    companion object {
        fun create(name: TaskName): Task {
            val id = TaskId.generate()
            return Task(id, name, TaskReport.create(id))
            // TaskReport作成忘れが構造的に不可能になる
        }
    }
}

TaskReportが純粋なクエリ要件なら、CQRSのリードモデルとして構築すべき。集約ではなくプロジェクションで対応することで、制約チェック自体が不要になる。

ステップ3: Sagaの誤用を避ける

集約間の制約チェックにSagaを使おうとするのは、よくある誤用パターンである。

Sagaの本来の目的

Sagaは複数の操作を順番に実行し、失敗時に補償するためのパターンである。

Sagaの正しい適用:
  注文受付 → 在庫引当 → 決済処理 → 配送手配
  (どこかで失敗したら補償トランザクションで巻き戻す)

Sagaの誤用:
  「ブランドに商品が紐づいているか確認して、紐づいていたら削除を拒否する」
  → これは一連の操作ではなく、ただの制約チェック。Sagaの出番ではない

誤用パターンの検出基準

観点Sagaが適切Sagaが不適切
目的複数ステップの分散トランザクション管理単純なデータ存在チェック
性質長時間にわたる複数操作の協調同期的な制約確認
失敗時補償トランザクションで巻き戻し操作の拒否

ステップ4: CQRS/ESの技術的制約を理解する

大原則: コマンド側はコマンド側だけで解決する

コマンドがクエリ側のリードモデルに依存してはならない。コマンド側はコマンド側だけで解決できないと設計が破綻する。

❌ 禁止: コマンド側 → リードモデル(クエリ側)を参照して判断
✅ 許可: コマンド側 → 他の集約にコマンド/メッセージで問い合わせ

なぜリードモデルに依存してはいけないか:

理由説明
イベントの非同期性イベントストアへの書き込みとリードモデルへの反映の間にラグが発生する
レース条件リードモデル参照→コマンド実行の間に状態が変わる可能性がある
責任分離違反コマンドモデル自体の検証ロジックが曖昧になる
結果整合性との矛盾強い整合性が必要な操作で結果整合性に依存する危険性

アンチパターン: リードモデルで事前チェック

// ❌ コマンド側がクエリ側に依存している
class CreateProductUseCase(
    private val productRepository: ProductRepository,
    private val brandReadModelRepository: BrandReadModelRepository, // リードモデルへの依存
) {
    fun execute(brandId: BrandId, productName: String) {
        // ① リードモデルでブランド存在チェック
        val brandExists = brandReadModelRepository.existsById(brandId)
        if (!brandExists) throw BrandNotFoundException(brandId)

        // ② 商品作成
        // ⚠ ①と②の間でブランドが削除される可能性(レース条件)
        val product = Product.create(brandId, productName)
        productRepository.store(product)
    }
}

このリードモデル参照は「無いよりまし」程度の位置づけであり、完全な整合性は保証できない。

他集約の状態確認方法(コマンド側で完結する方法)

リードモデルではなく、コマンド側の仕組みで他集約の状態を確認する。

方法1: 集約に直接問い合わせ(アクターモデル)

// Akka/Pekko: 組み込みメッセージで存在確認
brandActorRef ! Identify(brandId)
// → ActorIdentity メッセージが返る

// Typed Actor: カスタムメッセージで状態確認
brandActorRef ! ExistsBrand(brandId, replyTo = self)

方法2: リポジトリ/ドメインサービスで参照(参照のみ)

// ✅ 他の集約をリポジトリで参照するだけなら許可(更新は不可)
class CreateProductUseCase(
    private val productRepository: ProductRepository,
    private val brandRepository: BrandRepository, // コマンド側のリポジトリ
) {
    fun execute(brandId: BrandId, productName: String) {
        // コマンド側のリポジトリで存在確認(リードモデルではない)
        val brand = brandRepository.findById(brandId)
            ?: throw BrandNotFoundException(brandId)

        val product = Product.create(brandId, productName)
        productRepository.store(product)
        // ※ brandの更新はしない(参照のみ)
    }
}

注意: 参照はDDD原則に反しないが、複数集約の更新を同一トランザクションにすることは不可

Application層での複数集約操作の原則

操作可否理由
他集約の参照OK読み取りのみなら問題なし
他集約の更新(別トランザクション)OK結果整合性で対応
他集約の更新(同一トランザクション)NG集約の整合性境界を破壊する

イベントストアの制約

イベントストアは基本的に集約IDでしかアクセスできない。

可能: 商品ID → 商品集約のイベント履歴
不可: ブランドID → そのブランドに紐づく商品の一覧

「このブランドIDに紐づく商品があるか?」という逆引きはイベントストアでは直接実行できない。

逆引きを実現する場合のコスト

逆引きが必要な場合、ブランドIDから商品IDを解決できるインデックス用リードモデルを別途用意し、商品の登録・更新・削除のたびにそのインデックスも更新する必要がある。

Product集約 → ProductCreatedEvent → リードモデル更新
                                       ↓
                                    Brand-Product インデックス
                                       ↓
Brand削除時 → インデックスを参照して紐づき確認

できなくはないが、かなり複雑になる。 その複雑さに見合うビジネス価値があるかを先に検討すべき。

ステップ5: 覚悟を決める

CQRS/ESを採用する覚悟

CQRS/ESの非同期・イベント駆動的な性質上、以下は避けられない:

  • イベント処理遅延による一時的な不整合
  • 補償トランザクション失敗時のゴミデータ
  • リードモデルと書き込みモデルの一時的なズレ

これらを「問題」と見なすのではなく、分散システムの基本的な特性として設計段階から組み込む必要がある。

CQRS/ESをやるんだったらそれぐらいの覚悟を持たないとだめ

許容すべきこと

許容すべきなぜ
一時的な不整合データ結果整合性の本質
紐づき先のないデータ集約の独立性の代償
リードモデルの遅延非同期処理の本質

許容してはいけないこと

許容不可なぜ
集約内部の不整合集約は強い整合性境界
ビジネスルールの破壊不整合と要件違反は別
永続的なデータ不整合結果整合性は「最終的に一致する」こと

判断フロー(全体)

集約間の制約チェックが必要になった
    ↓
1. その制約は本当に必要か? → 要件を疑う
    ├─ 不要 → 制約を廃止。問題解消
    └─ 必要 ↓
2. そもそもモデリングの問題ではないか?
    ├─ 1:1の関係 → 同一集約に統合。制約チェック不要に
    ├─ 片方がクエリ要件 → CQRSのリードモデルで対応。集約不要
    └─ 独立した集約である必要がある ↓
3. Sagaを誤用しようとしていないか?
    ├─ 制約チェックにSaga → 不適切。Sagaは分散トランザクション管理用
    └─ OK ↓
4. コマンド側だけで解決できるか?
    ├─ YES → 他集約にリポジトリ/メッセージで参照(リードモデル依存は不可)
    └─ NO ↓
5. リードモデルでの「ベストエフォート」チェックで許容できるか?
    ├─ YES → リードモデル参照 + レース条件を許容 + 結果整合性
    └─ NO ↓
6. 強い一貫性が絶対に必要か?
    ├─ YES → 集約境界の見直しが必要(設計の問題)
    └─ NO → 結果整合性 + ゴミデータの許容

関連スキルとの関係

スキル関係
aggregate-design集約内部の設計原則。本スキルは集約の制約を扱う
aggregate-transaction-boundaryトランザクション境界と結果整合性。本スキルは制約チェックに焦点
cqrs-tradeoffs結果整合性の概念的トレードオフ。本スキルは実践的な覚悟を扱う

レビューチェックリスト

要件

  • 集約間の制約が本当にビジネス上必要か問い直したか
  • ライフサイクル全体で制約の実効性を検証したか
  • 要件緩和の可能性を検討したか

設計

  • Sagaを制約チェックに誤用していないか
  • 同一集約への統合の可能性を検討したか(1:1関係なら統合が自然)
  • 片方が純粋なクエリ要件なら、CQRSのリードモデルで対応できないか
  • イベントストアの逆引き制約を理解しているか
  • コマンド側がクエリ側(リードモデル)に依存していないか
  • 他集約の参照はコマンド側のリポジトリ/メッセージングで行っているか
  • Application層で複数集約の更新を同一トランザクションにしていないか

実装

  • 逆引きが必要な場合、リードモデルのコストを見積もったか
  • 一時的な不整合データの存在を許容する設計になっているか
  • 複雑さに見合うビジネス価値があるか評価したか

関連スキル(併読推奨)

このスキルを使用する際は、以下のスキルも併せて参照すること:

  • aggregate-design: 集約境界の設計(制約問題の根本原因)
  • aggregate-transaction-boundary: 1トランザクション=1集約ルールと結果整合性
  • cqrs-aggregate-modeling: CQRS/ESによるイベント駆動の結果整合性

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.89%
按下载量换算94

Claude

28.05%
按下载量换算72

Cursor

21.34%
按下载量换算55

Gemini CLI

10.55%
按下载量换算27

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限需确认

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills