2

I understand "the works" of event driven systems and I've built simple ones. However I find that I am struggling a bit in efficiently designing one.

E.g., Formulating all the events upfront seems not easy, I find that I'm removing/renaming some events I initially determined later down the road.

Another thing is determining the services that are supposed to care about those events upfront. E.g., "orderPrepared" event? Ahh service x,y,z needs that. Catch my drift?

I guess my question is, after determining the business requirements, what's your methodology in designing an event driven system? How does one actually "lay it all out" in an effective manner, minimizing changes later on?

1
  • 2
    I find that I'm removing/renaming some events I initially determined later down the road. -- Yep, that's how it works. Unless you're doing Big Design Up Front (a well-known anti-pattern), there's no possibility of knowing all the details ahead of time. Jan 8, 2020 at 15:45

5 Answers 5

6

While I am not an advocate of Big Design Up Front, I'm also not an advocate of No Design Up Front. Some systems are complicated enough you have to think through them. When you have multiple systems working together, and events (or messages) connecting them, there are often multiple teams affected by the mistake.

Agile methodology has the concept of Just in Time Design. Basically deferring the design until just before you actually have to implement a feature. The way it works in our sprints is something like this:

Release Train:

  • Sprint 1: perform Spike to design the interaction
  • Sprint 2: break down the tasks and start implementing them
  • Sprint 3: finish implementing, do integration testing, write bug reports
  • Sprint 4: finalize, regression test, and deploy

And then rinse and repeat for each release train after that.

The idea is that your Spike is time-boxed, and you have taken the time to think through:

  • What events/messages are needed to integrate the systems
  • What information needs to be included in the event/message
  • What guarantees or responses would be needed (if any)

At the end of the Spike, you write it up so everyone can reference it, create tasks in the backlog if needed to implement the details, and then those tasks can be worked.

This works well because you don't go into minutia like BDUP is known to do, and your design artifacts build up at the appropriate level of abstraction to be useful across teams. The type of information you need in the design is always subject to change, but those changes should be simple iterations with slight tweaks over time.

1

As @Robert Harvey has mentioned in the comments, there is no way for you to know everything before hand. And even if you are confident of the requirements before designing the system, to assume that requirements would not change will bring you nightmares later.
You are looking for an extensible design so breaking it down further would help.
1. Renaming/Removing some events. How to fix this? Thinking out loud, how about a configuration that services can fetch to determine what events they need to read. Since you are expecting this to change frequently, try making this a really light-weight service meant to handle just fetch and deliver of events. With this, if you end you changing your events, you might have to change a config and when your service pulls/refreshes the config, will read the new events.
2. Determining the services that are supposed to care about those events upfront. Wouldn't pub-sub model help for this? Your publishers don't really have to know who they are sending events to, they dump it to a sink and any numbers of services can subscribe to any number of events.

What's your methodology in designing an event driven system
1. Isolation: break the service down to the level where you think changing would not be cascaded to the other services. Let the service alone fail in case of any issue.
2. Use configurations liberally, they act as tuning parameters in your working system, move everything that you thing can change to configs.
3. Ensure your listeners are not doing a lot of heavy lifting in the context of reading the events.
4. Make your systems idempotent, consider logs if necessary, retry on failure and and replay your events if necessary. A good guide here.

0

I know it will sound old-fashioned, but the most solid way to model event driven systems is through state transition charts (a.k.a. state machines). If you are not familiar with UML, you can do your modeling with an event list. You can do it in a white board, and a very simplified example follows. (Nouns in upper-case are our first approximation to classes that will be needed in the actual implementation.)

User requests Copy of Book [this event triggers the transition from the starting point to the first state: Copy requested]

Librarian checks in LibrarySysSession whether a Copy of the Book is available [this is an action inside the Copy requested state]

If Copy is not available

LibrarySysSession displays Copy not available [this action triggers a transition to the end point of the state machine]

If Copy is available

LibrarySys displays Copy available [this action triggers transition to the Copy available state]

Librarian reserves the Copy [this action triggers the transition to the Copy reserved state]

Librarian fetches the phisical copy [this is the first action in Copy reserved state]

Librarian registers the lease of the Copy [this action triggers the transition to Copy leased state]

Librarian hands the copy to User [this is the first action in the Copy leased state]

And so forth... Of course, it's best to draw a state machine diagram, prefferably with a software engineering tool; but the event list is the most economical way of doing it, especially in a highly agile environment. Do have a team member copy the white board list to Google Docs, OfficeLibre, or whatever you are using.

By the way: event lists were one of the first methods used to identify classes in object-oriented analysis and design.

Best wishes!

0

Depending on how deep you want to get into the Domain Driven Design woods, you could consider Event Storming.

Doing one of these will highlight the domain events etc you should be interested in and how they relate to the rest of the system. Note that domain events are not the same thing as events in event sourcing. But understanding them will help you solve your "what events do I need" problem. Domain events are business actions not system concepts.

The Wikipedia article is a pretty good summary but reading some post-workshop summaries is a good way to get a feel for it. Open Practice Library has a good list of resources.

I find that the inevitable changes to which system event/components you need are much easier if you have a clearer picture of the domain events.

0

I would recommend reading Event Streams in Action - it will go over some of the design choices, such as

  • Passing data by reference vs. including all data in the event proper
  • Railway processing and dead letter queues
  • Registering and evolving event schemas (With avro and a schema registry)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.