I'm interested in the Idea of DDD but I have some questions about the concept of encapsulating and protecting the AggregateRoot internal Entities and how to reference them. I created a simple example (don't hit me if the domain design is bad, this is just an example to clarify the question).
// can be referenced from outside, is aggregate root
public class Library : AggregateRoot
{
IList<Shelf> shelfs { get; }
}
// can be referenced from outside, is aggregate root
public class Shelf : AggregateRoot
{
Book GetBookById(Guid Id) {...}
}
// should be accessed through Shelf, not referenced outside the context
public class Book : Entity<Guid>
{
Guid Id { get; } // or something else uniqe, e.g. ISBN
}
// how to reference a book here?
// I think, I should not use Id because this is internal and
//only valid for Shelf Aggregate (but I can't have a second one of this book)
public class Lending : AggregateRoot
{
// feels wrong because of passing internals from Shelf
Guid LendedBook { get; set; }
// should I Clone() an object with unique identity, is this allowed in DDD?
Book LendedBook { get; set;}
// create separate type for lending (but what should this type cointain)
LendedBookInfo LendedBook { get; set;}
}
Hope to get a clear answer, cause most samples are only about ValueObjects (that are easy, 'cause they are copied anyway and not really referenced). I used C# style of code for my sample, but any other programming language or pseudo code is also welcome as answer.
Your example of an external ID usage
Guid LendedBook { get; set; }
is fine. What you could do to make the model more explicit, is to create a value object BookId
and use that one to reference books. The value object BookId
is then a context-wide concept, i.e. not one that is local to a specific aggregate.
Apart from that, you probably don't want public setters or IList
as return type in your model. But I suppose that's just an example and not really the question here.