8 min read

Eye Training · Loops and Iteration

For every loop, check four things: where it starts, where it stops, what changes each time, and what's left over at the end.

Part 2 · Surface 21. Bug counts are hidden and some snippets are clean. See Start Here for how to use these drills.


J · The basics

Bug hunt
J · Sum the prices
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Email everyone
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Find the admin
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Skip comments
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Fetch every page
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Countdown
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

M · Three years in, these should jump out

Bug hunt
M · Remove expired items
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Insert in batches
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
M · Orders with customers
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Hide blocked users
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Index by id
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Retry three times
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

S · Where seniors stand out

Bug hunt
S · Drop expired sessions
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · Process the queue
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
S · Summarise a big file
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min

What your eye checks

Whenever you see a loop, ask:

  1. Bounds: does it start at the first item and stop at the last? <= against length and starting at length are the classics.
  2. What does the loop variable hold? for…in gives keys, for…of gives values, entries() gives both.
  3. Does every path move forward? A continue before the increment, or a variable that's never reassigned, means it never ends.
  4. Is the collection changed while iterating? splice in a forward loop skips items. (Map and Set deletion during for…of is safe.)
  5. What's left over after the loop? A last partial batch, a final buffered line.
  6. Does return or break do what's intended? Not inside forEach.
  7. Is there I/O inside the loop? One query per item is N+1; sequential awaits multiply latency.
  8. What's the cost per pass? includes, find or spread inside a loop makes it quadratic.
  9. How long does it run without yielding? A big synchronous loop in a server blocks every other request.
  10. Can one item stop the whole loop? Retries without a limit, failures without a dead-letter path.

Tells

You seeAsk
i <= arr.length / i = arr.lengthOne too far?
for (const x in array)Keys or values?
return inside forEachWho receives it?
continue in a whileWas the counter updated first?
while (x.cond) where x is constDoes it ever change?
splice(i, 1) in a forward loopWhat gets skipped?
A batch flushed at a size limitWhat about the rest?
await + query inside forN+1?
.includes( / .find( inside .filter(Quadratic?
{ ...acc, …} in reduceQuadratic?
A failure path that doesn't advancePoison message?
A loop over millions in a request handlerWho else is waiting?

Go deeper