2

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.

  1. 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?

  2. Is there any relationship between domain-events and domain-services?

Leonz
  • 141
  • 12
  • Sounds like Eric Evans and DDD never heard of ACID or transaction managers. – duffymo Mar 05 '16 at 13:46
  • @duffymo They did, but decided they wanted a simpler and more maintainable codebase. Also DDD is higher level than ACID or transaction managers which are implementation details. One is about identifying an abstraction, the other is how we implement _parts_ of that abstraction. – MikeSW Mar 05 '16 at 16:24
  • Sometimes you've gotta be ACID. I demand it from my bank. – duffymo Mar 05 '16 at 16:30
  • 2
    @duffymo ACID is called an aggregate in DDD. – MikeSW Mar 05 '16 at 16:31
  • I'll bet more people would know what ACID is than DDD. Eric Evans wrote a lovely book - then larded it with so much tripe that it was diminished. I sat with him at lunch at a conference and told him he needed an editor. He agreed. – duffymo Mar 05 '16 at 16:32
  • @duffymo It's not a secret that his book is quite old and some parts are obsolete. However, the tactical patterns like aggregates or the concept of persistence ignorance are not. – MikeSW Mar 05 '16 at 16:38
  • Some of his ideas are good. I don't think he's made much of an impact on the average developer. Everybody knows "Design Patterns"; few know DDD. Doesn't impact daily coding practice. – duffymo Mar 05 '16 at 16:39
  • @duffymo well, this is not because the book or DDD itself are so cumbersome. It is because average dev is not very interested looking outside of her comfort zone, speaking with customers, trying to understand their business domain. DDD is effectively establishing ubiquitous language within bounded context and very few devs are really interested in this. – Alexey Zimarev Mar 06 '16 at 12:57
  • @Alexey Zimarev, I think the book does bear part of the blame. "Design Patterns" did it right; DDD did not. I'll bet even those average developers will know what you mean when you say "Singleton" or "Factory", but they will be clueless when you say "aggregate". They'll know ACID, too. – duffymo Mar 06 '16 at 12:58
  • 5
    Concerning your bank example, I had a good laugh. They surely do ACID inside, but when you send money to another bank, they eventually disappear from your account and it takes from minutes to days before the amount actually appears on the receiver account. Do you have any idea where you money is? Is it transactional as a whole? No, it relies on inter-banking system to complete the transfer, but the whole operation is not ACID. Your internet bank UI is very much eventually consistent too, it is obvious. – Alexey Zimarev Mar 06 '16 at 12:59
  • @duffymo Yes, they might be clueless, however, they might be clueless on many other things, I don't see a correlation here. Dev are interested in things that improve their code and DDD is not about code. Another thing in DDD is the impedance mismatch that was hard to deal with with all those ORMs, RDBMSes and overall obsession with ACID. – Alexey Zimarev Mar 06 '16 at 13:04
  • I'm not interested in discussing. All opinion based. Here's what I do know: DDD hasn't made much progress diffusing into software development common practice. It's not because everybody on earth is stupid. It wasn't accepted. You sound bitter about it. Why is that? – duffymo Mar 06 '16 at 13:07

3 Answers3

8

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.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • If i understand correctly, if the business process is to notify seller when out of stock, `NotEnoughInventory` event will be most likely doing this notification job. If the business process was to change, before submitting order, the system will ensure there is available stock, does this means that I should have a domain service to check the inventory and allow submitting order if stock available? – Leonz Mar 06 '16 at 13:27
  • Another question is, why DTC is not related here? Since each process(including events) is its own transaction, if a process and event happens to occur concurrently, there will be 2 transactions in a same time, which I believe that web app (non-DTC enabled) only allows 1 transaction at a time (distributed transaction happens here) – Leonz Mar 06 '16 at 13:35
  • @Leonz DTC is a very specific implementation detail, one used for distributed transactions which themselves are a solution for a problem that shouldn't have existed in the first place. If you're doing DDD you have to forget the CRUD/ACID mindset. As I've said before, the aggregate is the DDD's unit of work i.e the transaction. Thing is, you're trying to use way too many things that you don't understand yet. You need to grok that DDD has nothing to do with implementation and you need to understand a message driven architecture + CQRS. Take it slowly, DDD,CQRS are not a recipes but paradigms. – MikeSW Mar 06 '16 at 19:10
2

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:

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
1

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

guillaume31
  • 13,738
  • 1
  • 32
  • 51