The other options are to:
1. Use a saga to model what should happen if the book AR updates succeed but the BookLending creation fails. Whenever I'm doing something that touches more than one AR I start to think in terms of saga's.
2. If there is no way for the BookLending creation to fail (assuming the Book AR updates succeeded), then you don't need to do it inside a command, but can use an EventHandler listending for the Book AR event (as somebody else mentioned).
BookLending might be a better place to store it. Treat Book Lending as a service
You could simply have
Book
{
the descriptive properties of book
}
BookForLoan
{
CopiesAvailable
BookId
BookLoan[] SpecificBooks
}
BookLoan
{
BookSerialNumber, MemberId, LendingInterval
}
Just be careful with The BookForLoan aggregate - at the aggregate is your transaction boundary as well.
It is totally fine to have two domain objects participating in the the same transaction. It works most cases and you can still use DDD in those circumstances.
You can relax the consistency boundary of an AR by make some transaction in an Aggregate dependent on the completion of others as long as they belong to the same Bounded Context. There is no point in over complicating things.
For instance consider the simple scenario where the person gets into a store, asks for a book to be lent, the clerk checks the book availability, goes downstairs to the warehouse, picks the book and registers the lend. The clerk already has the book in his hands, so even if you use two separate transactions it would hardly fail if not for a major failure of ones database system between two writes. So just make both writes in the same transaction. Probably this is the scenario you have in mind.
Nothing wrong with that.
Having said this, lending books can be more involved then this. Consider the case of an online store where the books are stored in uncertain location (for instance we have multiple warehouses spread across the country). The value in stock can be uncertain at the time of lending the book. For instance, can we actually infer that the book is lent if not shipped? And so on.
So to distributive nature of your business you might need a long running business transactions, say a BookLendingOrder which might fail during the process.
Cheers,
Nuno
So I would say that while an aggregate is defined by a consistency
boundary, it follows that all changes to an aggregate must be in one
transaction, the inverse is not true:
Having two aggregates cooperate in a transaction for certain use cases
neither violates the consistency boundary (each aggregate is fully
consistent)
nor does it neccessarily hint towards incorrent aggregate layout.
Cheers
Phil