1

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.

Beachwalker
  • 7,685
  • 6
  • 52
  • 94
  • In real world domains your would very rarely have to reference an entity outside of it's AR and if you need to then it might be an indicator that the concept is not an entity but an AR itself. For instance, why would Book be an entity of Shelf here? Couldn't a Book be moved to another Shelf? A Book is probably an AR in your sample domain and then your question goes away, so the premise of your question is a bit flawed. – plalx Nov 09 '15 at 21:08
  • However, I don't believe that it's prohibited to keep an entity's id reference from outside it's AR, it's just that the id is useless without the context so you must also keep a reference to the AR's id. Also remember that ARs should reference other ARs by id only and that a domain model is not meant to be used for UI queries and reporting. – plalx Nov 09 '15 at 21:08
  • @palx The example is not well designed cause it is not the focus here... it is just to illustrate the question. – Beachwalker Nov 09 '15 at 21:16
  • I known and that's why I wrote those comments. The first sentence of my second comment answers your question. – plalx Nov 09 '15 at 22:33

2 Answers2

1

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.

theDmi
  • 17,546
  • 6
  • 71
  • 138
  • But using the Guid Id of the Book means that Book needs to be an AggregateRoot (to have globally unique meaning of id) if Shelf is not referenced, too. Otherwise the id is not unique and an internal concept of the Shelf AggregateRoot. – Beachwalker Nov 13 '15 at 22:34
1

In DDD it's never a bad thing to model the real world. If you spoke to a Domain Expert in this domain, a librarian, they probably have terminology and workflow that could help you model your domain.

For instance they might talk about "lending a book" using a "book ticket system" and when they want to find a book by title they might look in the "title catalogue".

This might lead to a design where you have a BookTicketService class with a LendBook(lender, book) method, which might cause an entry to be recorded in the BookTicketSystem. Or a TitleCatalogueService class that has a SearchByTitle(title) method. Or when the library accepts a new book into the library, a record of it probably goes in the AccessionRegister, etc.

If you model your library using this ubiquitous language it allows other people in the library domain to pick up your software easier and most importantly, it allows software developers to talk to librarians about their requirements without talking in software development terms.

I'd Google a few things like "how to start a library" or "library glossary of terms" and try bring some of the language and processes you find into your software. People already run fully functioning libraries with tens of thousands of books and lenders. In theory all you need to do is understand how they do this, the terms they use and it should be possible to model it in software.

Adrian Thompson Phillips
  • 6,893
  • 6
  • 38
  • 69