Okay, I appreciate the title sounds odd. An event should always be for something that has happened, e.g. OrderCreated, ParcelShipped, etc.
However, I wonder if anyone has any thoughts on the following problem.
Consider an HR application which models people and their jobs. For simplicity's sake, a person can have a bunch of jobs and they can be ended at a date. The person has an EndJob operation which takes an endDate.
If the endDate is in the future, what would the domain event be?
JobEndedEvent (this is not true)
JobEndDateAddedEvent (this is quite technical)
Consumers in other bounded contexts will be interested to know that the Job will be ending, but may also wish to be informed at the point the job ends as well. I feel that the latter should be the consumer's responsibility, rather than the source's.
Any thoughts would be welcomed... Thanks.
Well, from a Domain perspective, you're probably talking about JobTerminationScheduledEvent because from the language point of view, you're notifying other contexts about a scheduling of a job's ending.
It's not the actual thing, schedulings can change and you will leave up to the other contexts how will they handle such an information. A given context might consider the scheduling to be enough information to consider the job will end by the given date.
Another context, as being notifying that such an event happened they might want to double-check when the date comes to make sure no changes happened before taking further action.
In the end, your context is actually expressing what happened which is: nothing concrete. You have a scheduled date defined for this action to happen, but it didn't happen yet.
If the endDate is in the future, what would the domain event be?
JobCompletionScheduled?
We made the decision now, but it's effective date is in the future. That's a perfectly normal thing to do in a line of business, and the decision itself is useful business intelligence to capture.
Dig around with your domain experts, and listen closely - there may already be vocabulary in your domain that describes this case.
Although there is an event that happens when you have specified that someones job is 'going to' end lets call it "jobEndIntentionEvent", there is also an implicit event that happens when the persons job actually ends - "jobEndEvent".
Now, the source bounded context possibly doesn't need to raise this "jobEndEvent" to act on it itself. You may have multiple bounded contexts that are only really interested in knowing about this event though. So should it raise it at all? Or do the multiple other bounded contexts all have to play the cards they're dealt - i.e. listen for the "jobEndIntentionEvent" and implement code that fires when the event they would have liked to have heard ("jobEndEvent") would have been received?
Or should the origin bounded context be nice and fire this 'integration event' for everyone.
Or alternatively a nicer solution would be we have a scheduling bounded context that is a subscriber to "jobEndIntentionEvents" and similar ones to that, and it knows to convert them into the REAL events that people actually care about - "jobEndEvents".
Related
I am applying Domain driven design in my project and I am running into a scenario where a user action translates into a command in one of my bounded contexts and thus produces an event. However I see that none of my other bounded contexts would care about consuming this event. Essentially all this command is doing is saving/ updating state in my bounded context.
My questions are :
does a command have to produce an event ?
If so, does it matter that nobody is listening ?
does a command have to produce an event ?
Absolutely not.
If you were using event sourcing as your persistence strategy, then all of your changes of state would be "events". But there's no particular reason that you must expose the event elsewhere.
Hyrum's Law is one reason that you might prefer not to broadcast an event
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.
Don't guess what information should be included in the event until you have enough data at hand to make a good guess.
does it matter that nobody is listening ?
In an ideal world, not really -- in practice, costs may well figure into the decision.
It is not a necessity for a command to produce an event, though it is preferable.
One of the most significant benefits of events is the ability to generate the state of the system as on a particular date/time from scratch. If you were to religiously bubble-up events for all changes in the system, you will be able to apply events sequentially and bring the system to the state of your requirement.
IMHO, it does not matter that nobody is listening at that point in time. I am assuming that you are persisting your event into an event sink/log as part of your application. Doing so has two benefits:
a. If you were to discover a future requirement which would benefit from an event log, you are already a step ahead.
b. Even if nobody ever consumes the event, as mentioned in the first response, being able to generate a state of the system as on a particular date/time is a cool ability to have.
The pattern of persisting events and deriving a system state has its roots in Event Sourcing. You would want to take a deeper look at it to see its benefits.
does a command have to produce an event ?
No, its not a requirement, a command can just modify a state of an entity without dispatching an event. As said in others responses you should require every state change to produce a domain event if you use Event Sourcing.
If so, does it matter that nobody is listening ?
Yes and No.
Yes because there is no good or bad model, only useful model, if no one is listening then your modeling is not really useful to anyone.
No because domain event are called invariant, they reflect business event and change only when the business requirement change, and so they are part of your API (see the concept of published language).
I am new to DDD. Now I was looking at the domain event. I am not sure if I understand this domain event correctly, but I am just thinking what will happen if domain event published failed?
I have a case here. When a buyer order something from my website, firstly we will create a object, Order with line of items. The domain event, OrderWasMade, will be published to deduct the stock in Inventory. So here is the case, what if when the event was handled, the item quantity will be deducted, but what if when the system try to deduct the stock, it found out that there is no stock remaining for the item (amount = 0). So, the item amount can't be deducted but the order had already being committed.
Will this kind of scenario happen?
Sorry to have squeeze in 2 other questions here.
It seems like each event will be in its own transaction scope, which means the system requires to open multiple connection to database at once. So if I am using IIS Server, I must enable DTC, am I correct?
Is there any relationship between domain-events and domain-services?
A domain event never fails because it's a notification of things that happened (note the past tense). But the operation which will generate that event might fail and the event won't be generated.
The scenario you told us shows that you're not really doing DDD, you're doing CRUD using DDD words. Yes, I know you're new to it, don't worry, everybody misunderstood DDD until they got it (but it might take some time and plenty of practice).
DDD is about identifying the domain model abstraction, which is not code. Code is when you're implementing that abstraction. It's very obvious you haven't done the proper modelling, because the domain expert should tell you what happens if products are out of stock.
Next, there's no db/acid transactions at this level. Those are an implementation detail. The way DDD works is identifying where the business needs things to be consistent together and that's called an aggregate.
The order was submitted and this where that use case stops. When you publish the OrderWasMadeevent, another use case (deducting the inventory or whatever) is triggered. This is a different business scenario related but not part of "submit order". If there isn't enough stock then another event is published NotEnoughInventory and another use case will be triggered. We follow the business here and we identify each step that the business does in order to fulfill the order.
The art of DDD consists in understanding and identifying granular business functionality, the involved aggregates, business behaviour which makes decisions etc and this has nothing to do the database or transactions.
In DDD the aggregate is the only place where a unit of work needs to be used.
To answer your questions:
It seems like each event will be in its own transaction scope, which means the system requires to open multiple connection to database at once. So if I am using IIS Server, I must enable DTC, am I correct?
No, transactions,events and distributed transactions are different things. IIS is a web server, I think you want to say SqlServer. You're always opening multiple connections to the db in a web app, DTC has nothing to do with it. Actually, the question tells me that you need to read a lot more about DDD and not just Evans' book. To be honest, from a DDD pov it doesn't make much sense what you're asking.. You know one of principles of DD: the db (as in persistence details) doesn't exist.
Is there any relationship between domain-events and domain-services
They're both part of the domain but they have different roles:
Domain events tell the world that something changed in the domain
Domain services encapsulate domain behaviour which doesn't have its own persisted state (like Calculate Tax)
Usually an application service (which acts as a host for a business use case) will use a domain service to verify constraints or to gather data required to change an aggregate which in turn will generate one or more events. Aggregates are the ones persisted and always, an aggregate is persisted in an atomic manner i.e db transaction / unit of work.
what will happen if domain event published failed?
MikeSW already described this - publishing the event (which is to say, making it part of the history) is a separate concern from consuming the event.
what if when the system try to deduct the stock, it found out that there is no stock remaining for the item (amount = 0). So, the item amount can't be deducted but the order had already being committed.
Will this kind of scenario happen?
So the DDD answer is: ask your domain experts!
If you sit down with your domain experts, and explore the ubiquitous language, you are likely to discover that this is a well understood exception to the happy path for ordering, with an understood mitigation ("we mark the status of the order as pending, and we check to see if we've already ordered more inventory from the supplier..."). This is basically a requirements discovery exercise.
And when you understand these requirements, you go do it.
Go do it typically means a "saga" (a somewhat misleading and overloaded use of the term); a business process/workflow/state machine implementation that keeps track of what is going on.
Using your example: OrderWasMade triggers an OrderFulfillment process, which tracks the "state" of the order. There might be an "AwaitingInventory" state where OrderFulfillment parks until the next delivery from the supplier, for example.
Recommended reading:
http://udidahan.com/2010/08/31/race-conditions-dont-exist/
http://udidahan.com/2009/04/20/saga-persistence-and-event-driven-architectures/
http://joshkodroff.com/blog/2015/08/21/an-elegant-abandoned-cart-email-using-nservicebus/
If you need the stock to be immediately consistent at all times, a common way of handling this in event sourced systems (can also in non-event based systems, this is orthogonal really) is to rely on optimistic locking at the event store level.
Events basically have a revision number that they expect the stream of events to be at to take effect. Once the event hits the persistent store, its revision number is checked against the real stream number and if they don't match, a conflict exception is raised and the transaction is aborted.
Now as #MikeSW pointed out, depending on your business requirements, stock checking can be an out-of-band process that handles the problem in an eventually consistent way. Eventually can range from milliseconds if another part of the process takes over immediately, to hours if an email is sent with human action needing to be taken.
In other words, if your domain requires it, you can choose to trade this sequence of events
(OrderAbortedOutOfStock)
for
(OrderMade, <-- Some amount of time --> OrderAbortedOutOfStock)
which amounts to the same aggregate state in the end
I have made an activity diagram for gym management, but i am facing a problem how will i connect Receptionist with Admin, According to requirement activity between Admin and receptionist takes place only through notification and i have made a signal and receptor for notification. Please also check if every notation is right and suggest me for modification?
I am sorry for not answering at once - several times had I looked at your picture, and, frightened, retreated.
You really tried and did something. It is good. But... You have put Use Cases directly into the activity diagram. So as is, it has no sense.
Let's take a customer. He has his swimlane. Good. According to your diagram, the customer comes and decides, what to do - immediately leave, join or inquiry. It doesn't matter, if he joins or inquiries, the result is common (why had he been choosing?) - he gives some unknown message to the receptionist. He never gets something back, never he does smth. else, he remains here and becomes immortal, because even his death won't finish his state of being here, waiting for some reaction from anybody. Poor man!
I don't think it is necessary to analyze here other swimlanes - they are even worse.
Better divide your work into levels.
Use Case diag. Define, who are actors (you have defined them well) and what are their interaction with system and its parts.
As the next stage you can make a deployment diagram - where are components of the system and maybe, actors, located and what messages they send to each other, defined.
And only now you can start with Activity diagram.
Also notice, that you'll have to return and correct the elders diagrams when you'll come to a dead end or some radical changes in the younger ones. You'll meet with both, be sure.
And when you have some problem with some diagram, come here, write down what you had BEFORE it (you didn't), what you have done on this stage (you did it) and we'll be able to help.
What are the best practices for using use cases to model system behavior that is executed periodically based on a schedule (rather than executed as a direct result of an explicit user interaction)?
If 'time' is modeled as an actor, what are accepted approaches to describing how time is used to trigger the use case (e.g. whether the period is configurable, valid ranges, etc.)?
Is the scheduling part of your system or external to it?
If the schedule is external, then I treat it as the actor. We then don't see time.
If scheduling is the system's responsibility, then I think it's may be helpful to think of time as an actor "tolling the bell", or in other words providing input. Enumerating time's responsibilities helps in the design of the schedule. However there will also be other actors who actually set the schedule. Separate time, from schedule.
It might be better to consider the actor who caused a particular task to be scheduled as still being the actor when the task actually starts:
Stock Clerk submits list of parts picked
System processes list of parts picked to update inventory
and add a note indicating that the latter occurs overnight.
Now that I write this, I don't think time is an issue in the use case. At this level, what's important is what happens and which actors are involved. When it happens is no more important at this stage than how.
Time is never a primary actor, after all, time doesn't receive something of value from the system when a use case is instantiated?
I think you are confusing your implementation decision with the business requirement that your implementation decision was chosen realize.
If you could provide an high-level description of what is being done periodically and why, I could elaborate.
DDD teaches us to build our classes like their real-world prototypes.
So instead of using setters
job = new Job
job.person = person
job.since = time.Now()
job.title = title
we define well-named methods in our aggregation root
job = person.promote(title, /** since=time.Now() **/)
Now the tricky part
Assume we have an UI for an HR where he/she enters a new title via the HTML form and makes a typo like "prgrammer" (Of course in real application there'd be a select list, but here we have a text input), or selects a wrong date (like default today)
Now we have a problem. There are no typos in real world. Our John Doe is definitely a "programmer" and never a "prgrammer"
How do we fix this typo in our domain model?
Our Person has just promote, demote, fire, etc. methods, which reflect the HR domain model.
We could cheat a little bit and change the Job record directly, but now we have a Job.setTitle method, that doesn't reflect our domain model and also, setters are evil, you know.
That may look a little "academic", but that really bugs me when I try to build a good domain model for a complex application
Another side of DDD is invariants - "always valid" entity. And when you try to break this invariant (some rule) you must stop execution and say "loudly" adout this (throw exception). So, you need to have a list of valid titles and when you try to change title (does not matter how) to invalid state, you must throw some usefull exception.
To "fix" typo situations you must separate operations in your domain promote is one operation (it may check something, sent contratulation email :) and so on). And edit operation - just to edit some properties. So, the differenece is in logic of operations. You can't call promote without some preconditions (for example, required experience of worker), but you can call edit and fix worker's name because of type.
And usually this operations are separated between different users: only HR's can promote but a worker can edit his name, if it's wrong.
This solution is very complicated for such example, but it's always with DDD.
The main concept - separate operations. Each one with their own conditions, permissions, rules.
A question about invariants (rules).
If a client is purely entering data, then the underlying domain in this (bounded) context is not very deep. In these cases, it's fine to use a CRUD style application and allow titles to be changed (setTitle()).
Just make sure dependent BCs (e.g., billing, vacation planning, ...) where no such thing as "invalid data" exists, can react to changes in your CRUD context appropriately.
The application should enforce input correctness before it reaches the domain layer, no garbage input. If that means using a dropdown for the job titles then so be it. You can validate the title against existing titles.
In my company of 18 thousand employees, typo happens all the time. You are going to have to be pragmatic about this and accept that there will be setters in your code (one way or another)
Pragmatic thinking is very much at the core of the domain driven design, and is what keep things simple.
"Purity is good in theory, but in practice it can be very difficult to achieve, and sometimes you must choose the pragmatic approach" - Patterns, Principles, and Practices of Domain-Driven Design (2015)
"There are no typos in real world", I get what you mean, but that's not true, there are human mistakes in real world scenarios and they should be accounted for in your domain if they are frequent.
If data entry errors aren't frequent it may not be worth the extra modeling efforts and those could perhaps just get fixed directly in the DB. It also depends if the business wishes to learn something about those mistakes or not.
However, if data entry errors are frequent, it might be an indicator that the system is perhaps not offering enough guidance and the business may wish to learn more about those errors in order to make processes more efficient and less error-prone.
You may wish to implement an operation such as job.correctTitle(...), perhaps in a BC dedicated to data corrections? Also, it's probably very rare that each and every piece of information will be erroneous so corrective operations can be segregated. That means you probably do not need a job.correctAllInformation(...) kind of operation.
This whole scenario is very fictive since job titles would usually be managed in a separate BC from where they are used and they would probably get picked from a list, therefore typos would be less frequent, but you will always have to deal with data entry errors. Choosing the appropriate solution is not always easy and will vary from case to case, but try to stay pragmatic and not strive for the perfect model in every sphere of your domain.