Command BusはOperation dispatchの選択肢でありArchitectureの前提ではない
Command Busは、Commandのtypeから対応するhandlerを選び、実行をdispatchする仕組みである。Mediator patternとしてprocess内で実装することも、message brokerを介して非同期化することもできるが、この2つは運用特性が大きく異なる。
典型的には次のような形になる。
HTTP / MCP / Job
↓
Command Bus
↓
Command Handler
↓
Domain / Repository
Busを置く利点は、validation、authorization、transaction、telemetry、idempotencyなどのcross-cutting behaviorをdispatch pipelineへ集約しやすいことにある。またcallerがhandler実装を直接知らず、Commandのcontractへ依存できる。
しかし、複数Transportを支えるためにCommand Busが必須になるわけではない。Microsoftの.NET application-layer guidanceでも、controllerからcommand handlerを直接呼ぶ構成、in-memory mediatorを使う構成、非同期queueを使う構成はいずれも選択肢として扱われている。Transport Adapterが共通のOperationはTransportから独立したApplication Capabilityとして置ける を直接呼べるなら、それだけでHTTP/MCP/Job間のlogic共有は成立する。
BusにはLocalization CostはLayerと抽象化を増やすほど無視できなくなる という反対側のコストがある。dynamic registrationやmiddleware pipelineが増えると、call siteから実際のhandler・authorization・transaction boundaryを静的に追いにくい。人間にもAI coding agentにも「このCommandは結局どこで実行されるか」を探索するhopが増える。
したがってCommand Busは、
- 共通pipeline behaviorが十分に増えた
- dispatchを一級の拡張点にしたい
- queueing/retryなどrequest lifecycleをCommand単位で扱いたい
といった要求が出たときに導入する方がよい。単に「CleanなArchitectureに見えるから」という理由で全OperationをBus経由にする必要はない。
またCQRSはRead ModelとWrite Modelの分離でありCommand BusやEvent Sourcingの同義語ではない とも同義ではない。CQRSはread/write modelの分離であり、Command Busはdispatch mechanismである。