I've been researching DDD & CQRS and I'm wondering about the correct way to present a scenario in which the application is actually being used to report what a user has already done (both in the user interface and in the command names).
Assuming I'm doing an application to track a user's activities and there are predefined set of valid activities: Swimming, Eating etc. Leaving aside the discussion about whether this domain is collaborative enough for CQRS or not (because, even if it isn't I'm sure there would be some very collaborative domains that lend themselves to similar semantic analysis), I'd like to know: On the user interface, do I present buttons that say 'Go Swimming', 'Eat' etc, with similarly named commands or do I rather use 'Report Swimming', 'Record Lunch' etc.?
The answer is in your question. I would say the clue is in how you described the application
"used to report what a user has already done"
The button's purpose will to be report a past activity so the command should be named 'Report Swimming', and the event 'Reported Swimming'.
I have faced similar scenarios and have found, 'report' commands and 'reported' events work nicely
Sounds like you are recording events. Things that have already happened and should be tracked somehow. Therefore you wouldn't send any commands at all. Just publish the respective events and handle them in your domain as needed.
Related
This may be a dumb question, but I don't know how to solve this.
I am moving from CRUD to Domain-Driven Design with CQRS.
I have seen many DDD examples like this. You could find many more on Github.
The domain model has methods like changeDetails, addSomething, removeSomething, etc., and the commands could be just like that.
But in the UI, I have only 1 page with all its information, and everything is updated by clicking a single Save button.
How could I trigger all of the commands in 1 click?
If all commands are triggered and 1 fails, could the information be inconsistent?
When you get to this problem, I think you need to redesign your UI and create a more task based UI, you do change one thing at the time. Just like for example when you buy something on Amazon.com, then you don't complete your order with just one big save button, instead it takes you on a journey, adding credit card details, selecting shipping, adding address, confirming the order.....
see this video Finding your service boundaries: a practical guide
We are using an event store that stores a single aggregate - a user's order (imagine an Amazon order than can be updated at any moment by both a client or someone in the e-commerce company before it actually gets dispatched).
For the first time we're going to allow our company's employees to see the order's history, as until now they could only see its current state.
We are now realizing that the events that form up the aggregate root don't really show the intent or what the user actually did. They only serve to build the current state of the order when applied sequencially to an empty order. The question is: should they?
Imagine a user that initially had one copy of book X and then removed it and added 2 again. Should we consider this as an event "User added 1 book" or events "User removed 1 book" + "User added 2 books" (we seem to have followed this approach)?
In some cases we have one initial event that then is followed by other events. I, developer, know for sure that all these events were triggered by a single command, but it seems incredibly brittle for me to make that kind of assumptions when generating on the fly this "order history" functionality for the user to see. But if I don't treat them, at least in the order history feature as a single action, it will seem like there were lots of order amendments when in fact there was just one, big one.
Should I have "macro" events that contain "micro events" inside? Should I just attach the command's id to the event so I can then easily inferr what event happened at the same and which ones not (an alternative would be relying on timestamps.. but that's disgusting).
What's the standard approch to deal with this kind of situations? I would like to be able to look at any time to the aggregate's history and generate this report (I don't want to build the report incrementally every time the order is updated).
Thanks
Command names should ideally be descriptive of intent. Which should mean it's possible to create event names which make the original intent clear. As a rule of thumb, the events in the event stream should be understandable to the relevant members of the business. It's a good rule of thumb. It should contain stuff like 'cartUpdated' etc.
Given the above, I would have expected that the showing the event stream should be fine. But I totally get why it may not be ideal in some circumstances. I.e. it may be too detailed. In which case maybe create a 'summeriser' read model fed the events.
It is common to include the command’s ID in the resulting events’ metadata, along with an optional correlation ID (useful for long running processes). This then makes it easier to build the order history projection. Alternatively, you could just use the event time stamps to correlate batches in whatever way you want (perhaps you might only want one entry even for multiple commands, if they happened in a short window).
Events (past tense) do not always capture human - or system - user intent. Commands (imperative mood) do. As all command data cannot always be easily retraced from the events it generated, keeping a structured log of commands looks like a good option here.
I would like to implement CQRS and ES using Axon framework
I've got a pretty complex HTML form which represents recruitment process with six steps.
ES would be helpful to generate historical statistics for selected dates and track changes in form.
Admin can always perform several operations:
assign person responsible for each step
provide notes for each step
accept or reject candidate on every step
turn on/off SMS or email notifications
assign tags
Form update (difference only) is sent from UI application to backend.
Assuming I want to make changes only for servers side application, question is what should be a Command and what should be an Event, I consider three options:
Form patch is a Command which generates Form Update Event
Drawback of this solution is that each event handler needs to check if changes in form refers to this handler ex. if email about rejection should be sent
Form patch is a Command which generates several Events ex:. Interviewer Assigned, Notifications Turned Off, Rejected on technical interview
Drawback of this solution is that some events could be generated and other will not because of breaking constraints ex: Notifications Turned Off will succeed but Interviewer Assigned will fail due to assigning unauthorized user. Maybe I should check all constraints before commands generation ?
Form patch is converted to several Commands ex: Assign Interviewer, Turn Off Notifications and each command generates event ex: Interviewer Assigned, Notifications Turned Off
Drawback of this solution is that some commands can fail ex: Assign Interviewer can fail due to assigning unauthorized user. This will end up with inconsistent state because some events would be stored in repository, some will not. Maybe I should check all constraints before commands generation ?
The question I would call your attention to: are you creating an authority for the information you store, or are you just tracking information from the outside world?
Udi Dahan wrote Race Conditions Don't Exist; raising this interesting point
A microsecond difference in timing shouldn’t make a difference to core business behaviors.
If you have an unauthorized user in your system, is it really critical to the business that they be authorized before they are assigned responsibility for a particular step? Can the system really tell that the "fault" is that the responsibility was assigned to the wrong user, rather than that the user is wrongly not authorized?
Greg Young talks about exception reports in warehouse systems, noting that the responsibility of the model in that case is not to prevent data changes, but to report when a data change has produced an inconsistent state.
What's the cost to the business if you update the data anyway?
If the semantics of the message is that a Decision Has Been Made, or that Something In The Real World Has Changed, then your model shouldn't be trying to block that information from being recorded.
FormUpdated isn't a particularly satisfactory event, for the reason you mention; you have to do a bunch of extra work to cast it in domain specific terms. Given a choice, you'd prefer to do that once. It's reasonable to think in terms of translating events from domain agnostic forms to domain specific forms as you go along.
HttpRequestReceived ->
FormSubmitted ->
InterviewerAssigned
where the intermediate representations are short lived.
I can see one big drawback of the first option. One of the biggest advantage of CQRS/ES with Axon is scalability. We can add new features without worring about regression bugs. Adding new feature is the result of defining new commands, event and handlers for both of them. None of them should not iterfere with ones existing in our system.
FormUpdate as a command require adding extra logic in one of the handler. Adding new attribute to patch and in consequence to command will cause changes in current logic. Scalability is no longer advantage in that case.
VoiceOfUnreason is giving a very good explanation what you should think about when starting with such a system, so definitely take a look at his answer.
The only thing I'd like to add, is that I'd suggest you take the third option.
With the examples you gave, the more generic commands/events don't tell that much about what's happening in your domain. The more granular events far better explain what exactly has happened, as the event message its name already points it out.
Pulling Axon Framework in to the loop, I can also add a couple of pointers.
From a command message perspective, it's safe to just take a route and not over think it to much. The framework quite easily allows you to adjust the command structure later on. In Axon Framework trainings it is typically suggested to let a command message take the form of a specific action you're performing. So 'assigning a person to a step would typically be a AssignPersonToStepCommand, as that is the exact action you'd like the system to perform.
From events it's typically a bit nastier to decide later on that you want fine grained or generic events. This follows from doing Event Sourcing. Since the events are your source of truth, you'll thus be required to deal with all forms of events you've got in your system.
Due to this I'd argue that the weight of your decision should lie with how fine grained your events become. To loop back to your question: in the example you give, I'd say option 3 would fit best.
I have a couple of questions regarding if the following process can be considered use-cases.
Website where establishments can post events.
User can "follow" establishment, "attend" event.
etc...
On my index page, i have the following sections:
Recommended Events, Events recently created, Events from establishments that the user "follows", Top 10 establishments, Recent comments, Popular events and so on.. (all which i am pulling from a database)
Would the index page be considered a use case? And would all the sections i named be individual use-cases? Considering i already have a Consult establishment, and consult event use-case, would all the section fall into this category?
I have on the establishment page a button where the user can click and the user will follow the establishment and receive notifications. All the button does once clicked, is adds the user to a table (User_Preferences), pretty much like a "like" button or a follow button.
Would this be considered a use-case(Add to Preferences use case)?
When i visit an establishment page, i am pulling data from many tables, such as: beverages, music, artists_attended, food, etc.
On the use-case Consult establishment, would i need to include every individual information? consult_beverage, consults_music,consult_artist, consult food all included to consult establishment? or are they considered already in consult establishment?
Finally, would every page i create, Index,Establishment,Events,UserProfile, etc... would they all be considered a use-case? Consult Establishment, Consult Events, Manage Profile
thank you, any tips or help would be appreciated, i understand the concept of use cases, but i sometimes tend to overthink some uses cases. thanks for the help.
The index page itself is not a use case. A use case represents some interaction between an actor and the system, but the page and its sections are part of the system design. If you were to replace the web browser with a custom-written GUI application, the use cases should be essentially the same.
In this case, you seem to be creating the use cases after you've designed the system, which is probably what's tripping you up -- use cases are usually determined before the system is designed.
"Add to Preferences" seems like a good use case. How much work goes into realizing the use case is normally of little importance; what matters is whether the interaction provides some value to the actor. The complete set of use cases describes what the user can do with the system, not how many engineering hours were spent constructing it.
You should not incorporate details on the stored data in your use cases. If you find yourself doing that you need to take a step back and try to think a little more abstractly. What does the use case do for the actor, what does the actor want? To get information about an establishment? Then that's enough, you don't need to specify the exact information stored in the system. The important thing is that the actor wants the information and that the system provides it.
Use cases are part of system analysis, not system design. As such, there is no problem with having the same design component (page) realize several use cases. So you could for instance have use cases for "see recommended events", "see coming events for 'followed' establishments", "see coming 'attended' events", all being realized in different sections on the same page.
A page is never any use case. A use case is what brings value to an actor. Simple as that. If you can name the value then you got the name of the use case. If you can't name the value then you don't have a use case.
E.g. your 1st events page: I would assume that the use case behind it will be Find Event. Similarly you have to think of the other cases. On the opposite Login to Site is not a use case because it does not bring any value to the actor.
One of the basic tenets of CQRS, as I understand it, is that commands should be behaviour-centric, and have a value in the business or the UL, and not data-centric, ie., CRUD. Instead of focusing on updating a customer, we have commands like CustomerHasMoved. What if you have CRUD screens which are there to correct certain data. For example, we need to change the name of a customer which is misspelled. This doesn't really have much value in the business. Should this just be under the umbrella of an UpdateCustomer command?
I just want to put a comment on this quickly as it popped up.
It is important to note that some objects are actually CRUD and thats ok. I may not really care why a name is changing in my domain where I ship products to people and only need that data to print mailing labels. The trick is in making behavior the default and THEN reverting to a CRUD interface once you are sure you really don't care about the reasons as opposed to vice versa.
Greg
Actually, there could be various reasons to update the name of a customer. As you were saying, it could be misspelled or... you could get married and change your name to your husband's.
If you had only an UpdateCustomer command, you would loose the original intent and you would not be able to have different behaviours for each of them. If the name was misselled it could be as simple as updating the database, whereas if your customer got married you might need to notify the marketing departement so tthat they can offer a discount.
In the case that your entity is purely CRUD, that is there is no intent that you can associate with modifying the properties, then it's OK to have an UpdateEntityCommand. You can then transition slowly to something more task based
CustomerHasMoved is the event that is fired after you have updated the customers location. This event updates the read databases/cache databases. The command from the gui should be MoveCustomer or something like that. I think I would put the update of the customer name in a command like UpdateCustomer.