alberto-brandolini event-storming domain driven design highlights Product and Tech
(LM → my personal comments)
It turns out that the steps are awkward. The software is imposing a couple of extra process steps to guarantee consistency of the internal data structure, but this approach is unnaturally pushing complexity outside the software, forcing users to do extra manual activities on paper and phone.
Finding a solution won’t be as easy as spotting the problem. And the blocker is only the visible symptom, not the root cause. But choosing the right problem to solve is a valuable result and we achieved it quickly.
Even if we established a clear link between the main process blocker and a possible solution, putting it to work is not only a technical issue: permissions needed to be granted, and roles and responsibilities in the organization around that step needed to be redesigned to overcome the current block.
Despite the initial assumption that software was the most critical part, it turned out that the solution was mostly politics. And when it comes to politics, transitions usually take more than expected, and they’re never linear or black-and-white.
we start introducing more rigor in our process by introducing Commands representing user intentions/actions/decisions (they are blue stickies where we write something like Place Order or Send Invitation), and Actors (little yellow stickies) for specific user categories.
Read models are emerging as tools to support the decision-making process happening in the user’s brain
Only a few places still look like CRUDs, but most of the business is described in terms of Events flowing in the system. -> And it feels so right.
Domain events may come from:
Silos minimize the learning newcomers need to start contributing to the company business.
This is the fundamental evolutionary advantage of Silos: they allow us not to spend much time explaining our organization to newcomers. Somebody is going to say something like: “That’s all you need to know!” and the new hire is now ready to deliver value, with no possible excuses.
Silos promote local optimizations. It’s easier to gather consensus (more about it later) around issues and agree on local improvements than to find a cross-team or cross-department agreement.
we need to define some goals and targets sounds like common sense or a tautology. Yet, linking salary bonuses to reaching given goals isn’t necessarily obvious or even a great idea. Over justification - replacing the existing intrinsic motivation with an extrinsic one, a prize, or a sum of money - has the nasty effect of killing the original motivation. It does work with dogs, but it’s already wrong with kids. If you’re working with adults, maybe you should be looking for something more sophisticated.
Organizations are made of human beings and shaped by their decisions.
We’re biased to add, not to remove It turns out there is a strong bias towards adding things instead of removing them
We’re given a small lego structure, and we assume there must be a reason for this shape. Nobody mentioned it, but well …let’s make sure we’re not making mistakes or irritating anyone.
Now, forget easy experimental challenges with lego bricks and think about processes and rules in your organization. Many people will complain about them, but very few people will have the guts to break them or even take the initiative to change them unless they’re pretty sure there won’t be consequences.
LM: people are so afraid to refactor old code, so complexity only grows and exponentially
The natural bias towards adding is strong and pervasive. We can affect organization agreements, but software development, law-making, and city evolution follow similar growth anti-patterns.
LM: software developers that were not exposed to the cost of their “additions” in their work experience (in my view, most developers who never worked at an early stage startup) will just add another database, add another messaging system, add another framework. They’ve never paid the price of maintaining those things because they changed teams, or because they had a devops team to manage the infrastructure for them. The one with narrow views, not even realize they are paying the price because they are just doing tickets, so they don’t realize the work they are doing now is a consequence from their decision a couple of months back.
I suspect the reason has to do with confidence: you’re not taking many risks adding one more piece to the puzzle. Removing one piece instead requires being aware of the impact of your choices on a larger ecosystem. When this awareness is hard to achieve - like in complex artifacts, siloed organizations, or untested legacy software - you enter the realm of risk-taking …or simply stay out of it.
Facilitation around critical decisions is necessary and challenging. Unstructured discussion can lead to half-hearted commitment, an illusion of consensus, or - worse - the feeling of being tricked into someone else’s agenda.
Software development is a learning process, working code is a side effect
LM: and AI with take care of the latter.
It’s not the typing, it’s the understanding that matters. However, once you acknowledge this, a whole world of inconsistencies starts unfolding.
What is the value of code written on time, and on budget by someone who doesn’t understand the problem?
LM: OMG this is sooo true. The answers is “negative value”. Just added complexity without any gains.
Just measuring deliverables is a lot easier. But this oversimplification is poisonous. The value for the company is not in the software itself, it’s in the company ability to leverage the software in order to deliver value.
LM: hence why project managers are mostly unnecessary or they destroy value according to Marty Cagan. They widen the gap between value and software.
Software doesn’t work like that. Misunderstandings aren’t funny, they’re more likely mistakes that could cost a lot of money, or even human lives.
Coding and ambiguity don’t play along very well. Coding is actually the moment when ambiguities are discovered, in the form of a compile error, an unexpected behavior, or a bug. Conversations tolerate ambiguities, but Coding won’t forgive them.
Checklist: How many people understand your system?
iterative development is expensive. It is the best approach for developing software in very complex, and lean-demanding domains. However, the initial starting point matters, a lot. A big refactoring will cost a lot more than iterative fine tuning (think splitting a database, vs renaming a variable). So I’ll do everything possible to start iterating from the most reasonable starting point.
Among all approaches to software development, Domain-Driven Design is the only one that focused on language as the key tool for a deep understanding of a given domain’s complexity.
Domain-Driven Design doesn’t assume consistency of the different areas of expertises. In fact, it states that consistency can only be achieved at a model level, and that this model can’t be large.
LM: example: a “product” entity can have different purposes, properties and names depending of the domain: for warehouse, it’s called inventory.
When modeling large scale system, we shouldn’t aim for a large “enterprise model”. That’s an attractor for ambiguities and contradictions. Instead we should aim for 2 things:
A small, strongly semantically consistent model is called Bounded Context in Domain-Driven Design -> a portion of the model which we must keep ambiguity free. Every word in the model has exactly that precise meaning.
The event storming approach:
This is what we do in EventStorming: we gather the best available brains for the job and we collaboratively build a model of a very complex problem space.
The action will take place in phases of increasing complexity. We’ll keep things easy at the beginning, adding more details as long as people are getting confidence with the format. We’ll leverage the idea of incremental notation to keep the workshop in a perennial “Goldilocks state”: it has to be not too challenging, not too easy, just right!
commands
representing user intentions/actions/decisions and actors
for specific user categoriesuser categories
might evolve to a collection of personas
if their motivations are differentLM: your workshop might not need all those steps and the facilitator should feel what’s most important to help the overall clarity of the system to improve to all participants. In my experience with online Event storming sessions, just adding events and enforcing a timeline already generates a ton of value and this can take many 1/2 hour sessions.
Some discussions cannot be solved during the workshop. And narrowing the focus to one single issue might not be the best use of everybody else’s time. When a conversation is getting non-conclusive, I mark it with a Hot Spot (signaling that it won’t be forgotten) and move on. On the other hand, some discussions are interesting for everybody, and the workshop might be the one chance in a lifetime to get a long-awaited clarification.
Reverse Narrative is a powerful tool to enforce system consistency. Even if we think we’re done with forward exploration, we usually discover a relevant portion of the system (around 30-40%) that was buried under the optimistic thinking. -> Pick an event from the end of the flow, then look for the events that made it possible. The event must be consistent: it has to be the direct consequence of previous events with no magic gaps in between.
LM: focusing on revenue and sales goals can in fact decrease the long term value for the company, because it’s harder to think long term when you focus on revenue, but it’s easier when you focus on customer value. -> in the long term, customer value === company value
Now I consider “getting the boundaries right” the single design decision with the most significant impact over the entire life of a software project. Sharing a concept that shouldn’t be shared or that generates unnecessary overlapping between different domains will have consequences spanning throughout the whole socio-technical stack.
Ideally, a bounded context should contain a model tailored around a specific purpose: the perfectly shaped tool for one specific job, no trade-offs.
Whenever we realize a different purpose is emerging, we should give a chance to a new model, fitting the new purpose, and then find the best way to allow the two models interact.
It’s our job as software architects to discover boundaries in our domain, and this will be more an investigation on a crime scene than a tick-the-checkboxes conversation.
During a Big Picture Event storming, It’s usually a good idea to resist the temptation to resolve those duplicates and find and agree on a single wording choice. Different wording may refer to different perspectives on the same event, hinting that this might be relevant in more than one Bounded Context, or that the two or more events aren’t the same thing.
boundary events are also the ones with different conflicting wordings. Here is where the perception of bounded contexts usually overlaps. A key recommendation here is that you don’t have to agree on the language! There’s much more to discover by making disagreements visible.
Moreover, keep in mind that when two models are interacting, there are usually three models involved: the internal models of the two bounded contexts and the communication model used to exchange information between them.
In general, different phases usually mean different problems, which usually leads to different models.
The model is basically two things
Even if getting finally to the big picture felt exhausting, the real outcome is that you’ve been there, had the discussion and created the model. Don’t fall too much in love with it: the model is still wrong.
Half day session (no full day session due to Zoom Fatigue + timezone differences)
When looking for bounded contexts
You can split the workshop in smaller parallel threads, provided an expert is available for facilitating
Seeding a skeleton structure to facilitating global ordering before starting: just a few Events (possible candidates to be Pivotal Events) and/or Frames to provide some structure before the activity starts.
optional: use different colors as personal signatures. When narrating the story, turn orange all events that has been enunciated by the narrator and validated by the audience.
mental model: every step is an experiment. Make copies of the whole model on each step so you can easily go back if a given step is not making the model better.
Make interests explicit
Main recipe/tools/steps are still valid, with some tweaks
We’re expecting processes to start from a given trigger (usually a Command or an external Event), and to finish with a combination of Events and Read Models.
I tend to be really strict in the implementation of the color grammar when it comes to policies because there is always a business decision between an event and the reaction. Sometimes the underlying decision is too obvious to be noticed; the mandatory lilac is just there to force your modeling team to think.
Policies represent business decisions, organization reactions to given events, and our stickies can represent different stages of maturity.
Policies tend to be the first thing that needs to change when the business context changes. Policies are the flexible glue between the other building blocks of business processes.
The interesting bit here is that policies is where people lie. Discovering the real implementation of an existing policy is an investigation game: people will not tell you the real story at first attempt.
In EventStorming I explore Read Models starting from the decision: the decision needs data; hence, the data needs to be available, and I capture it in a read model.
avoid sequencing read models -> Some implementation need sequences, and the sequence matters, but many times, fetching data is not a process step: it’s a piece of one possible solution leaking into the problem space.
“Policies as placeholders for a mandatory conversation.”
“Hotspots as a tool from smart procrastination.”
expecting a linear process model is an illusion -> it’s normal to have a continuous explosion of branches/alternatives -> As you can only solve one problem at a time, use hotspots to make the paths you’re not exploring now visible, finish the exploration of the most important branch, then comeback and start again from the next most important branch.
Rush to the goal strategy -> Model the process as a straight line really fast (it won’t reflect reality). When speaking out loud, capture all objections with Hotspots and only then start exploring the them.
If we zoom into business transactions, we’ll discover that they’re never atomic but they’re rather a sequence of states which are somewhat inconsistent.
Once released in production, Domain Events have a very annoying cost of update, due to their high number of potential listeners. Renaming a domain event in order to increase precision, might require many other software components to be updated. As every Domain-Driven Design practitioner knows very well, naming is an incredibly hard problem, so anticipating the mess, while the model is still only paper is probably a good idea.
In Domain-Driven Design, Aggregates are defined as units of transactional consistency. They are groups of objects whose state can change, but that should always expose some consistency as a whole.
LM: aggregate === “units of consistent behavior”