I tried to breakdown domain-application-infrastructure standard schema, but I identified a lot of other building blocks in CQRS application I am working on.
I find easier to explain my app as set of four types of modules
- kernel
- context specific
- infrastructure
- host
In kernel there are the following features (building blocks)
- event
- domain (depends on event)
- query
- projection (depends on event and query)
- api
- scheduler (depends on event)
- saga (depends on event, domain and scheduler)
kernel is not bound to any infrastructure
every feature is implemented as module, and module instance is responsible for doing feature specific task relying on abstractions
(for example domain feature provides Engine, which can execute commands)
context specific has different number of blocks from context to context, but they can be
- context domain (defines aggregates, and commands/events)
- context query (defines query schema)
- context projection (defines what events from context domain to project to what schema from query)
- context api (exposes UI-specific api, relying on context domain and context query)
- context saga (implements eventual consistent business processes based on context domain, may reference context query as well)
infrastructure layer implements abstractions used by features in kernel, and may be:
- sql server event store
- katana self hosted web api
- sql server query
- sql server scheduler
- sql server event provider
there may be more than one infrastructure for provider
and last big group of blocks is hosts, hosts are separately hostable process bootstrappers, they may bootstrap a lot of endpoints in a single process or in many separate processes. The typical hosts can be:
- api host (uses katana web api, sql server event store and sql server query for context api which relies on context domain and context query)
- projection worker host (uses sql server event provider, sql server query, context domain events, context query, context projection)
- saga worker host (uses sql server event store, event provider, scheduler and query, with context saga etc)
I think query is not for UI api only, it may also be used by sagas (business processes) - for example send email to all admins - where all admins are in read model
Also I think it makes sense to separate projection from query, as you may change strategy of populating query later with different projection methods