sashok_bg
sashok_bg

Reputation: 2999

DDD Call Adapter from Within Domain Object

I am implementing a Hexagonal Architecture with Domain Driven Design.

I have a Value object called "Address" that has a "validate()" method. I would like to have a default validation provider for the address that is within my domain, but also allow external users to provide an overridden validator.

So I created an AddressValidationAdapter interface that can be implemented by the outside world in "dependency inversion" manner.

My question is - what is the best way to call my AddressValidationAdapter from within my Address class ?

Thank you very much for your thoughts. Best Regards Alex

Upvotes: 0

Views: 1342

Answers (2)

rascio
rascio

Reputation: 9279

Do I need to add it as a dependency in its constructor ?

Absolutely no! Value object are data and you are putting yourself in a hell with serialization/deserialization for it

Should I use some sort of global / static context ?

Not sure what you mean, but global/static context is scary, what about multiple validation done in parallel?

Should I use event driven approach where I post a "ValidationEvent" within my domain and subscribe to a validation success notif ?

Domain events are related to entities state changes, nothing is changing when you do validation

Should I create a Service that orchestrates everything ? (Seems not very DDD like)

It could be...

but also allow external users to provide an overridden validator.

I'm very curious of the details of this, why an external user would need a different validation?
Could it be that an Address has some sort of generic validation that need to be always checked, but different use cases have more stricter rules?
If that's the case why the Address itself would need to know them? It is just a value! An Integer just know that it has to be a number if in certain usage you need it to be in a range of values it's something that you add to it, but it doesn't know about it

DI/IoC approach is good and I was thinking you could do something like:

class Address {
    ....

    validate(AddressValidationAdapter customValidation) {
         // generic validation then...
         customValidation.validate(whatAreYouPassingHere)
    }
}

Whatever you are using as whatAreYouPassingHere, can't the code doing:

Address address = ...
address.validate(customValidator)

just read the values needed from the address and do its own validation?

Upvotes: 1

ArwynFr
ArwynFr

Reputation: 1722

You mention Domain Driven Design, which is a practice that requires all business related code to go in a domain layer, and all non-busines related code to go out of that domain layer. Other than that, DDD is more concerned by how you design and evolve your business model, not so much about application architecture. The author of the DDD concept states that it can be used with any software architecture.

You also mention Hexagonal Architecture, which addresses software architecture, and has more constraints on how you structure your code. Hexagonal Architecture defines 3 concentric layers in applications:

  • The domain layer validates that state changing values do not violate business rules;
  • The ports layer is a business representation of infrastructure interactions;
  • The adapters layer implements the actual communication with external infrastructure.

Hexagonal Architecture also states that type references should go inwards, which means ports are not allowed to reference adapters, and the domain model is not allowed to reference other layers. A good practice is also to forbid direct reference accross different adapters. However, this is not much of a concern in your situation.

Address validation is definitely not an adapter layer concern, because it is not related to how your application interacts with an external infrastructure or data structure. This means that address validation should not be implemented as an adapter, in the sense of Hexagonal Architecture. It is not a port either for the same reasons. Address validation should go in the domain layer, because business rules validation is the purpose of the domain layer (Hexagonal Architecture) and all business related code should go in the domain layer (DDD).

However, neither DDD nor Hexagonal Architecture state anything on how you should structure your domain layer internally, so it is up to you. If you want your application to use different validation implementations, you may want to use the adapter pattern in cunjunction with a dependency injection library. Note that "adapter", here, refers to a software engineering desing pattern that has inspired the Hexagonal Architecture concept of adapter layer, but is totally independant from it.

Since the purpose of the domain layer is to validate state changing data, there should be very little code apart from validation rules implementation and data structure. If you move the latter to a validator class, there will be little left to write in the domain model objects themselves. You are probably going to end with an anemic domain model this way. You might want to consider implementing Always Valid State domain model, where validation rules are implemented directly in the domain model's setters and constructors.

If you wrote an adapter class due to the fact that you need to retrieve external data to do the actual validation, this is a good evidence that your domain model is lacking information and should be extended, rather than violating Hexagonal Architecture constraints.

Upvotes: 2

Related Questions