Partial modularization is worthless in my opinion.
We would also need consider:
bounded contexts - maybe together with application layer (app services/handlers)
above should have impl and api(events, some dtos, interfaces)
sagas - now we have Sage in scope of one module (BC) but in general
they should span above many BDs
I thought about this issue, we have even started with full-blown
modularization. So all work is done.
But trust me - show this to Maven newbee and he will cry and wont look
at Leaven any more:)
besides: Maven has some haters too:)
So to please everybody I'm thinking about providing "arhetypical"
project structure, but empty. Code would be maintained in current
shape - big pail and whoever wants can split it to modules. But it's
just a thought - every time I speak it loudly it sounds silly:)
btw: according to work optimization look at current approach: unit
tests are stored in main project, by integration and acceptance tests
are stored in separate project.
But just in sake of education purpose we assumed that model of people
is very distinct in all Bounded Contexts and provoked all this
"problems" to illustrate them:)
I agree that modularization is a great feature, but it's also very
unforgiving :)
In order to fully implement a bounded context (and properly 'bound'
it) you'd need at least 2 modules for each BC (like Sławek said), i.e.
sales-api and sales-impl (and the latter can be further split into
sales-domain and sales-infrastructure, but I haven't tried that).
API modules consist of Commands and Finders interfaces with their Dto
[and some Events if it makes sense to propagate them to the outside
world] and these are the only objects that come out of the BC. All the
DDD buildinging blocks, CommandHandler-s and Finders implementations
are hidden.
The API is used both in communication with the interface (in our case
a .WAR module, and possibly other, remote clients) as well as between
different BCs.
A short example (which is more complicated case than the what is
currently implemented in the sample)
In SALES business context I create an order for a client and I need
person's address. I cannot access Customer entity from the CRM module
because it's different BC so instead i query CustomerFinder from CRM
module to give me CustomerDto and use it's address.
If I need to keep track of that Customer in SALES (and keep additional
data with it) I would create another Entity and perhaps call it Client
and keep the id of the Customer (which I got from CustomerDto).
SALES context can change entities of CRM BC but only using provided
API, i.e. issuing commands, or dispatching events that CRM or sagas
listens to,
In above example - even though we use a relational DB underneath we
cannot use foreign key constraints because we only keep IDs as numbers
(actually we can ;) ), but this way we gain some scalability potential
if we chose to split BCs over different data stores.
One last closing comment on the Client<->Customer duality. It doesn't
break the "ubiquitous language" rule and actually follows it
perfectly. Language is ubiquitous only in it's BC and concept mapping
across different BC is natural.
Modularization is a very interesting topic and I wish we could delve
deeper and figure out how to do it properly in one of the next
milestones. Keep the ideas comming :)