Count the decisions

Free preview 5 min to read

Grooming is easiest to understand backwards: look at finished code and count the decisions that had to be made before it could exist.

The ticket

Imagine the line that started this feature:

"When an admin adds a partner, fetch their logo from their website automatically."

One sentence. Reasonable. It is what an ordinary backlog item looks like, and everyone in the room would nod at it.

The code

app/services/partners/fetch_site_icon_service.rb, 86 lines. Here is what is in it:

MAX_BYTES = 1.megabyte
TIMEOUT = 5
ACCEPTED = %w[image/png image/jpeg image/webp image/svg+xml
              image/x-icon image/vnd.microsoft.icon image/gif].freeze
# Preference: apple-touch-icon (largest) > <link rel="icon"> (largest) > /favicon.ico
def fetch(url, limit = 3)
  return nil if limit.zero?
rescue URI::InvalidURIError, SocketError, Timeout::Error,
       OpenSSL::SSL::SSLError, Errno::ECONNREFUSED => e
  Result.new(success: false, url: nil, errors: [ e.message ])

The decisions

Reading those four fragments, at least eleven separate questions were answered:

# Decision Value in the code
1 How large a file will we accept? 1 megabyte
2 How long do we wait? 5 seconds, open and read
3 Which image formats? Seven, listed explicitly
4 Which icon do we prefer? apple-touch-icon, largest first
5 What if there are several the same size? Not decided: sort_by is not stable, so a tie can come out in either order
6 What if the page declares none? Fall back to /favicon.ico
7 Do we follow redirects? Yes, two at most (three requests in all)
8 What happens if the site is down? Return a failure Result, do not raise
9 Which failures do we catch? Five exception classes, named
10 Does a failure block adding the partner? No: the admin can still save
11 Do we identify ourselves? A User-Agent naming the app

Eleven decisions, and the ticket contained none of them.

flowchart TB
  T["'fetch their logo automatically'"] --> D["11 decisions"]
  D --> G["decided in a grooming session, together, in 30 minutes"]
  D --> A["decided alone at the keyboard, in 11 interruptions"]
  D --> P["decided by production, in 11 incidents"]
  G --> R["the same eleven answers, at different prices"]

The three places a decision gets made

In a grooming session. Together, before the work starts. Everyone hears the answer, the reasoning is on record, and disagreement is cheap because nothing is built.

Alone at the keyboard. The developer hits each question mid-flow and picks something reasonable. This is not a failure: most of these eleven are perfectly good decisions and the developer was the right person to make them. The cost is that nobody else knows the answers, so the reasoning lives in one head and in git blame.

In production. A partner's site serves a 40MB TIFF and the request hangs. Now decisions 1, 2 and 3 get made, expensively, by whoever is awake.

The same eleven answers, at three very different prices. Grooming is not a ceremony; it is choosing the first column for the decisions that are expensive in the third.

Which of the eleven belonged in the session

Not all of them, and this is the part that separates useful grooming from a meeting.

Decision 10: does a failed fetch block saving the partner?: is a product decision. Nobody but the person who owns the feature can answer it, and getting it wrong means rebuilding the controller.

Decision 8: return a Result or raise?: is an architectural convention this codebase already has, so it needs no discussion at all.

Decision 3, which image formats?: is a fine thing to leave to the developer. It is cheap to change, invisible to the product, and looking up what browsers accept is a five-minute job that a meeting makes worse.

A first cut at the rule, refined over this course: groom the decisions that are expensive to reverse or that someone outside the code has to answer. Leave the rest to the person doing the work.

A session that decides all eleven wastes an hour. A session that decides none of them leaves the expensive ones to production.

Key takeaways

  • A one-sentence ticket produced 86 lines containing at least eleven separate decisions.
  • The same decisions get made in grooming, at the keyboard, or in production: the answers may match, the prices do not.
  • Decided at the keyboard, the reasoning lives in one head and in git blame.
  • Groom what is expensive to reverse or what someone outside the code must answer.
  • Deciding all eleven in a meeting wastes an hour; deciding none leaves the expensive ones to production.
Lesson 1 of 7 · free

Keep going with lesson 2

What grooming is and is not

Separates grooming from four other meetings and defines its three outputs, attendees, timebox and inputs.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...