We’ve had some difficult meetings in the past 2 weeks. Some were because there were issues that came up during the development of a feature that we hadn’t talked about during our initial refinements and planning (1). Some were because of an inherently difficult topic (that might well be its own context) that some of us didn’t feel comfortable continuing/releasing with the amount of information we had (2).
The most difficult part for me during these meetings was the way we talked about what had went wrong before. We are a team that mostly consists of people who haven’t been there before July (other teams, other companies) and we are used to different ways of working.
A lot of our communication during development happens asynchronously in Slack. “I’m not sure what this acceptance criterion is meant to say, can someone explain?” usually yields good results if someone who knows sees the message and says “yes, let’s have a quick chat so I can explain”. It doesn’t if no one is actually sure about this anymore. “Ugh, I can’t remember” is not that much (but slightly) better than no one replying at all.
We had a lot of “Why did you only write this in Slack? Why didn’t you mention it at our next refinement?” and “because I thought you others had talked about this problem while I wasn’t there, not that no one has thought about this before” back and forth. And a lot of “Why did no one speak up during refinement?”, sometimes closely followed by “Why are you speaking up now? Why are we making a fuss about something that we had a common understanding of a few minutes/days ago?”
I think there are multiple problems hidden in this:
We will never get to a perfect refinement, where we think about all possible edge cases. Some things just come up while writing code. You test one invariant and then you realise there’s a related one that’s so edgy no one talked about it before. Sometimes everyone thinks they understood things the same way but if you dig deeper you realise that wasn’t the case.
We have different levels of comfort when it comes to our blind spots in terms of the domain(s) we are talking about. To me, Domain-Driven Design means really understanding what and why you are doing things. And we don’t live in a perfect world where our domain experts are always available, so we need to do some guessing now and then. But then we should at least be comfortable with the guessed model we came up with.
This leads me to some questions:
a. How can we make our refinements better? We learned in the past weeks that we get better results when we draw out stuff (what a revelation, I know). But how can we get better at thinking about (almost) all possible cases? Yes, we could BDD the crap out of every user story, but we all know that business won’t read them, so is it worth the effort? Would we really get that many new insights and improved understanding without validating with our domain experts?
b. How can we adopt a “Fail Fast” culture for our product development process? I think we can count it as a failure if we didn’t catch an issue during refinement and planning. So the fastest way to fail would be to catch it during development. So shouldn’t we celebrate this instead of asking ourselves why we did not catch it even earlier? Or am I going about this the wrong way?
How can we get to a common ground when it comes to understanding our (sub) domain and those our feature has implications on? I am usually someone who pushes this hard. I want to know everything. And I know that my anxiety plays a big part in that. But I also know that some of my nagging has led to improved understanding and thus improved models. I do see though how time consuming this is and that a lot of problems maybe could be fixed in another iteration without too much chaos. But how do I learn what is enough? How does our team learn what’s the right level?
And last but not least: How can we communicate about all this better?