I have a question on validation approaches in ddd. I've read quite controversial opinions on that. Some say that this should live out of entity, others say that this should be placed in entity. I'm trying to find an approach that I could follow.
As an example, suppose I have the User entity with email and password. User has a method Register(email, password). Where should the email and password validation be placed? My personal opinion is that it should be inside the Register() method. But such approach might lead to messing User class with validation stuff. One approach might be to extract the email and password rules in separate policy objects and still invoke them from Register() method.
What is your opinion on validation approaches in DDD?
First off, I think validation is somewhat of a slippery subject due in part to the various contexts within which it needs to be considered. Ultimately, there will be validation rules executed at various application layers. At the very least, there should be standard guards in domain objects. These are just regular pre-condition and argument checks that should be part of any well designed object and fits with your opinion for the Register method. As stated by lazyberezovsky, this is to prevent the objects from getting into an invalid state. I side with the always-valid school of though on this. I think if there is a need to persist entities in an invalid state, a new entities should be created for this purpose.
One issue with this approach alone however is that there is often a need to export these validation rules to other layers, such as to a presentation layer. Moreover, in the presentation layer, the rules need to be formatted differently. They need to be presented all at once and potentially translated into another language, such as JavaScript for immediate client-side feedback. It can be difficult or impractical to attempt to extract validation rules from exceptions raised by a class. Alternatively, the validation rules can be re-created at the presentation layer. This is much simpler and although potentially violating DRY it allows for the rules to be context dependent. A specific workflow may require for different validation rules than the ones enforced by the entity itself.
The other issue with the described approach is that there may be validation rules which exist outside of the scope of an entity, and these rules must be consolidated together with the other rules. For example, for user registration, another rule is to ensure that the email address is unique. The application service hosting the applicable use case would usually enforce this rule. However, it must also be capable of exporting this rule to other layers, such as presentation.
Overall, I try to place as many constraint checks into the entities themselves because I think entities should be always-valid. Sometimes it is possible to design the rule framework such that it can be used to both raise exceptions and be exportable to outer layers. Other times it is easier to simply replicate the rules across layers.
Actually validity of user is context dependent. User can be valid (name and email are valid), but registration operation can be impossible to perform. Why? Because there can be already existing user with same name. So, user which looks like valid in some context, can be invalid in registration context.
So I'd moved part of validation into entities or value objects (e.g. Mail object) to avoid obviously invalid states of entities (e.g. user with null name). But context-dependent validation should exist in that context. So, if I'm registering user:
Mail mail = new Mail(blahblahblah); // validates if blah is valid email
User user = new User(name, mail); // validates if name is valid and mail not null
// check if there already exist user with such name or email
repository.Add(user);
Also I think that method Register should be method of some domain service (like MembershipService), because it definitely should use some repository.
As an example, suppose I have the User entity with email and password. User has a method Register(email, password). Where should the email and password validation be placed?
If you are following DDD, email address and username are key concepts in your domain - so they should be represented as entities. In that case, the validation for an email address lives in the EmailAddress entity, and the validation for username should be placed in the Username entity.
pseudocode example:
class EmailAddress
{
Constructor(string email)
{
if (email.DoesNotMatchRegex("\w+#\w+.\w{2,3}"))
throw error "email address is not valid"
}
}
class Username
{
Constructor(string username)
{
if (username.length < 6)
throw error "username must be at least 6 characters in length"
}
}
class User
{
Register(Username username, EmailAddress email)
{
if (username == null)
throw error "user must have a username"
if (email == null)
throw new error "user must provide email address"
// At this point, we know for sure that the username and email address are valid...
}
}
First of all i would separate between two things: Validation and Business Rules where the latter normally goes into a service or an entity method. For validation such as valid e-mail address or valid passwords i usually stick them onto the entity that owns them so i can move them around with the entity if i ported my application to a different platform. Now for your register method example i can't see why would this method be called in the first place if the object was in an invalid state, and if it will be called i will make it a step in another method like SignUp that might do something like this: if (isValid()) register(username, password).
Related
What is the difference between using user.Email vs await _userManager.GetEmailAsync(user)?
I mean, once I have the user instance itself, what is the use of the _userManager's GetEmailAsync() method which takes exactly that user instance as parameter? I can access the user's email via its property.
I examined the source and I do understand that there is an abstraction layer of using IUserEmailStore but its default implementation is just returning the Email property...
I also do understand, that may exist other implementations, of IUserEmailStore but this case the question will arise: are the user.Email property and _userManager.GetEmailAsync(user) consistent to each other, or are not?
If not, that is a problem, if yes, then we are returned to the original question: what is the use case of using _userManager.GetEmailAsync(user)?
(the same question goes to UserName, PhoneNumber, etc properties)
What is the difference between using user.Email vs await UserManager.GetEmailAsync(user)?
user.Email only works if your TUser actually has an Email property in the first place.
Fun-fact: ASP.NET-Core-Identity does not actually require whatever class you're using for your TUser to have a String Email property.
i.e. what you're presupposing (that users have e-mail addresses) is not actually guaranteed in, nor required by, ASP.NET-Core-Identity.
ASP.NET-Core-Identity's only constraint on TUser is TUser : class, so you could even use String or IDictionary for your TUser if you're brave enough.
While ASP.NET-Core-Identity does have a String Email { get; } property defined only on class Microsoft.AspNetCore.Identity.IdentityUser<TKey>, but you are not obligated to use this class at all: it's just a prewritten implemention that covers the most common use-cases and (probably) saves most people time by having them subclass it.
But there are also other scenarios to consider:
...such as domain-model design where users have multiple e-mail addresses per user, in which case having a single scalar String Email { get; } property simply won't work... though neither would GetEmailAsync either, but that's another part of ASP.NET-Core-Identity's design that you missed: you can implement IUserStore<TUser> and not implement IUserEmailStore<TUser>, so there wouldn't be either an Email property nor a GetEmailAsync method. (Just make sure you don't subclass class UserStoreBase) and instead build your store implementation from scratch.
In this hypothetical case, where no types implement IUserEmailStore<TUser>, there wouldn't be any methods anywhere in your codebase that would have to throw NotImplementedException or NotSupportedException. And that's a good thing: a common mantra when designing a domain-model is to "make invalid things impossible" (that's my corruption of the original maxim "make invalid state unrepresentable").
Another scenario is some (atypical, I'll admit) system where Users do have an email address, but it's not stored or represented by the in-memory User object, in which case you would have to use a custom implementation of GetEmailAsync to get a user's email address every time.
I imagine this might be a possibility when using a back-end user-store with extremely fine-grained security (e.g. some paranoid Active Directory setup where the current Thread's NT security token is used to attest permission to request e-mail addresses from the directory... but that idea is just speculation and I hope no-one ever actually has to support that, at least not without good blood-pressure medication on-hand).
In conclusion: Not every system has user e-mail addresses, and ASP.NET Core Identity doesn't require them to expose them - and the (admittingly very complicated) design of ASP.NET Core Identity reflects that.
.Net Core 3, Clean Architecture.
I have read a lot articles about data validation with CQRS. For example there and there.
I have done some conclusions:
Need to validate data in DTO. It is contract for entities.
Some suggestions from authors validate date into entities (domain).
In CQRS AbstractValidator we can validate too, but other rules.
Email field validation will be in 1 and 2.
Age restriction will be in 3.
But three validations in server + one in client are problem (big DRY).
Where is better validation in DTO or Entities? I think in DTO, because when I get DTO from input, I can validate and call ModelState.IsValid. But I read some articles that need validate input data in entities too.
So, I'm confused. Can you explain me:
If need to validate an Email field, and an age restriction (18), where need to put validation in Clean Architecture with CQRS?
All your Api contracts, commands should rely on primitive types. Once you want to initialize your domain model, here is where you will not be able to do it, if smth is wrong. If you do DDD, it suggests to prevent object being in invalid state versus validating an invalid object (Domain model vs Crud based).
Clean Architecture splits the responsibility by layers, each layer should have its own validation logic.
Each layer should reject the input which breaks its layer's responsibility. This is validation. So the meaning of validation is differrent depending on its context.
It all depends on the type of validation. Is it superficial or deep validation?
Superficial validation is things like password strength or checking for the correct format of a URL or email address. Whereas deep validation is the kind of thing that matters to the domain. So that could be something like, is this cargo hazardous or is this person too high a risk to extend credit to.
Check out this post which explains that concept in more detail from a CQRS perspective: How to validate Commands in a CQRS Application
I have an aggregate root called User.
Here's an example of how it's modelised:
User: {
id: string
username: string,
email: string,
auth: LocalAuth {
password: string
}
}
In my application, I have an API route -
POST /users/id/password - that allow users to change their password.
In order to change their password, we must ensure that users enters their old password. The request model should look like this:
{
oldPassword: string
newPassword: string
newPasswordRepeating: string // in case of user errors
}
The controller that handle this request should do the following:
Check if the oldPassword is equal to the current one
Check if the newPassword is valid
Update the user data
Return the updated user data
In order to handle such business logic, I could create a VO model named PasswordUpdate (idk..). This VO could encapsulate the validation logic in its own model.
Does this kind of implementation faithfully follows the DDD rules?
Because in my case, this VO is never contained in an Aggregate Root and is not stored. The purpose is only to modelise a password update with a domain model.
Does this kind of implementation faithfully follows the DDD rules?
Very short answer: go right ahead.
Short answer: the DDD police are not going to come after you anyway, so don't over think it.
Broad answer: I find that the description of Value Objects by Evans is something of a muddle, polluted by the fact that he was drawing from experience in Java.
But if you look really carefully, what's going on is that Evans is proposing the creation of a domain specific language that you can use to describe the behaviors of the model. Value objects are doing a few things: they are giving you domain specific types (so that the type system can assist, as it it able, in restricting the frequency of certain kinds of errors), they are giving you domain specific semantics (rather than insisting that all domain behaviors are described via operations on domain agnostic primitives), and they are providing an isolation layer between the domain behavior and the in memory representations of domain state.
The value of this is not restricted to the "domain model"; you should feel free to apply this abstraction everywhere it makes sense to do so.
BUT... there is a particular trap in the case that you describe that you should be aware of.
The domain model is something that you are supposed to able to change aggressively to meet the needs of the business, which of course can include changing the implementation of the value objects.
Messages, however, should be changed conservatively. Messages are part of the API. If we want to be able to release compatible clients and servers using a different cadence for each, then we need the interface between them to be stable. The message shouldn't be carrying domain rules with it (those belong in the model), it's just a representation of state.
"Validation" usually happens when we take the message (part of the api) and translate it into values understood by the model.
This question is related, but more specific than this question.
I'm going to use a simple example here. Say we have a User entity in one context and a Customer entity in another context. These are 2 different representations of the same entity.
Let's say the User and Customer both have an email address, but the email address is always changed via the bounded context that the User belongs to. So the user context is the source of truth for the email address. So ideally I would like the email address in the Customer context to be immutable from the point of view of the customer context.
So when the email address is changed in the user context, an EmailAddressChanged event is emitted. This is fine; I subscribe to the event in the Customer context. However, I now need to handle this event by mutating the Customer email address. So I need some sort of command method to make this change.
How can I ensure that the command method is not used, other than when handling the event from the User context?
If I allow mutation in both contexts then they both become sources of truth and I need double the number of events and handlers to ensure that the information remains consistent in both contexts
Maybe there is a hidden customer/supplier relationship between these bounded contexts? If User bc is the source of truth for Customer bc, then User bc might expose an API to be accessed by downstream contexts (Customer, maybe something more?). In your question you said only the email address should be "immutable" and dependent on User context - however, I think it might a hint that entire Customer context is a consumer/customer of User context and should use its public API (which should not expose internal user domain model directly - some facade classes are required to hide the details).
If that's not the case, and there is no such relationship between the contexts - you can use a specialized component in your Customer bc to make changes to the database, without directly invoking domain methods. Then, the repository can be used to query customers and recreate them with updated email address. My point is - if you want customer bc to apply EmailAddressChanged events, you obviously need something to alter the database, but you don't need to do that via domain methods. The component applying EmailAddressChanged events would be part of the infrastructure layer of Customer context. If you use this solution, then there is no risk of modifying customers via business case scenarios.
Btw, isn't your Customer in fact a specialized read model of User context?
In Domain Driven Design, there is an emphasis of placing behaviors where they correctly belong. I'm not always sure what exactly constitutes "correct," though.
Consider this scenario: "The client withdraws an amount of money from a bank account."
Grammatically, we have that:
'client' is a subject
'withdraw' is a verb
'amount' is a direct object
'account' is an affected prepositional object
Classically, the client would execute this: account.withdraw(amount).
This could be read as: "The client commands a bank account to withdraw an amount of money." However, this does not grammatically correspond to the original scenario, since 'bank account' is now the direct object and an infinitive removes 'withdraw' and 'amount' from the main clause so that the primary idea conveyed is that 'client commands account'.
To adhere to DDD, we should regard this code as precisely describing the original scenario. This implies that the 'withdraw' method does not model a behavior performed by the account (the account is not a subject), but rather it models a behavior that indirectly affects it (the account is a prepositional object) and could very well be renamed 'wasWithdrawnFrom'. Moreover, the method argument represents something being affected by the client as opposed to by the object (it is a direct object for a client subject, not an object subject).
If we extrapolate from this example, we can see that methods may represent behaviors that affect the object (object is not the subject) and method arguments may represent direct objects of a client subject.
However, whether or not methods should represent behaviors performed by objects is unclear.
So my question is: How should we use methods to model object behavior?
1) Methods should strictly represent behaviors that affect the object. (The object cannot act as a subject, only a grammatical direct/indirect/prepositional object)
2) Methods may represent both behaviors that affect the object as well as behaviors performed by the object. (The object may act as a subject or a grammatical direct/indirect object)
You seems to be stuck in a theoretical thesis. I'm not sure you can apply a theory that works for every scenario/project. Behaviors usually appears when you start bombarding your Model with Use Cases. I try to let the cases dictate behaviors.
To follow your example:
Actor Customer want to withdraw money from Account. The way to do it is like you do Account.Withdraw(Money amount)
But your question "How should we use methods to model object behavior?" is a common DDD question. How to enrich your model with behavior? My best hints is to find your Value Objects. Value objects usually comes with behavior.
In example Account is and Entity (Aggregate root probably). Money (Value object with Currency and Amount) should be withdrawn from an Account. That should be Account Single Responsible (Principle) to control that Account balance and all access to it.
Regarding your (2) question in the end. Methods are absolutely used for change the objects inner state. But when it comes to behaviors performed by the entity/value object like
Customer.Order(newOrder) or advert.Apply(candidateCV) we can make entities communicate with each other. We can also create chained behaviors through Domain Events which can help us not to leak to much business logic to our application services. See Udi Dahan's blog for that or my blog article regarding Anemic Domain model http://magnusbackeus.wordpress.com/2011/05/31/preventing-anemic-domain-model-where-is-my-model-behaviour/
I Hope you got some ideas. It's difficult to give concrete hints when we are so abstract here.
/Best regards Magnus
I find that scenario too simple to be real, hence too simplistic to model too. I would reformulate the
"The client withdraws an amount of money from a bank account."
to something like
"The client submits withdrawal request of value xxx $ from his account" (when I go to my bank I have to fill out a form in order to withdraw money where I state amount, the account number, date and my signature)
There one can spot a request (command) to a service (withdrawal service) of an client (client identified by ID) from his account (account identified by ID) and the money value (money as value object).
I don't care much about the grammar, as English is my second language so when trying to understand the Domain, I try to understand how the business sees the concepts (Account) and workflows (withdraw an amount) and not to do grammar analysis.
The point of DDD is to model things like they are in the business, so behaviour shows up according to Domain understanding.
in this scenario, for me it's clear that we're working within the Account Operations Bounded Context and at least the Account aggregate root is involved. Of course, in banking terms, probably (I'm guessing here) there will not be a withdrawl but an operation to increase the Debit/Credit part of an account, so most likely the account will register that a debit/credit operation has happened. And a Domain Event is born and published. Then let the domain expert tell you what will happen next.
"The client deletes an order" => order.delete
Probably the order is never deleted, but its status will changed to 'canceled' or similar. However for that case when an order really should be deleted, the order doesn't delete itself, the Orders repository deletes that order.