I remember the first time I heard this. It was on a podcast. I listen to so many podcasts that it was a fruitless effort trying to find it. So perhaps writing about it will allow me identify this very smart person.
It’s sometimes ironic when you hear such a nugget of wisdom, but fail to realise the value of it. This was one of those cases, and in my DevOps journey, it has been a gem of wisdom that I have managed to articulate to a wider group of contributors — from devs, to DBAs to BAs to Product Owners. But alas when I first heard it, I was yeah, that’s kind of cool…
I've always felt I've let developers down in my attempts to give them a logical equivalent of production. At Olympic, when I was looking after the dev team for the Woolworths shopping site, we had more than our fair share of HTTPS errors. Some of them were simple errors, and some seemed to sneak up on us due to the speed of HTTPS changes in Chrome. The sad fact was, regardless of the error, it was complex to provide HTTPS in dev. IIS Express did get us a little closer, but still the infra (infrastructure) changes would leak into the code, which is where I drew the line. Managing the state of your app based on features is hard enough. Managing the state of both environment and features in your app is just crazy — and that’s crazy meaning bad not crazy meaning good.
You can imagine my joy when I came across tools like Vagrant and Bowery.io. Finally, a repeatable, reliable means of abstracting dev environments. Being able to provide at least a logical and repeatable representation of production, was bad! — That’s not bad meaning bad, but bad meaning good!
Say what you want sports fans, but MJ has some mean moves. So one can imagine my dismay when I was told — “this sounds complex Reuben.” Mmmmm, really?
You would think this was, perhaps an aberration — a blip in the space time continuum, but I am truly astounded, as I encounter this reaction a lot when suggesting release automation ideas. Ideas like “v1.0 of your app should be your pipeline to PROD”, is meet with “mmmm Reuben that’s too complex.” I smell a pattern here, how about —
Hard yes, complex no.
There’s a certain irony here, as I myself, having contributed my fair share of code, have settled for nothing less than complexity for the implementation. I’m sure sports fans, that you have not fallen into this pit of despair.
Yes I am a recovering over engineer-er
So when developing, complexity is our friend when it comes to implementation. Anything outside this scope, complexity is a barrier. Herein lies the issue, easy, hard and complex are relative. I also think the following are likely candidates for poorly distinguishing between these states:
- When teams are under so much pressure to deliver, even just thinking outside the scope of the sprint is a massive context shift. Context shifts have a huge consequence to contributors. There is also technical and emotional baggage as well. In this scenario anything outside the scope of the sprint is complex.
- Lazy — I tried to think of another adjective but hey it’s the truth. We pick and choose, which is a part of our human make up. We are quick to make decisions, and if we're not inspired or motivated or if we don't resonate, then it’s very easy to say “it’s complex”, as an excuse not to understand the issue, let alone do the work. Hence lazy.
So as any good agile person would say — how about a glossary? Here's a Reuben Dunn definition of the two. Paraphrased of course.
- Involves many things, like people or business processes.
- A myriad of dependencies.
- The Rosetta Comet Mission spent 10 years heading towards comet 67P. It was to intercept the comet and then land a probe on the surface of a comet, which would be 310 million miles from earth. That’s so far away it takes 20 minutes to communicate between Rosetta and Earth. The team landed the probe on a comet, shaped like a rubber duck, traveling at some insane velocity.
- The inter and intra workings of a cross functional team of contributors working together to deliver value to their software.
- Implementing a queue mechanism using a database.
- Just one week of no issues on the Auckland Train Service.
- Stuff that takes time, and makes you think.
- Stuff you don't feel like doing or are not inspired to do aka Lazy.
- Naming things.
- Cache invalidation.
- Off-by-1 errors.
- Adding a build/release pipeline as your first feature — automated build,test, deploy.
- Talking with people face to face.
- Turning your 7 step installation document for Foo into an automated install script.
- Learning Git commands and switches.
If there’s anything I've missed or you have a different opinion, leave a note.
The key is knowing the difference between the two and being willing to be held accountable on it. Typically I feel that when we fail to articulate exactly what the issue is, we enter a trap where those issues will never get solved.
For me the biggest factor in deciding between the two is this unrealistic trap where contributors think they need to solve all problems. This is the first anti-pattern that we need to break. Contributors need to be equipped, which is easier said than done, but we need to know where the needs are. If contributors are putting everything into the hard or complex bucket, these needs become invisible. This helps no one.
Hard things can be solved by contributors. They may need some assistance, whether it’s a research or implementation spike, or consulting with another team. This may have a heavy time component so we may need an iterative approach, and acknowledge the effort in the sprint.
Complex things typically require a diversity in thought, which brings its own inertia. The thinking stage may be longer than the implementation stage, which sounds obvious when you think about it, but, as Rosetta has shown us, complex things can be done.
One area that will continually be grey, are issues that are relatively easy/hard to understand but can be complex to explain. A great example of this was IOC/DI. DI was relatively easy to grasp and explain. IOC, on the other hand, I could never understand from reading stuff and listening to someone explain it. The irony being when I figured out what IOC looked like, I was like, is that it? In fact, I believe to this day, I have never been able to explain that to anyone. This can cause confusion of what is hard and complex
My encouragement to you all, is to learn the difference between the two, in order to uncover the real issues. Is something hard or complex because we are time poor? Then perhaps reducing your velocity for a couple of sprints is what you need. Is this complex because it requires the team to resolve conflict? Then perhaps you and your team need a crucial conversation?
It also forces us to have the value proposition discussion. What is the value of doing this hard task? A build pipeline’s value grows exponentially as we delivery more and more releases (OK I'm only going on empirical data here…) Some complex tasks might not have enough value to complete the task, but the discussion may start. This approach may be employed to select a less complex implementation as well.
Then consequence of getting this wrong, I feel, leads to a greater dysfunction — at a micro (team) and a macro (organisational) level. These consequences typically unfold at release and typically impact other teams, and are things that continually repeat. This causes frustration which contributes to flashpoints across the organisation.
Learning how to approach problems is just as important as solving a problem. The more we do it, the better equipped we become. By discerning between easy, hard and complex, we'll have better success at using the right approach to solve the problem.