2

I would like to have one or more libraries of reusable classes that are basically value objects, such as Address, PhoneNumber, EmailAdress, containing mostly properties and a few supporting methods. How can my Domain layer use these without breaking the rule that the Domain Layer should not contain external references, and without defining them as interfaces/abstract classes in the Domain Layer?

3 Answers3

4

... without breaking the rule that the Domain Layer should not contain external references

I think your definition of 'external references' requires some reevaluation. It is hard to imagine a domain layer that does not reference anything. In C# and Java you will reference at least basic numeric types, dates and strings. I also don't see any harm in referencing external libraries like Noda/Joda time. On the other hand, you of course would not want to reference any heavy technical libraries like persistence, communication, UI etc.

So I would say that you can build your own reusable library referenced from domain but it requires a very careful consideration, and is often not worth the coupling that it will create. I would use a following criteria for every type:

  • Should be context-independent. EmailAddress for example is relatively independent of the context it is used from. Address on the other hand may have a different meaning depending on a Bounded context.
  • Should be stable (does not change often).
  • Should not hide any out-of-process communication (db, network etc)
  • Should not have any dependencies of its own (other than standard Java/C#)
Dmitry
  • 17,078
  • 2
  • 44
  • 70
  • 1+ for first bullet point. I've seen so many times entities being used out of context for the sake of reuse. It's also related to your second bullet point, since using an entity in *n* contexts gives it *n* reasons to change, and probably means it will change *n* times as often. – MattDavey May 17 '13 at 12:14
1

I think that what you're referring to is a shared kernel.

Shared Kernel – This is where two teams share some subset of the domain model. This shouldn’t be changed without the other team being consulted.

While this looks great at first, since we are drilled not to repeat ourselves, be aware of the pitfalls:

  • The concepts should have the same meaning in every context. Some of these concepts hold subtle nuances depending on the context. Ask your domain expert.
  • Changes are more expensive; it might be cheaper to duplicate these few classes so that you can change them on your own than to have to consult multiple teams when something changes.
JefClaes
  • 3,275
  • 21
  • 23
  • I'm thinking some of these could be abstract classes, where custom context could be added by client domain. – Terry Plyler May 17 '13 at 14:53
  • You can also use containment to add semantics, rather than inheritance. Java and C# don't permit multiple inheritance, so sometimes containment is your only choice. Containment allows you to re-define the interface to match the needs of different domains as well. – drdwilcox May 17 '13 at 16:39
0

Stability cuts both ways. If you pull an entity out into each domain, then any changes have to be executed across multiple projects. If you don't, then changes have to be coordinated across multiple domains. The logistics of the former are easier than the latter, but the work involved in the latter can be greater. Either way, you have to test the changes on each platform.

And unless the entity is mature with a relatively well-defined semantics, my experience is that almost everything changes. So stability is nice, but might be a bit of a red herring.

That being said, I like (and +1) @Dmitry.

drdwilcox
  • 3,833
  • 17
  • 19