DDD - can I use value objects as models helpers - api

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.

Related

Patterns when designing REST POST endpoint when resource has a computed property

I have a resource, as an example a 'book'.
I want to create a REST POST endpoint to allow consumers to create a new book.
However, some of the properties are required and computed by API, and others were actually taken as they are
Book
{
name,
color,
author # computed
}
Let's say the author is somehow calculated in API based on the book name.
I can think of these solutions each has its drawbacks:
enforce consumer to provide the author and just filter it (do not take into account as an input) # bad because it is very unpredictable why the author was changed
allow the user to provide author # same problem
do not allow the user to provide an author and show an exception if the user provides it
The last solution seems to be the most obvious one. The main problem I can see is that it is inconsistent and can be bizarre for consumers to see the author later on GET request.
I want my POST endpoint to be as expressive as possible. So the POST and GET data transfer objects will look almost the same.
Are there any simple, expressive, and predictable patterns to consider?
Personally I'm a big fan of using the same format for a GET request as well as a PUT.
This makes it possible for a client to do a GET request, add a property to the object they received and immediately PUT again. If your API and clients follow this pattern, it also means it can easily add new properties to GET requests and not break clients.
However, while this is a nice pattern I don't really think that same expectation exists at much for 'creation'. There's usually many things that make less less to require as a property when creating new items (think 'id' for example), so I usually:
Define a schema for PUT and GET.
Define a separate schema for POST that only contains the relevant properties for creation.
If users supply properties not in the schema, always error with a 422.
some of the properties are required and computed by API
Computed properties are neither required nor optional, by definition. No reason to ask consumers to pass such properties.
do not allow the user to provide an author and show an exception if the user provides it
Indeed, DTO should not contain author-property. Consumers can send over network whatever they want, however it is the responsibility of the API-provider to publish contract (DTO) for consumers to use properly. API-provider controls over what properties to consider, and no exception should be thrown, as the number of "bad" properties that can be sent by consumers is endless.
So the POST and GET data transfer objects will look almost the same
Making DTOs of the same resource look the same is not a goal. In many cases, get-operation exposes a lot more properties than post-operation for the same resource, especially when designing domain-driven APIs.
Are there any simple, expressive, and predictable patterns to consider?
If you want your API to express the fact that author is computed, you can have the following endpoints:
POST http://.../author-computed-books
GET http://.../books/1
Personally, I wouldn't implement that way since it does not look natural, however you can get the idea.
I want my POST endpoint to be as expressive as possible. So the POST
and GET data transfer objects will look almost the same.
Maybe just document it instead of relying explicit stuff like it must be almost the same as the GET endpoint.
E.g. my POST endpoint is POST /number "1011" and my GET endpoint is GET /number -> 11. If I don't document that I expect binary and I serve decimal, then nobody will know and they would guess for example decimal for both. Beyond documentation another way of doing this and to be more explicit is changing the response for GET to include the base {"base":10, value:"11"} or changing the GET endpoint GET /number/decimal -> 11.
As of the computed author I don't understand how you would compute it. I mean either a book is registered and the consumer shouldn't register it again or you don't know much about the author of it. If the latter, then you can guess e.g. based on google results for the title, but it will be a guess, not necessarily true. The same with consumer data, but at least that is what the consumers provided. There is no certainty. So for me it would be a complex property not just a primitive one if the source of the information matters. Something like "author": {name: "John Wayne", "source": "consumer/service"} normally it is complex too, because authors tend to have ids, names, other books, etc.
Another thought that if it is weird for the consumers instead of expected, then I have no idea why it is a feature at all. If author guessing is a service, then a possible solution is making the property mandatory and adding a guessing service GET /author?by-book-name={book-name}, so they can use the service if they want to. Or the same with a completely optional property. This way you give back the control to the consumers on whether they want to use this service or not.

What is the difference between using user.Email vs await _userManager.GetEmailAsync(user)?

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.

Good practice to achieve this eventual consistency

In my application, when a user is created, an Event called UserCreatedEvent is thrown.
This user must have all his description data retrieved from Facebook (with his authorization of course) and should be treated by some custom process.
I chose to apply eventual consistency (using Akka and his eventStream feature to handle events) between the fact of saving the user aggregate and the fact to retrieve all his description data and apply them, since it involves some call network to Facebook.
The point is I also allowed any newly created user to override some of the description (job, age etc.) through the REST api PUT /api/users/:id.
1) Should the process of handling UserCreatedEvent (basically an Akka actor) call this api (causing an indirection) to assign default user description (from Facebook) or should it retrieve and update user itself?
2) Should the process of handling UserCreatedEvent and the api aiming to manage User (CRUD) be part of the same bounded context? (in that case, no recommendation to involve the indirection).
I'm not sure I would call this eventual consistency, since consistency (making sure that an entity respects invariants) is not at stake. This is more like out-of-band asynchronous data completion.
What hoops this side process has to go through again basically depends on your context :
REST API if there's important stuff there you want to reapply (logging, security, whatever)
Application Service / Command handler layer if you want that data completion to be treated as a full blown modification with proper validation (e.g. did Facebook return data that would be unsupported in your application ?)
In the domain layer, you could model it either as just any other modification of the User, or as a specific, maybe more intention-revealing operation : User.completeDescriptionData(...)
I wouldn't necessarily place this in a different Bounded Context since it doesn't introduce a new definition of User. It's important that the part that knows the nitty gritty details of talking to Facebook is in a separate non domain layer though.

How do you represent domain object behaviors using methods when a domain object is acted upon and not the actor?

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.

Validation approaches in ddd

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).