3

I am currently designing and implementing a framework using Domain Driven Design concepts.

I am trying to put the Validation in the domain model layer.

Sometimes doing validation needs to access the database and query it, as an example :

"querying to check multiple column unique index"

With respect to this and the fact that queries should be written in the repository layer classes, It comes out that domain entities need to have references to their repository interfaces in the domain model layer in order to put the validation completely in the domain model layer.

I wonder if It is ok for domain entities to have access to repositories ?

And if it is not ok then how should this situation be handled?

I mean should such validation methods be moved to repository or Application Service Layers? If yes, is It ok to move the validation methods to those layers ?

Or as domain services can have access to repositories, should we create domain services in the domain model layer for validation?

How should we handle It?

thanks in advance

gwt
  • 2,331
  • 4
  • 37
  • 59
  • 2
    Possible duplicate of [Is it ok for entities to access repositories?](http://stackoverflow.com/questions/827670/is-it-ok-for-entities-to-access-repositories) – guillaume31 Jan 03 '17 at 19:54
  • @guillaume31 I don't think it's the same as the question you mentioned, and I edited my question and added more details. Any solutions would be appreciated ! – gwt Jan 03 '17 at 20:05
  • What invariant exactly do you need to check? Which aggregate root are we talking about and why should it be its responsibility to validate this uniqueness? "Checking multiple column unique index" is not much of a domain description... – guillaume31 Jan 03 '17 at 20:05
  • your Q title is exactly the same as the Q I linked to – guillaume31 Jan 03 '17 at 20:06
  • I am trying to put the validation in the domain model layer to handle all complexities that sometimes might happen in validation! for example validating a complicated domain service such as production line feed that is a very complicated process if you know. And checking the uniqueness is just another condition where querying is needed. In such conditions It happens that you might need to query the database so you need to access the repository for it. – gwt Jan 03 '17 at 20:11
  • So how should this situations be handled ? – gwt Jan 03 '17 at 20:12
  • It depends on your context and domain. There's no hard and fast answer as long as we don't know the context. – guillaume31 Jan 03 '17 at 20:13
  • I know that "Checking multiple column unique index" is not much of a domain description but it is a validation necessity to be checked before adding an entity to database and if you want to put the validation in the domain model layer so It should be checked in there. – gwt Jan 03 '17 at 20:21
  • downvoter any comments? – gwt Jan 03 '17 at 20:30
  • A few existing questions whose answers are all true at some level : http://stackoverflow.com/questions/998317/where-should-i-put-a-unique-check-in-ddd , http://stackoverflow.com/questions/2660817/ddd-validation-of-unique-constraint. Also check out http://thinkbeforecoding.com/post/2009/10/28/Uniqueness-validation-in-CQRS-Architecture – guillaume31 Jan 03 '17 at 20:33
  • @guillaume31 thanks. as Samuel says in http://stackoverflow.com/questions/998317/where-should-i-put-a-unique-check-in-ddd One possibility is to do the same way I mentioned. adding a method to repository for example: GetByName() where Name should be unique, and then call that method from the Model class. This solution needs the model to have a reference to the repository. So from your opinion Is it ok? – gwt Jan 03 '17 at 20:44
  • Could be depending on your context, but you have to be aware that race conditions could occur, and now the entity has an "inpure" dependency to a concrete Repository that has to be passed to it somehow. – guillaume31 Jan 03 '17 at 21:14
  • I usually like the solution from thinkbeforecoding's blog better, but then YMMV depending on your domain – guillaume31 Jan 03 '17 at 21:15

1 Answers1

4

I wonder if It is ok for domain entities to have access to repositories ?

Not really - it creates a dependency tangle among your components.

The architectural expectation is that an aggregate, when loaded, has all of the state information needed to protect its invariant. Any other state involved in a modification to the aggregate should be passed in as an argument.

So the need to query something outside of the aggregate boundary suggests that there is a flaw in your design (the constraint you are trying to enforce isn't "real", the aggregate boundary is drawn in the wrong place, etc).

Using a domain service to support the query that the aggregate needs is better than connecting to the repository directly, but not a whole lot better. The domain model is supposed to be isolated from the environment, but introducing a domain service (or a repository) to support validation binds the domain model to the process boundary.

An acceptable alternative, which may fit your needs, is to have the application fetch the necessary data from the repository and then pass a representation of that data (or a domain service that provides access to that data) to the aggregate, which can then use it for "validation".

Note that you have a consistency issue - some other aggregate can be changing the remotely located data while you are using a stale copy of it to "validate" your own changes. If your aggregate boundaries are correct, the cost to the business of an inconsistency here should be "small".

The key takeaways being that state retrieval and state validation are separate concerns, and understanding that any state that an aggregate does not control is necessarily stale -- separating retrieval and validation in time doesn't add a new race condition to your system. So leave the data retrieval in the application component, put the validation in the aggregate, and accept the tradeoff that you are working with stale data.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • Thanks a lot. What if the repository instance is passed to domain entities from above layers using constructor injection ? Like the way it's done for domain services . – gwt Jan 06 '17 at 12:10
  • @VoiceOfUnreason I have almost the same problem now. AR contains a value object collection, it is a large collection and and the value object also is a large object. But the value object contains a identity, so I make AR hold the value object identity instead. AR implement the logic to find some value object identity from the identity collection, and also need the detail of the found value object, so How can I resolve this? – YonF Aug 20 '18 at 05:03
  • If an object is being _injected_ with any other component, it conceptually looses its status as domain model. As intriguing as it might by to give a domain model direct access to its repository, don't do it. Domain models literally only mind their own business. – Arman Sep 22 '20 at 07:00
  • It seems to me that you're being too dogmatic regarding DDD. There are many occasions where loading an entire list of associated entities is poorly performant, and it doesn't seem logical to compromise so much performance just to adhere to DDD principles. – Julian Gr Aug 21 '23 at 14:05