Monday, April 12, 2021

Stop measuring Sprint Predictability

In strongly plan-driven organizations, we often see a fascination with Sprint Predictability. So - what is it, and why would I advise against it?

Let's first take a look at how we can measure Sprint Predictability:

We have four key points of interest in this measurement system: 

  1.  What did the team plan based on their known/presumed velocity?
  2.  What did the team actually deliver based on their committed plan?
  3.  What did the team miss, based on their committed plan?
  4.  What did the team overachieve?

Charted, it could look like this:


We can thus tell whether a team can estimate their velocity realistically, and whether they are setting sufficiently SMART (Specific, Measurable, Ambitious, Realistic, Terminated) goals for themselves.

In a multi-team setting, we could even compare these metrics across teams, to learn which teams have a good control over their velocity and which don't.

If by now, you're convinced that Sprint predictability is a good idea - no! It's not! It's a horrible idea!

Here's why:

The Crystal Ball

Every prediction is based on what we know today. The biggest challenge is predicting things we don't know today.

Here are a couple reasons why our forecast of predictability may be entirely wrong and why we may need to adapt. We may have ...

  • Vague objectives
  • Mis-estimated the work
  • Made some assumptions that turned out false
  • Encountered some unforseen challenges
  • Discovered something else that has higher value

Of course, management in a plan-driven organization can and will argue, "That's exactly the point of planning: to remove such uncertainties and provide clarity." With which we are back to square 1: Trying to create the perfect plan, which requires us to have a perfect crystal ball. 

Predictability implicitly assumes that adaptation (ability to respond to change) is a luxury rather than a necessity. When we operate in an environment where adaptation really isn't required, we should not use an agile approach to begin with.


Let's now take a tabular look at the five reasons for getting forecasts wrong:

Cause Challenge Alternative
Vague objective The communicated objective and the real goal may be miles apart.
It's better to pursue the actual goal than to meet the plan.
Take small steps and constantly check whether these are steps in the right direction, changing course as new information arises.
Mis-estimation Work was perceived simpler than originally thought, mandating tasks nobody expected, consuming extra time. Avoid aligning on the content of the work, instead align around the outcomes and break these into bite-sized portions that have little risk attached.
Wrong assumptions Some things about our Product turned out differently than we had anticipated. We can do more pre-work, which does nothing other than trade "delivery time" for "preparation time", we still make un-validated assumptions. Validating assumptions is always a regular part of the work. Set up experiments that determine the next step rather than trying to draw a straight line to the goal from the beginning. Accept "open points" as you set out.
Unforseen challenges An ambitious plan has risk, while an un-ambitious plan has risk buffers. Pondering all of the eventualities to "right-size" the risk buffer is a complete distraction from the actual Sprint Goal. Equally avoid planning overly optimistic (e.g., assuming absolutely smooth sailing) as well as overly pessimistic (e.g. assuming WW3 breaks out) and just accept that unusual events take us out of our comfort zone of being predictable. Learn over time which level of randomness is "normal."
Value changed Something happened that made new work more valuable than the one originally planned. While this shouldn't frequently happen within a Sprint, it could be part of discovery work. Ensure there is clarity within the team and organization that the primary goal is maximizing value and customer satisfaction, not meeting plans. 

As we can see from the above table, "Sprint Predictability" is a local optimization that gives people a cozy feeling of being fully in control, when in reality, they're distracted from creating value for the organization. 


Re-Focous

As much as managers, and even some Scrum Masters, like to use metrics and numbers to see whether teams have high predictability on their Sprints, we need to re-focus our discussion towards:
  1. How well do we understand which goal we're trying to achieve? (Level of Transparency)
  2. Do we understand, and have the ability to generate, value? (Ability to Inspect)
  3. Since "The biggest risk is taking no risks" - let's agree on how much risk can our organization bear with (Ability to Adapt)
When we focus on these pillars of Scrum, we will go an entirely different direction from "becoming more predictable" - we need to improve our ability to respond swiftly and effectively as new information arises!

And once we have high responsiveness, we can argue formidably whether a "Sprint Predictability Index" has any value at all.

Sunday, April 4, 2021

A few things you have to understand about systems

The difference between a system and a compound is that while a compound is defined by the sum of its component, a system is defined by the product of the interactions of its components.

This very simple statement has profound consequences, regardless of whether we are talking about chemical, physical, social or entire economic systems.


Decomposition and Reassembly

Classic science has it that if you de-compose a complex problem into smaller units, the complexity can be handled in individual bites. While this works great when interactions are not as prevalent, it entirely fails when the behaviour of a system is predominantly defined by component interactions.

A de-composed system missing even one of its interactions will not display the same properties as the complete system.

Modifying a de-composed system may create an entirely different system when re-assembled.


Synchronization

Interaction generates friction. The mechanism of minimizing friction is synchronization.

As friction reduces the motion energy of the affected components, the amount of friction gradually reduces until the interacting components will have minimal friction.  As such, every interacting component of a system will enter into a synchronized state over time.

The momentum of a system in a synchronized state will be the cumulative momentum of all components. The same holds true for inertia.

Synchronization does not equate stability. Indeed, the process of synchronization could destabilize, and potentially destroy, the entire system.


Subsystems

On a higher level of abstraction, a subsystem behaves like a component, assuming its internal and external interactions are separate and distinct.

Interacting subsystems will generate friction until they are synchronized.

Subsystem synchronization could oscillate between different states and have different driving forces until an equilibrium is achieved.

Independent subsystems behave like components: they may be in sync within themselves, yet out of sync with each other.


Component Effectiveness

Since the components of a system are as effective as their interactions, the effectiveness of any individual component is both enabled and constrained by its interaction. 

Effectiveness is enabled by synchronized interactions.
Effectiveness is constrained by frictional interactions.

When a component's interactions are predominantly frictional, the component is rendered ineffective unless it's intended to be an abrasive component.


Why is any of that important?

Think about what the above means for piloting changes in parts of your system.
You may not achieve what you intend.

Thursday, April 1, 2021

Improving Code Reviews

A "code review" activity is part of many organizations' development process - and oftentimes, it sucks. It frustrates people, wastes their time and the value in improving quality is questionable at best. If you feel that's the case, here are some things you can try.




What's a Code Review?

"Code review" is a feedback process, fostering growth and learning. It should not be confused or conflated with a QA sign-off process. While finding problems in the code may be part of doing the review, that's not the key point.

So-called one-way "gate reviews" without feedback on defect-free code are a waste. A major portion of their value is missed. The best reviews won't merely help people learn where they messed up - they help people find new, better ways of doing things!

Now, let us explore five common antipatterns and what we could do about them.

Five Code Review Antipatterns and how to deal with them

Review Hierarchy

In many organizations, the Code Review process "puts people in their place": A more senior person reviews the code of more junior persons, and annotates everything that these did wrong. Yes - this sounds exactly like a teacher grading a student's term paper, and the psychological implications are very similar.

While this does indeed foster some form of learning, it creates an anhedonian mindset: the key objective of the coding developer is to avoid the pain of criticism and rework. There is little joy in a job well done. Deming's 12th point comes to mind.

Suggestion 1: Reverse the review process. Let the junior review the senior's code, and see what happens.

Suggestion 2: Do review round robins. Everyone gets to review everyone else's code.

Suggestion 3: Have an open conversation, "How do Code Reviews affect our view of each other's professionalism?"


Huge Chunk Reviews

I'll admit that I've been both on the giving and receiving end here: Committing huge chunks of code at once and sending thousands of lines of code for review in one big bulk, without any comments. And the review outcome was, "This is garbage, don't work like that!" Rightly so. Nobody in their right mind has time to ponder such a huge amount of changes in detail. The review feedback will take a long time and probably not consider all the important points - simply because there are too many.

Code Reviews shouldn't create a huge burden, and they should have a clear focus.

Suggestion 1: State the review objective: What would you like feedback on?

Suggestion 2: Send increments into Code Review that can be thoroghly reviewed in no more than 15 minutes.

Suggestion 3: Reduce feedback intervals. For example: no more than 2 days should pass between writing a line of code and getting it reviewed.


"LGTM" or whimsical feedback

Poor reviews start with the premise that "the only purpose of a review is to find problems." On the positive side of the spectrum, this leads to a lot of a standard "lgtm" (Looks Good To Me) annotations as code is simply waved forward. On the opposite side of the spectrum, some individuals feel an almost sadistic need to let others know that there are always problems, today stating "this is good", and tomorrow stating "this is bad."

Behind this antipattern is the "controller mindset" that someone in the organization believes that a review is intended to tell others, "you did this wrong, you did that wrong.

You can improve this by moving away from checking the code towards positive reinforcement, creating virtuous learning cycles

Suggestion 1: Change the guiding question from, "What is wrong with this code?" towards, "What could I learn from this code?

Suggestion 2: Create Working Agreements how you want to deal with extreme ends of the review spectrum.

Suggestion 3: Collect the learnings from Code Reviews and look at them in the Retrospective.


Ping-pong or Ghosting

Small story: One of my teams had just fixed a production problem that was causing a revenue loss of roughly €15k per day. Someone from a different team did the code review, demanded some semantic fixes, these were made - next round: lather, rinse, repeat. After 2 weeks, the reviewer went on vacation without notice. The fix got stuck in the pipeline for 5 days without response. This funny little event cost the company over €250k - roughly three years' worth of developer salary!

Things like that happen because the expectations and priorities in the team aren't aligned with business objectives and also because of a phenomenon I call "ticket talk."

Suggestion 1: Make the Wait Time and Flowback caused by Code Reviews visible.

Suggestion 2: Create a Working Agreement to talk face-to-face as soon as there's flowback.

Suggestion 3: Replace Code Reviews with Pair Programming.


Preferences, emotions and opinions

Let's return to the "whimsical feedback" antipattern briefly. Many times, I see feedback over "use CamelCase instead of Snake Case", "use Tabs indentation instead of spaces" or whether a "brace should open behind the method name rather than in a new line". 

None of these make the product any better or worse. The debate over such matters can get quite heated, and potentially even escalate into a full-blown religious war. These are entirely up to personal preference, and as such, not worth a review annotation: They are red herrings. 

Suggestion 1: Formalize coding conventions and put them into your Lint / SCA config.

Suggestion 2: If you're really bothered, use a pre-commit hook to prevent checking in code that violates static code rules.

Suggestion 3: If you think a rule is missing or unproductive, bring it up in the Retrospective.


Alternative perspective

Code Reviews are just one way to improve coding within a team and/or organization. Mandatory code reviews - by default - create interrupts in the flow, reducing overall performance by a significant amount. Better options include:

  • Code Review upon request
    (e.g., "I want to talk with you about this code")
  • Code Dojos, where the entire team assembles to learn from one another.
    (SAFe's IP Iterations are great for dojos.)
  • Pair programming - making the discussion part of the process.
    (Reviews should be obsolete if you do Pairing right)

Still, if your organization mandates code reviews, try to make the best from them.


Summary (tl;dr)

Code Review is more about fast feedback learning than about "catching errors".
A positive "what can I learn" attitude makes reviews much more enjoyable and beneficial than a negative "what did they do wrong" attitude.

When reviews expose pressing problems, don't just annotate them. Engage the discussion about "how can we work differently?"