Is usage of value objects from third-party libraries in domain entities acceptable as per Domain-Driven Design?

43 Views Asked by At

My team and I are building an application for our company and we need to use Java Money (JSR-354) and its Reference Implementation to represent monetary values. We are trying to build this application as per the guidelines of DDD. To that end, we wanted to understand if it is acceptable to use value objects such as javax.money.MonetaryAmount from inside a domain entity (example Bill).

Since this couples the domain model with a third-party library, is this practice considered normal in the DDD paralance?

While we are using this arrangement at this point, we wanted to understand if this is considered an anti-pattern and if it would ideal to use our own value object to represent money value and move the use the javax.money.MonetaryAmount during persistence (inside adapters).

2

There are 2 best solutions below

0
Alex Borodin On

The Dependency Inversion Principle says high-level modules should not import anything from low-level modules. So, the domain as a system's center should not depend on any library.

So, you can create your own interface for these value objects and use them via dependency injection.

This is in theory.

But if we go a bit deeper, to understand why this principle applies, we need to consider future change probabilities.

Domain changes less frequently than any other part of the application, for example, UI. So, the domain should not depend on UI to avoid the situation when we need to fix the domain model each time we change the button color. And so, we need to use dependency inversion to depend on abstraction.

In other words, you need to weigh the risk of library change. If you imagine that the library interface will change or you'll need to replace the library, you should not use it directly. Create an abstraction.

If it is a common library that has not changed its interface for years and is only one possible library to use, then there is no need to add complexity.

0
VoiceOfUnreason On

Short answer: you should evaluate javax.money.MonetaryAmount similarly to the way you evaluate java.lang.String or java.util.ArrayList.


Domain Driven Design: Tackling Complexity at the Heart of Software is the first DDD book, written by Eric Evans. Chapter 10 ("Supple Design") discusses this topic:

In every programming environment, a few basics are so pervasive that they are always in mind. For example, in Java development, primitives and a few standard libraries provide basics like numbers, strings, and collections. Practically speaking, "integers" don't add much to the intellectual load. Beyond that, every additional concept that has to be held in mind in order to understand an object contributes to mental overload.

Consider a shipping application that needs to track locations. LOCODE identifiers are not Strings, but Strings are a general purpose data structure that can store LOCODE data. So it is reasonable to use String as part of the underlying implementation of the Location domain value, as shown here: https://github.com/citerus/dddsample-core/blob/master/src/main/java/se/citerus/dddsample/domain/model/location/UnLocode.java

Analogously, your domain probably doesn't have "MonetaryAmount", but might reasonably include Price, or Salary, or Bet/Ante, or any of a number of other domain specific concepts that might be implemented using a general purpose MonetaryAmount data type.

Introducing a library dependency to leverage a general purpose implementation is fine; which is to say that, yes, of course there are trade offs, but it's pretty common for those trade offs to be favorable.