Skip to content
academia.sh

Lesson 06 / 15

Code Style and Automation

Once the style axis is handed to a tool, the human's finding drops from 22 to 15 and its style share from 0.318 to 0.000; the total stays the same if all five axes were already covered, and climbs from 15 to 22 in a three-reviewer panel.

Contents

The previous lesson’s table gave its most expensive closure as the style axis: closing it missed 7 defects and found dropped to 15. The same axis was also the most crowded class in the first lesson’s class distribution, where a note was made — that this class requires the least information to see.

The two traits together set this axis apart from the others and open a question: does this axis require a human’s reading at all. The lesson measures that question. The style axis is handed to a tool, and three things are counted: what the total found becomes, how much the human’s own finding shrinks, and which classes that finding is made up of.

What the Style Axis Searches For

The style axis looks at the code’s appearance: indentation width and consistency, line length, whitespace placement, bracket position, import order, the case convention of names, trailing whitespace, end-of-file newline.

There is something missing from this list, and the distinction sits inside the course: choosing a name is not the style axis’s job. Whether a name is meaningful is a judgment and is read on the implementation axis; which case convention that name is written in is a rule and is read on the style axis. Naming itself is the subject of the Clean Code course and is not repeated here.

The part that enters the measurement is one sentence: what determines a style defect’s correctness is not a judgment, it is a writable rule. A rule that can be written can be applied, and a rule that can be applied can be handed off. None of the other four axes carries this trait: whether a signature breaks a contract, whether a body is correct, whether an assertion is meaningful, and whether a text contradicts the code all require judgment, not a rule.

The Decision Itself and Applying the Decision

A style discussion is two separate jobs, and confusing them is what burns the most rounds.

The first job is the decision itself: which indentation width, which line length, which ordering. This is given once and written into a text. The decision is not inherently right or wrong on its own; its value lies in consistency.

The second job is applying the decision: checking, on every change, whether the rule was actually applied. This job is redone on every change and involves no judgment; the rule’s text is compared against the code’s text.

What gets handed off is the second job. A formatter applies the rule to the code; a linter reports where it was not applied. Both are a tool class and make no decision — they carry out a rule already given to them. How these tools are wired in is the subject of the Continuous Integration and Delivery course, and how they are set up in frontend projects is the subject of the Frontend Quality course; neither is repeated here. The only thing measured here is what is left in review after the handoff.

Skipping this distinction shows a single symptom in practice: the same style issue gets re-argued from change to change. What is argued is, on the surface, a line of code; in reality, it is a decision that was never written down.

Writing the rule therefore comes before setting up the tool, and is independent of it. A written rule ends the argument even without a tool: the finding is no longer a preference, it is a reference to a text, and the tool only adds execution on top of that. The reverse order does not work — installing a tool in a repository with no rule hands the decision over to the tool’s settings, and the argument moves to the configuration and continues there.

# taught review-comment example, not executed

before handoff
  style   Indentation is used at two different widths in this file.
  style   Line length is over the limit in four places.
  style   Import order differs from the rest of the file.

after handoff
  (no review note on the style axis; the rule is now written into the tool)
  interface  Second parameter of the public function has become required.
  test       Test's only assertion is that the call does not throw.

This block is an example and is not run; the lesson’s numbers come only from the measurement block.

The Tool’s Two Differences

The tool entering the measurement differs from a reviewer at two points.

It is single-axis. It looks only at the style class and finds nothing from the other four classes. The rule is the one axis that can be written; the tool has no counterpart on the axes that require judgment.

It has no attention. A reviewer reads a limited number of chunks in one round; the tool reads the entire change, and that limit does not apply to it. At this lesson’s scale the two limits coincide — the change is 12 chunks, attention is also 12 chunks — so the difference does not show up in the numbers. The condition of the difference is still known, though, and it is outside this topic.

The Measurement’s Assumptions

  • RA39 — The shared setup is unchanged: 600 lines, 12 chunks, 24 defects, attention 12 chunks. The class list and distribution do not change.
  • RA40 — The tool finds only defects in the style class, and finds all of them; the chunk limit does not apply to it.
  • RA41 — The tool produces no false finding. The setup does not include the tool counting something outside the rule as a defect; the measurement is therefore in the tool’s favor, and this is stated explicitly.
  • RA42 — In the “without tool” column the human can carry all five axes; in the “with tool” column no reviewer carries the style axis.
  • RA43 — Reviewer count is held the same in both regimes; the handoff adds no one to the panel and removes no one.
  • RA44 — The tool does not count as a reading and does not enter the reviewer column; its finding sits in a separate column.
  • RA45 — The cost of the handoff — writing the rule, setting up the tool, wiring the pipeline — is not in the measurement. The only thing measured is found and missed defects.
  • RA46 — The ratio is the style defect count in the human’s finding divided by the human’s total finding. Resolution at the defect level is 1/24 = 0.042.

Measurement

"""Code style and automation: what changes when the style axis is handed to a tool.

Part 1 - the same panels without and with the tool; the human's find and the total found.
Part 2 - the class distribution of the human's finding in the two regimes.
"""
SEED = 20260815
AXES = ("interface", "implementation", "test", "documentation", "style")
UNWRITTEN = "unwritten requirement"
CLASSES = AXES + (UNWRITTEN,)
ATTENTION = 12
CHUNK = 50


def rng(seed):
    state = seed % 2147483646 + 1

    def draw(n):
        nonlocal state
        state = (state * 48271) % 2147483647
        return state % n
    return draw


def change(lines, defect_count=24, seed=SEED):
    draw, defects = rng(seed), []
    chunk_count = max(1, lines // CHUNK)
    for i in range(defect_count):
        defects.append({"no": i + 1, "class": CLASSES[draw(6)],
                         "chunk": draw(chunk_count)})
    return {"lines": lines, "chunks": chunk_count, "defects": defects}


def review(d, axes, attention=ATTENTION):
    read = set(range(min(attention, d["chunks"])))
    return {k["no"] for k in d["defects"]
            if k["class"] in axes and k["chunk"] in read}


def panel(d, assignments, attention=ATTENTION):
    found = set()
    for axes in assignments:
        found |= review(d, axes, attention)
    return found


def formatter(d):
    """The tool class: only looks at the style axis, no attention limit."""
    return {k["no"] for k in d["defects"] if k["class"] == "style"}


FULL = set(AXES)
HUMAN = FULL - {"style"}
d = change(600)
tool = formatter(d)

PANELS = {
    "one reviewer": ([FULL], [HUMAN]),
    "three reviewers, separate axes": ([{"interface"}, {"implementation"},
                                        {"test", "documentation"}],
                                       [{"interface"}, {"implementation"},
                                        {"test", "documentation"}]),
    "three reviewers, same axis": ([{"implementation"}] * 3,
                                    [{"implementation"}] * 3),
    "five reviewers, five axes": ([{a} for a in AXES],
                                   [{a} for a in sorted(HUMAN)] + [HUMAN]),
}
print(f"{'panel':<32s} {'without tool found':>18s} {'with tool: human':>16s} "
      f"{'tool':>4s} {'total':>6s} {'missed':>6s}")
for name, (a, b) in PANELS.items():
    plain = panel(d, a)
    human = panel(d, b)
    total = human | tool
    missed = [k for k in d["defects"] if k["no"] not in total]
    print(f"{name:<32s} {len(plain):18d} {len(human):16d} {len(tool):4d} "
          f"{len(total):6d} {len(missed):6d}")

print()
print(f"{'regime':<20s} {'human found':>12s} "
      f"{'style share':>11s} {'ratio':>5s}")
for name, axes in (("style with human", FULL), ("style with tool", HUMAN)):
    b = review(d, axes)
    style = sum(1 for k in d["defects"]
                if k["no"] in b and k["class"] == "style")
    print(f"{name:<20s} {len(b):12d} {style:11d} {style / len(b):5.3f}")
remaining = sorted({k["class"] for k in d["defects"]
                    if k["no"] in review(d, HUMAN)})
print("classes of human's finding while style is with tool: " + ", ".join(remaining))
total = review(d, HUMAN) | tool
missed = [k for k in d["defects"] if k["no"] not in total]
print(f"human plus tool: found {len(total)}, missed {len(missed)}, "
      f"no axis searches for "
      f"{sum(1 for k in missed if k['class'] == UNWRITTEN)}")
panel                            without tool found with tool: human tool  total missed
one reviewer                                     22               15    7     22      2
three reviewers, separate axes                   15               15    7     22      2
three reviewers, same axis                        6                6    7     13     11
five reviewers, five axes                        22               15    7     22      2

regime                human found style share ratio
style with human               22           7 0.318
style with tool                15           0 0.000
classes of human's finding while style is with tool: documentation, implementation, interface, test
human plus tool: found 22, missed 2, no axis searches for 2

When the Tool Changes the Total

The top table’s first and last rows say the same thing: 22 and 22. If all five axes were already covered by humans, the tool’s contribution to the total found is 0. The tool does not look anywhere no one was already looking.

The second row shows the reverse. Three reviewers covered four axes — interface, implementation, test, documentation — and found 15 without the tool. Once the style axis is handed to the tool, the total climbs to 22. No one was added to the panel or removed; the one axis that was not covered got covered, at a cost of 7 defects. A three-person panel got matched to a five-person panel’s number.

The third row repeats the same rule on the narrowest panel. Three reviewers were looking at the same axis and finding 6; the tool raises this to 13. Missed is still 11, and 9 of that comes from the three axes no human is looking at. The tool closes one axis; it does not close the others.

The pattern comes together in one sentence: the tool’s contribution equals the size of the axis the humans did not cover. This is the axis side of the course’s second claim — the tool behaves like a person too: what grows the number is not its presence, it is that the axis it covers had not been covered before.

When the tool’s contribution happens does not show in the table but changes the review. The tool runs the moment the change is submitted, and the seven defects it finds are closed before review even begins: no note gets written, no reply is expected. Even in rows where the total stays the same, the review’s subject matter shrinks, and the part that shrinks is exactly the part that required no judgment.

The last column carries the sixth class in all four rows. In the best case with the tool, missed is 2, and both are in the unwritten-requirement class. Automation does not raise the ceiling of found above 22. The tool looks at what was written, just like review; what was never written, it too cannot see.

Where Attention Shifts

The bottom table looks at the same handoff from the human’s side, and the numbers here change even in the rows where the total stayed fixed.

With style on the human, a single reviewer’s finding is 22 defects and 7 of that is in the style class; the ratio is 0.318. With style on the tool, the human’s finding drops to 15 and the style share is 0; the ratio is 0.000. The human’s finding is left with four classes: interface, documentation, implementation, test.

What changes is not the total, it is the content of the review. Before the handoff, about a third of a review’s findings are rule defects; after, it is zero. Every remaining finding comes from an axis requiring judgment, and what gets discussed in the review text shrinks in the same proportion: applying the rule is no longer up for discussion, because the text deciding it was written once and its application is now carried out on its own.

There is an honest limit here that needs to be stated. At this scale, the freed reading has no numeric return: the change is 12 chunks, attention is also 12 chunks, so the human’s reading was not being exhausted to begin with. Redirecting the attention freed from the style axis to another axis changes no number, because the other axes were already being read in full. For the freed attention’s counterpart to show, a single condition is required: what there is to read has to be larger than the attention budget. No such case has been built in this setup, and it is not this topic’s variable.

Two Assumptions Built in the Tool’s Favor

The measurement holds the tool stronger than it might be in reality at two points, and both affect how the result should be read.

The tool finds the entire style class. A formatter applies only the rules written for it; a style defect outside the rule set — a file layout that differs from the rest of the repository, an inconsistent abbreviation style — is invisible to it and stays with the human. The measurement has no such remainder; if it did, the “style share 0.000” row would have come out above zero.

The tool produces no false finding. When the rule set does not match the rest of the repository, the tool also reports spots that are not defects. These findings do not enter review, but they cost time and require the rule to be rewritten, and this cost is not included.

Both assumptions are set deliberately. The purpose is to show that even in the tool’s best case, the total stays at 22: what sets the ceiling is not the tool’s quality, it is the axis list itself.

Summary

  • The style axis looks at the code’s appearance and separates from the other four at one point: what determines its correctness is not a judgment but a writable rule. Choosing a name is not on this axis; the case convention of a name is.
  • A style discussion is two jobs: the decision itself is given once and written into a text, applying the decision is repeated on every change. What gets handed to the tool is the second.
  • The tool’s contribution to total found equals the axis humans did not cover: 0 if five axes are already covered, 15 to 22 on a three-reviewer panel, 6 to 13 on three reviewers on the same axis.
  • Automation does not raise the ceiling: missed in the tool’s best case is 2, and both are in the unwritten-requirement class. The tool too looks only at what was written.
  • The handoff changes the review’s content even where the total stays fixed: the human’s finding goes from 22 to 15, its style share from 0.318 to 0.000, leaving only the four axes requiring judgment.
  • At this scale, the freed attention’s numeric return is 0, because the change is not larger than the attention budget.

Next Step

This topic’s six lessons moved a single variable: the axis looked at. Raising axis count pushed found from 6 to 15 and then to 22; closing an axis cost exactly the size of its class; adding people changed nothing. All these measurements shared one silent assumption, and this lesson said it out loud: the change was always exactly the size of the attention budget, meaning what there was to read could be read.

The next topic lifts that assumption. The axis looked at is held fixed, and this time what there is to look at grows. The question is this: do the defects axis diversity earns stay in place once the change stops being fully readable, or does the found ratio collapse independent of the axes?

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close