Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>No, in my opinion domain entities should never be allowed to be invalid, even temporarily. The problem is that it if you allow the domain to be invalid, just like you described in your question, it gets difficult to introduce new rules as complexity grows. For example you allow entity to be invalid due to some attribute, assuming that it will be validated later. But before that happens someone adds another rule, that varies its result in accordance to the same attribute - how do you know if the rule behaves correctly? You don't. Believe me, it happens quite often in non trivial domains.</p> <p>The other reason for nor allowing state to be invalid is that in certain scenarios it can introduce problems with ORMs - I have personally seen an issue involving NHibernate cache and sub-entities that were invalid but somehow still remained in cache, I can't recall any specific details though.</p> <p>The technique I tend to use bases on validation rules and validation results. In short, most of the methods on entities is implemented in the following way (C#, if you don't mind):</p> <pre><code> public virtual void ChangeClaimEventDate(DateTimeOffset newDate) { var operationResult = ValidatorOf&lt;Claim&gt; .Validate() .WithCriticalRuleOf&lt;EventDateFallsIntoPolicyCoverage&gt;().WithParam(newDate) .WithCriticalRuleOf&lt;EventDateFallsIntoInsuredCoverage&gt;().WithParam(newDate) .WithCriticalRuleOf&lt;PerformedServicesAreAvailableOnEventDate&gt;().WithParam(newDate) .WithCriticalRuleOf&lt;EventDateCannotBeChangedForBilledClaim&gt;().WithParam(newDate) .ForOperation(this); if (operationResult.OperationFailed) { throw new InvalidBusinessOperation(operationResult); } SomeDate = newDate; } </code></pre> <p>The most important thing about this code, is that certain validation rules are checked even before the entity is changed. This example shows usage of result sets, as very often I need to provide information about validation even if it succeeds (in other words, I have validations that fail and information about it has to be shown to user; however the domain entities are still valid.</p> <p>The <code>OperationResultSet</code> and <code>ValidatorOf</code> are pretty simple infrastructure classes that allow adding new validators easily with fluent interface. The validators are implemented as classes implementing <code>IValidator</code> interface, which allows implementation of pretty complex validation rules and it is easier to test them individually as well.</p> <p>My point is, that validation should be performed before the changes to domain entities are performed - with the right convention and some infrastructure it even simplifies the code structure.</p> <p>Edit note: due to some critical voices for this answer, I've decided to change the sample code to one that throws an Exception instead of returning results. Although I still believe that it is the way to go for my kind of scenarios, I agree that without specifying full context this might be misleading - the Exceptions should be indeed the first option and additional factors should exist to choose alternatives. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload