What Your Code and Kids’ Drawings Have in Common

February 2, 2026

Most unreadable code isn’t broken. It works — but it’s tiring to understand.

You start reading a function to learn what it does. Halfway through, you’re reasoning about how it does it. Your brain keeps switching gears.

Kids make the same mistake when they draw people.

Kids drawing a person

A child draws a person with an enormous head and carefully counted fingers… but the body is vague or missing.

It’s one picture built from mismatched layers:

Some parts get intense detail. Other parts are barely sketched. The drawing represents one thing, but it’s assembled from incompatible zoom levels.

Code does this constantly.

BAD: mixed abstractions

function processOrder(order) {
  if (!order) throw new Error("Missing order");

  // business rule
  const total = order.items.reduce((sum, i) => sum + i.price, 0);

  // formatting detail
  const formattedDate = new Date().toISOString();

  // infrastructure concern
  try {
    http.post("/orders", { ...order, total, formattedDate });
  } catch {
    retryWithBackoff();
  }
}

This function is about processing an order — but it also worries about validation, formatting, networking, and retries. Each line makes sense; together they force the reader to constantly change mental mode.

GOOD: consistent abstraction

function processOrder(order) {
  const payload = prepareOrder(order);
  sendOrder(payload);
}

function prepareOrder(order) {
  // validation, totals, domain rules
}

function sendOrder(payload) {
  // HTTP, retries, timeouts
}

Now each function mostly speaks one “dialect.” You can understand the intent without being forced into the machinery.

How to spot mixed abstraction (fast)

You’re probably mixing layers when you see any of these:

1) “And then suddenly…” lines

While reading, you feel a gear shift: “Ok we’re processing an order… and then suddenly we’re constructing headers.” That “suddenly” is the smell.

2) Domain words and plumbing words in the same breath

Names from different worlds colliding:

When they’re interleaved, you’re doing two jobs at once.

3) Uneven detail

One part is very high-level (“process”, “sync”, “handle”), but another part is meticulous (“format ISO string”, “map status codes”, “loop indices”). That mismatch is exactly the kids-drawing problem: giant head, missing torso.

How to avoid it without ceremony

A) Do a “story pass” and a “mechanics pass”

Write (or refactor) in two passes:

You’re not adding abstraction — you’re relocating detail.

B) Create explicit boundaries

A simple, durable boundary is:

No architecture astronaut badge required.

C) Name functions by what they promise at their level

Good names act like a zoom lock:

Names that mix levels (processAndSendOrderWithRetries) are often confessions.

Good code improves the same way kids’ drawings do — not by adding detail, but by putting the right detail in the right place.