So, having looked at what a DDD system looks like structurally, the next question is how do we build these things? How do we design them?

The best technique that I know for doing this is something called event storming, which was developed just a few years ago by Alberto Brandolini.

Definition:

Now, event storming a technique that is used really for two things, but as we just saw in domain driven design, those two things are the same thing.

In other words, you can use it to both analyze the domain, analyze the business, and also to develop the code that is going to be modeling the business because by modeling the business you are also coming up with a design for your code.

So, event storming then is a collaborative technique that you do in conjunction with business people in order to come up with a design for a system that models the structure and flow of activities within the business itself.

It’s important to point out that stories are also important here also. Is one of the things that gets people down a wrong track when they do event storming is they try and do too much at once. They try and model an entire bookstore, for example, in one session and that way lies madness is that what you want to do is focus on a specific story and then model that part of the system that you need to model in order to implement that story.

Then, once that’s more or less done, and in fact if you’re working in an agile way, you’d implement at that point, but once that’s done, then it makes sense to go back and modify your previous work in order to incorporate additional stories into it.

So you sit down with a story and a bunch of business people and a white board and a bunch of sticky notes and you start modeling.

Now there are a couple terms that we have to discuss before we even start though.

  • First one being an event.

So an event is something that happens at the business level that your customers, or end users, or domain experts care about. It’s a business level thing. Remember what we’re doing with domain level, domain driven design, is implementing the domain.

So, an order having been submitted is an event, a payment having been received, a nightly reconciliation report completed.

Now that’s an interesting one because it’s not a human actor that triggers it. Is that orders being submitted and payments being received is a human actor, but here it’s some kind of automated process that’s triggering it. We don’t really care who’s triggering the event. What we care about is the event itself. Also notice that the events are specified in past tense and that’s also important.

An event is something that has happened that will trigger something else to happen next. So putting the events in past tense is a good way to keep them straight, is a good way to organize the system linguistically.

How do you do Event Storming?

So, having looked at what a DDD system looks like structurally, the next question is how do we build these things? How do we design them? The best technique that I know for doing this is something called event storming, which was developed just a few years ago by Alberto Brandolini.

Now, event storming a technique that is used really for two things, but as we just saw in domain driven design, those two things are the same thing.

In other words, you can use it to both analyze the domain, analyze the business, and also to develop the code that is going to be modeling the business because by modeling the business you are also coming up with a design for your code.

So, event storming then is a collaborative technique that you do in conjunction with business people in order to come up with a design for a system that models the structure and flow of activities within the business itself.

It’s important to point out that stories are also important here also. Is one of the things that gets people down a wrong track when they do event storming is they try and do too much at once.

They try and model an entire bookstore, for example, in one session and that way lies madness is that what you want to do is focus on a specific story and then model that part of the system that you need to model in order to implement that story.

Then, once that’s more or less done, and in fact if you’re working in an agile way, you’d implement at that point, but once that’s done, then it makes sense to go back and modify your previous work in order to incorporate additional stories into it.

So you sit down with a story and a bunch of business people and a white board and a bunch of sticky notes and you start modeling. Now there are a couple terms that we have to discuss before we even start though. First one being an event.

So an event is something that happens at the business level that your customers, or end users, or domain experts care about. It’s a business level thing. Remember what we’re doing with domain level, domain driven design, is implementing the domain.

So, an order having been submitted is an event, a payment having been received, a nightly reconciliation report completed. Now that’s an interesting one because it’s not a human actor that triggers it. Is that orders being submitted and payments being received is a human actor, but here it’s some kind of automated process that’s triggering it. We don’t really care who’s triggering the event. What we care about is the event itself.

Also notice that the events are specified in past tense and that’s also important. An event is something that has happened that will trigger something else to happen next. So putting the events in past tense is a good way to keep them straight, is a good way to organize the system linguistically.

 Let’s understand is the color codes:

Demo: Events:

Use micro.com

Now let’s move on and look at how this process actually works.

What Miro is is a whiteboard system. Basic idea is that you have a palette here to work on.

The first thing that one does when you do event storming is you put the events onto the board.

Events are orange.

So I’m going to create an orange event here, put it up on the board.

  1. And this is going to be the very first thing that we’re going to do when somebody pushes the button on the shopping cart. So let’s say that the cart has been purchased.
  • So once the cart has been purchased, we then have to process the credit card.

So that’s going to bring up another event here. And this will be payment accepted. By the same token, we have to process the order.

  • So there is a third event here which is going to be the order accepted. In other words, the distinction I’m trying to make here is the difference between the payment process and the shipping process.
  • Next order of business is we have to think about what happens as part of the payment process. Well, certainly once the payment has been accepted, we can’t process the order until we know that we’ve been paid. So there’s at least one more event here which is going to be that the shipment is authorized.
  • Looking at the other flow. I have to learn how to spell. Once the order has been accepted, we then have to start doing things like generating shipping labels and creating lists of things to pick. So let’s get those guys in. So a shipping label has been created.
  • And we created a pick list, as this is the list of things that we’re going to pull off the shelves inside of our warehouse.

So again, these are all events that are interesting at the business level.

Now there are a couple of things here to point out is

  • first of all, I’m going in terms of time, time moves left to right. So what that means is that when things are stacked up on top of each other vertically, that means that they are happening at the same time or at least they can happen at the same time. So the payment has been accepted, the shipment has been authorized, that authorization process can be going on while we are creating shipping labels and creating pick lists because nothing bad will happen if we do these activities up here before the payment has been authorized.
  • So when this is all finished, of course, the last thing that we might want to add is that the package is now ready to ship.

But we can’t ship yet because the payment’s not finished.

So that’s our start. I’ve started with a few events.

This is not going to be right most likely, as generally when you’re doing this in the real world, events occur to you as you’re working, the more events you add, the more events occur to you.

We haven’t put in the activities yet, I’ll start doing that in a moment. But as we put in activities, you will find that new events occur just as a side effect of the thinking that goes around doing the activities.

So that’s the first step though. 

 Demo: Activities flow

So, now that we have some events on the board, we can start thinking about what to do when the events occur.

When the cart is purchased and then the order is accepted, there’s things that have to happen in-between that.

So let’s start adding some commands, some activities. (Sticky color Blue)

  • So once the card has been purchased, we have to issue an invoice, that could be something as simple as just displaying it on the screen, but remember, we’re staying in the domain here. So as we’re working, I’m working in a, what’s called a metaphor, that being a manual process where there’s actually real people doing the actual work in the physical world. Of course we’re not going to be doing it that way when we implement but the way we think about this is that we’re moving the physical world into the computer. The activities that occur in the physical world will also be happening inside the computer as we’re working. So I issue an invoice, and the other thing I’m going to need to do obviously is request a payment because we can’t accept a payment until we’ve requested it. So let’s add a request payment event.

Now again, notice that these are stacked vertically which means that they can happen at the same time.

  • The next order of business is we now have to actually process the payment and I’m not sure what the best way to do that is.

So the payment processing is going to be an external entity (Pink). I know that as a fact because I’ve done this kind of work before, and you second source your payment to a payment process or service of one sort or another. So we need an external entity here that’s going to be doing the work.

And that would be our payment processor. The request payment then is going to delegate work to our payment processor so let’s just draw an arrow in order to indicate that that’s happening here.

Note:

And I’m not sure exactly what’s going to go on here and I don’t really want to stop the flow of my work so I’m going to leave myself a note just to remind myself that there’s more to do here than I’m thinking of. How does this happen. So red, remember, is for all of the notes, all these things that have to be filled in later in order to be able to complete the system.

  • After the payment has been processed, then clearly we’re going to have to accept it.

So that’s going to go up here to the payment accepted. And then we can move forward.

Now, moving to the right then, what do we do after the payment is accepted?

Once the payment is accepted, then I need to send a receipt and I need to authorize the shipment.

So now we can actually start thinking about actually doing the shipping. Actually, let’s flip this over because I know that authorized shipment is going to be impacting the flow up here so if I put it on the top, it’s going to make the diagram read a little bit more easily.

Now once I’ve sent the receipt to the customers, there’s really not much else to do in this particular flow. So the flow of activities effectively stops here is that will continue this flow but up to this point, we have what amounted to two parallel flows. There’s no official notation for that but what I do is I just use a big X just to indicate, all right, this flow is finished.

 Demo: Activities flow2 (authorized shipment flow)

Now let’s look at the second flow at the authorized shipment flow. Once we’ve authorized the shipment, of course the next event is going to be that the shipment has been authorized.

There’s some business rules involved though is that the shipment can’t be authorized. Or rather the shipment can’t be made until we’ve received payment.

So I’d like to capture that business rule on the diagram and I’m going to do that using a purple note, a process note.

I cannot ship unless payment has been processed.

So that’s a business rule. It has to do with shipment authorized. So I’ll attach it here to the shipment authorized step.

Once the shipment has been authorized, then I can create a shipping label.

So let’s do that next. Now the shipper is clearly going to be an external entity also. So we need another one of those external guys. Pink in other words. Something that’s external to the system. So this is our shipping agent, whoever that is, UPS or somebody who’s in charge of shipping.

So once the label has been created, the next thing that we’re going to do is flow down to our shipping agent.

So, now we are done with the second flow.

 Demo: Activities flow3

So before we can do anything else, we’ve got to go look at how was that first flow interact with the warehousing flow that I’ve been putting aside for the moment. So, the order has been accepted, there are activities that have to happen after the order has been accepted, so let’s get some of those in place.

  • First of all I have to initiate the shipping process.

And then I’m going to have to create my pick list, in order for there to be a pick list created, I have to create the pick list. After I initiate the shipping process that will cause the shipping label to be created and the pick list here is created as part of creating the pick list, obviously.

  • Once the label has been created, we then need to register that fact with our system so that if something comes up and we have to get into customer service we can deal with that.

So let’s go over here and add, shipping info to customer account.

  • By the same token, once the pick list has been created, we then have to actually put stuff in a box.

So let’s assemble, the package. So the package is not ready to ship until both of things happen, so I’m going to overlap the two events. So our flow here starts here, there’s one flow, there’s a second parallel flow down here and then they coalesce together with the package being ready and then finally once it’s ready to ship, we can then ship the package.

All right now let’s see if everything winds up properly here. Can’t ship unless the payment has been processed, so the shipment has been authorized here.

The payment has been accepted there, we authorized the payment there, so the payment has been accepted. All of this stuff can be going on parallel.

Now, once we ship the package there’s going to be some events there too which I hadn’t thought about, so let’s add those.

  • Once we ship the package we’re going to get some sort of tracking info.

And that will have come from the shipping agent. So let me indicate that with another arrow down here. And then once we ship the package of course, the package will have been shipped, so let’s put an event that indicates that, that’s certainly something that the business people are interested in.

So now what?

Once the order has been shipped there are a few things that has to happen.

  • First of all we want to make sure that it arrives, ’cause it seems to be there’s another event here.

We’ve received a delivery notification of some sort from our shipper. Now this is kind of an interesting one, when we start putting activities in here because there really isn’t any activity that we can do because it’s all external. So, there’s no official way to indicate that, but what I do is I’m going to change the color of this note, to the external color, to, pink, to indicate that this is an external event.

And then instead of putting text on it, what I’m going to do is draw on it.

So the order has been shipped, I wait for some amount of time and then eventually a delivery notification is been received and again this is an external event that is triggering that, it’s the shipping service that’s triggering that.

The tracking info has been received, now there’s something that we can do at that point, which is to notify the customer.

That we’ve shipped. And then we have another event that happens after that. It’s matched to that if you will, which is that the customer has been notified.

And then finally we can mark the order as complete.

So that is pretty much the complete flow here.

It’s not everything, I’m sure. In other words as we work on this further, things will occur to me that didn’t occur to me before. I should also say that this is very much a collaborative process, it’s very difficult to do this sitting by yourself at your desk.

So as I’m working on this, as we the team is working on this, everybody will be putting information in to this system if you will and we’ll tend not to forget things that way. Remember there are going to be business people in the room.

But that is basic flow of this system.

Demo: Entities (Who is doing it)

So now that we’ve got the flow under control, we have to start thinking about not what is happening, but how it’s happening. Who’s doing it, in other words?

So the next step in this process is to start adding aggregates or entities or some kind of label of who is receiving the event and then doing work with the event.

So the entities are all labeled with yellow stickies, so let’s go to yellow here.

  • The cart has been purchased, and we need to issue an invoice. Who’s going to do that?

So I’m going to just grab out of the hat a sales clerk, somebody whose job it is to issue invoices to customers.

If you were working in a store, this is the equivalent of a cash register receipt.

And the sales clerk is going to span these two events.

By the same token, if we’re requesting payment, we need a different kind of entity to do that. This kind of entity is going to be a cashier.

In other words, I’m separating concerns here. I’m separating the interacting with the customer concern with the actual processing of payments concern.

  • Now, next order of business. A payment is accepted, and we need to authorize a shipment.

Well, in a normal kind of factory business, there’s this odd word for a person who does that, which is a comptroller, somebody who’s in charge of the finances.

And the comptroller is in charge of authorizing shipment.

  • So the comptroller is in charge of authorizing the shipment.

And the payment has been accepted. We’re sending a receipt to the customer. I think that’s probably another sales clerk activity. Though, at this point it might make sense to not be a sales clerk anymore, but to be a shipping clerk.

So I have a comptroller. I have a sales clerk receiving the payment, accepted message, and doing this activity.

Then we need to authorize the shipment. We had the earlier can’t ship until the payment has been received rule in place, but the shipment has been authorized, and now we have to create a label. I think if we’re creating a label, we actually need a shipping clerk, which is different from the sales clerk.

So here I’m receiving the shipment authorized activity. I am performing the create shipping label, and the shipping clerk is going to do that work.

Now let’s go up to the other flow.

The order has been accepted right here. I’m creating a pick list. What I’ll do to handle that one is I’m going to generate create a dispatcher in the warehouse whose job is to create the pick list.

And we initiate the shipping process. That probably should be the shipping clerk that’s doing that, so let’s get our shipping clerk up here. The label has been created, and then we add information to the customer account.

Now, we don’t have anybody doing that, so let’s come up with a new entity or aggregate name for handling that situation. We’ll call this guy the, oh, I don’t know, the customer liaison.

And then we create a pick list. And we’re going to assemble the package. Now, here we have another conundrum, is that assembling the package is definitely outside the system, but it’s also being done by a human being. So there’s a special way we can annotate that. What I’ll do here is I’ll make a green sticky note which is going to indicate a sort of external UI kind of thing. And then I’m going to draw on that a little stick guy, which means an external actor. So the external actor is going to be in charge of handling the pick list created and then assembling the package. External actors can go in many places.

Here I’ve done it as the person responsible for binding these two things together, the event and the activity, but I could also just attach it to a single activity if I wanted to. Either way makes sense. You can improvise here. The package is ready. We’re then going to ship the package. I’ll allow the shipping clerk to do that one. The order has been shipped. And now we have to wait. So I’m going to create an internal sort of, not really in the domain, but an entity. I’ll call it a reconciler whose job is to just wait for things. Again, this is not official events terming, but I’d put these kinds of things in parentheses in order to indicate to me at least that this is not really a domain level thing. This is an implementation level thing. But I need some kind of entity dealing with the issue of waiting. Tracking information and then notifying the customer.

Let’s say we have some kind of customer agent that’s in charge of doing that. And then finally, we have the delivery notification and the customer has been notified events. Now, these have to be sent at the same time. And there’s going to be one thing that’s handling both of these events and generating the order complete message. That could be our agent, for example, handling that.

But the problem is how do I indicate that graphically?

So again, I’m going to have to improvise a little bit here. What I’ll do is I will first of all put a plus sign here, which to me means the delivery notification and the customer notified events are being issued at the same time. And then I’m going to put a circle around this whole thing to indicate that a single agent here is handling both of these events and generating the order complete event. So we now have entities or perhaps aggregates, as we don’t know yet.

Remember, an aggregate from the outside looks like an entity because you’re looking at the single portal object that talks to all of the entities on the other side of that portal that are doing the work. So these are either aggregates or they’re single entities. It really doesn’t matter.

That’s an implementation detail.

But we now have all of the who handled.

Demo: Context

So now that we’ve handled the who, let us do a little bit more work here and start thinking about context.

In other words, what context do things work in?

I’m just going to add context here on the same stickies that I’ve specified the entities on.

The sales clerk, I believe, should be working within the order processing context.

The cashier is working within, well, it would either be the store context.

I think in this case it’ll be the finance context, though. So let’s do a context entirely for finance.

The shipping clerk or the sales clerk really is going to be working in the context.

This is in the context of the store. The sales clerk is in the context of the store.

The comptroller is definitely within the finance context.

The shipping clerk, as compared to the sales clerk, definitely is working in the warehouse context. Moving up here, the shipping clerk, again, is working in terms of the warehouse context.

The dispatcher is working in the warehouse context. Lot of stuff happening inside this particular bounded context, but that makes sense since this is mostly a shipping story.

The customer liaison. That kind of bothers me, right? The customer liaison is a singleton. There’s only one of ’em. And the agent over here is really also talking to the customer, so I think customer liaison is probably, either agent or customer liaison is wrong.

I think I’ll call them all agents just (laughs) because it’s shorter.

So let’s call this guy an agent. And the agent is working really in the customer service context, not the warehousing context. So I’m going to cut and paste this guy and replace these. And replace this one. There’s my agent working in the customer service context.

The reconciler is an internal thing. I don’t know what it’s working in, maybe a shipping context here. Since it’s dealing with waiting for the shipping service to tell us that the order has actually been shipped.

And I think, is that everything? That’s everything.

So now we have the events. We have the activities to perform after the events are received. We know who is receiving the event and doing the activity.

Those are our yellow entity notes. And we know the bounded context within which these guys are working. I left that shipping clerk. It’s just for the sake of completeness.

Finish that up, he’s in the warehouse.

So this is really enough to code from, is that we have a basic design here that is mapping the domain, that is using domain level terminology in order to keep things straight. When things happen at the domain level, we know exactly where to go on our map in order to make things work.

And really we’re just ready to code.

We created shipping clerks.

We create agents.

We creates dispatchers.

Those could be microservices.

They could be classes if we’re working inside a big monolith instead.

We know what the events are, how they get sent.

We know who receives them.

We’re ready to code.

So this is the basic coding process.

There are a couple more steps, and I will do those next.

 Demo: Context Maps

So our event map is finished at this point, but there are a couple of other diagrams that might be useful, especially if the map gets really large, ’cause this one is not particularly large. It’s only handling one small story.

So there are two things that we’re trying to capture in these other diagrams.

  • The first one is the relationship between the larger bounded contexts, and
  • the second one is the individual endings and what sort of work do they have to do?

So let’s start with the first one, the notion of the context affinity map.

The basic idea here is that we want to capture all of our contexts. Now this is going to get kind of small because I need some room to work here, but let’s, let’s make this guy smaller and I’ll put it off to the side. And we’ll start looking at what the individual contexts are. So first of all, there, and I’m going to just do this by hand here.

So first of all, we have a warehouse context. And I have an order processing context. And I have a finance context. And I have a store context. Not sure where the best place to put that is. Let’s put it down here.

We can always move them around, if we need to. What am I missing? Customer service. And shipping, that’s warehouse related. So these are my larger bounded contexts.

In the microservice world, these might be microservices, they might not be.

In other words, the individual end user microservices, if you’re implementing inside a monolith, the individual and these basically are classes or objects.

However, in the case of an aggregate, the context might not have a one-to-one to the individual services. In fact, it probably won’t. There probably are multiple services working within the context.

So for example, if you look at side customer service over here. Customer service, there is the agent is working inside customer service. That’s pretty much the only thing working inside customer service.

However, the shipping clerk and the dispatcher both are working with inside the warehouse.

The shipping clerk and the dispatcher are both working in here. Inside customer service, the only thing that’s working is the agent.

The other thing I put in these diagrams as I’m working is the relationships between them. So here, we have the warehouse context is interacting with the customer service context. And it’s interacting with the shipping context, so going back over to my other diagram, oops. If I can move it, there we go.

The warehouse context is interacting with the customer service and the shipping context. And by the same token, the finance context interacts with the store context, and with the order processing context. So finance is operating with store and with order processing. And we’re not really seeing it here, but well, we are, actually. The store interacts with the warehouse, so we have a interacts with relationship here.

So what I’ve drawn here, then, is a map of the system which is showing me the bounded contexts and the relationships that they have between them. And a diagram like this can be extremely useful when you are trying to get a big picture. Now I’ve just drawn it on my virtual whiteboard here, but I should say that when I do this in the real world, I found that the best way to do this is to use index cards or large post-it notes. So what I’ll do is each one of the context will have an index card associated with it with the name of the context at the top, usually the things that are inside the context underneath the line and then I’ll tack them, literally tack them up on a cork board on the wall and I’ll stretch little pieces of string between the cards that are related to each other in order to indicate their relationships. So that way, you end up with a physical artifact on the board, which anybody can walk over to and look at, and more to the point, it’s really easy to change as the design evolves.

 Demo: Entity Map

There’s one other artifact that might be useful as you are working from your entity map in the direction of the code. The basic problem here is to put into a concise format the jobs of the individual entities inside the system. Now, again, this is something that I use index cards or large post-it notes for. So the basic idea here comes from something called a CRC card. CRC cards go back far in history. They were developed by Kent Beck and Ward Cunningham when they were teaching object-oriented design.

Rebecca Wirfs-Brock did a lot of work with CRC cards, in fact, has written quite a nice book on the subject, but this is from probably 20 years back now, a long time ago.

The basic idea of the CRC card is to try and identify the classes in the system, the responsibilities they have, and the collaborators, who do they talk to?

Now, in an Envy model, classes are not really going to be classes. They’re probably going to be services or something like that, or entities, just leave it at entities, but the responsibilities are particularly important. We’re not interested in other words of defining methods or something like that at this point. We’re trying to figure out what responsibilities the individual entities have.

So, going up and looking at our earlier model, the sales clerk is responsible for notify the customer about sales activities. So I could make a card for that. I could call it the sales clerk.

So that’s basically a CRC card in this kind of context.

Now, in terms of the real big picture, you’d have multiple cards, and again, they would have relationships to other entities, so the basic idea here, for example, is if the finance entity who’s handling authorized shipment talks to a shipping clerk through a shipment authorized event, there is a connection there, there’s a kind of lightweight, coupling relationship there. So what that’s saying is that the comptroller is interacting with the shipping clerk through an event. So what I think of this as is not a context map, but an entity map.

What it’s doing is just showing us all the entities in the system, and the relationships they have with each other by means of the event system.

So you don’t need either of these diagrams. They’re both useful, they’re particularly useful as the system gets larger and larger and larger. For one thing, the entity diagram over here can be capturing information from multiple stories, which you won’t see on an individual map, but whether you need it or not is going to depend a lot on the complexity of the system, how big the system is, things like that. But I’ve found them to be useful in my own work.

Next Steps:

 

Conclusion

Domain-Driven Design provides a structured approach to modeling complex domains. By defining Bounded Contexts, identifying entities, and using event-driven communication, DDD helps bridge the gap between business requirements and software implementation. When combined with microservices, DDD enables scalable, maintainable, and efficient systems. 

 

References:

https://www.linkedin.com/learning/software-architecture-domain-driven-design

Leave a Reply

Discover more from Rajeev Singh | Coder, Blogger, YouTuber

Subscribe now to keep reading and get access to the full archive.

Continue reading