5

It feels right to put format validation inside the domain objects (VOs or entities) because it is the natural place for high cohesion and the domain knows best what every domain description/attribute/property means. Many DDD practitioners and books authors (Vaugh Vernon, Dan Bergh - and even Eric Evans suggest , but on a different aspect: authorization, to model the domain to reflect these matters) suggest to design the domain model in a way to reflect and enforce a proper state of the business.

I agree that format validation (ie.: address property in EmailAddress VO should be max ~250 chars and should match a regex) should be implemented inside the domain objects. But these validation checks work best with a domain model that will be used for both state changes and state queries.

What about CQRS where the command side (where the domain model is) has little or no knowledge about the read side. Should one reimplement the same input format checks in the query side of the application? In CQRS there are some common responsibilities for both command and query side (like input format validation), so the usual format validation implementations that most of DDD practitioners suggest will be duplicated.

How should one deal with this, w/o making the domain model (from the command side) to be anemic and w/o making unaware of the state of the attributes it will hold .

An example : there might be a feature that would let a conference owner to schedule a conference and change the number of available seats. But because the conference room is not big enough, the maximum allowed number of seats would be 100. So a business rule would be that : a conference owner cannot add more than 100 seats for a scheduled conference (also minimum 1 seat needed for the conference to be in a valid state). So a method would be on a ConferenceAR :

changeNumberOfAvailableSeats(numberOfAvailableSeats) {
    if(!isNumber(numberOfAvailableSeats) || numberOfAvailableSeats > 100 ||   
            numberOfAvailableSeats < 1) {
        throw new DomainException ...
    }  

    // Change the number of available seats ...
}

On the query side there might be an UI page where you can find all the scheduled conferences that have a certain number of available seats. So again , on the server's query side of the application, there must be a format validation that will check if the query for scheduled conferences with a number of seats available is a number and is in the range 1-100. This query might be needed by someone who wants to reserve a certain number of seats for a conference . Also conferences might be on the same topic so one could see a conference with the same topic many times and choose the one cheaper or with more seats available.

So again, should one reimplement the format validation on both query and command sides or there is another solution?

P.S. : there are many format validation duplicates (on both command and query side) like the email format validation , or a currency format validation (if the currency is : USD || CAD || AUD etc ...)

P.P.S. : Another question that popped up : Does the query side of the application require any input format validation ? If the input is not a valid format it will return nothing , query found no data related to the request. I see that format validation on the query side is purely a security measure (ie. for buffer overflows). So is the input format validation really required on the query side ?

migrated from stackoverflow.com Jun 20 '14 at 15:04

This question came from our site for professional and enthusiast programmers.

3

I would think if your domain objects on the command side are always in a valid state, you shouldn't need to worry that the queries return invalid results.

What would you do, anyway, if you discovered an invalidity on the read-side, anyway? Tell the read repository to re-enter the values? ;-)

If the read side were to have checking, it would think it would be in the area of some kind of unit or integration testing, because instead of a data entry error message, it's a bug.

One of the things about CQRS is prying apart those concerns, plus just having stuff in one place. Otherwise it makes it harder, not easier (really, it can be as easy or easier, otherwise, look for a better way to implement it or keep studying it).

  • My question was about the part before actually fetching the data for query. Format validation as a security concern like buffer overflows. It is not that the queries would return invalid state, it's more about the in between validation for technical concerns , not the state or authorization. Buffer overflow is a technical concern but affects both command and read side – Tudor Jul 10 '14 at 10:11
  • Buffer overflow - I'd call that part of Security or Reliability - both of which are completely cross-cutting concerns so put them wherever they need to go without worry! 'Validation' is a concern which is partially cross-cutting. That's not an industry standard term, but I think you can probably guess what I mean. It often needs to be in more than one layer, but doesn't belong in all. Unfortunately this violates DRY. Often expressing your simpler validation concerns via a very simple DSL which is specd in one spot, interpreted per-layer, solves this (but is only worthwhile in large apps) – FastAl Jul 11 '14 at 16:33
  • AOP should be avoided in my opinion . There are rarely ocasions where AOP is needed . Data format validation actually happens in the domain in the command side . But on the read side is a bit different . The only need for format validation on the read side is for these security checks and nothing more (security as in not state preservation but the whole business protection , like buffer overflow wchich can compromise the whole business). My question was if the validation should be shared by both sides (AOP as you say), but i now decided to separate them and do not use aop. – Tudor Jul 11 '14 at 16:47
  • I totally agree you should separate them. I think I gave the wrong impression with the word 'aspect!' I was definitely not talking about AOP, but 'aspect' in general as a cross-cutting concern; see en.wikipedia.org/wiki/Aspect_(computer_science) Only I don't mean AOP, e.g., you can do logging sans 'strict AOP'. Validation is an aspect in this sense as it cross-cuts some layers (can be in Db, domain objects, controllers, even views - not commenting on where it should go) (note: most devs don't notice this fact). Anyway ... Sounds like you have a plan, good luck it will probably go well! – FastAl Jul 11 '14 at 19:09
  • Thanks +1 and validated, maybe someone will read the comments – Tudor Jul 12 '14 at 6:19
0

If you're using events to transfer data, you can probably treat many of those concerns as simply another kind of data the read-model needs to store and arrange in a convenient way. For example,

  • You'll already want a listener for events like RoomCreated and RoomDisabled from the domain, because you're keeping some sort of fast-to-query representation of what rooms are available, right? Why not also maintain a biggestActiveRoomSize variable at the same time?
  • See a ContactCreated or ContactEmailUpdated event? Check the length and update a stored maxEmailCharacters.
  • See a PricingPosted event? Make sure the currency inside the event is present/added to your own knownCurrencies list. That means shortly after it gets used, it'll become an option people can search with.

In other words, whatever comes from the domain is automatically valid, and everything you see expands the envelope of what you're willing to allow the user to enter.

Granted, this does not work for certain complex things like regular expressions or if/then logic. For those cases, perhaps:

  • As part of your build process, compiling the domain-model emits a configuration file that the query-side can load and use.
  • Outright duplication of logic. Not ideal, but workable as long as the query-side is very clear about where the authoritative source is and you have a procedure around updating the values that humans will follow.
  • Crazier idea: Have the domain model store/broadcast an event whenever it starts up, containing that kind of information. Multiple read-models could decide what (if anything) they want to do with it.

I think you should plan for some duplication (there's always something) but when it comes to "what values or ranges are actually being used", I'd try making it just another part of the read-model.

  • What your are sugesting seems a bit messy . I finally decided (as i wrote in the comments of the other answer) to go with format validation in the domain value objects for the command side, and in the query objects (the query dtos) for the read/quiery side . This way the logic for the format validation does not scatter all over the system . I split the validation in 2 because the query format validation is a bit more flexible t, and differes from the command format validation where full consistency is needed. On the query side is just a simple security check , not consitency check – Tudor Jul 17 '14 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.