skip to content

A module exposes both a right-to-left compose and a left-to-right pipe, and one photo chain watermarks before it resizes - how do you find and prevent that mistake?

level: seniorimportance: should knowfreq 40%

answer

  1. silent, not broken
  2. uniform shapes fit any ordering
  3. assert the image, not the wiring
  4. direction belongs in the helper name
  5. one direction per codebase

basics

~20 s

Find it by asserting the chain's observable output, not its wiring: a listing written for one helper and passed to the other runs backwards while every join still fits. Prevent it by keeping one direction per codebase and naming the helper after its direction.

solid answer

~40 s

The mistake is a listing authored for one convention handed to the other. When every stage is photo to photo, all joins still fit, so nothing rejects it - the chain simply runs backwards and produces an oversized watermark on a shrunken image. Detection has to be behavioural: a test that asserts a property of the finished photo, such as the mark's size relative to the image, fails, while any test of the wiring passes. Prevention is convention work: one direction per codebase, the other helper unexported or renamed so the direction is in the name, and stage shapes chosen so that at least one join would break if the order reversed.

code

pseudocode · 7 lines
pseudocode
// all three stages: photo -> photo
intended = compose(reduceQuality, watermark, resize)  // right to left
shipped  = pipe(reduceQuality, watermark, resize)     // left to right

// intended: resize -> watermark -> reduceQuality
// shipped:  reduceQuality -> watermark -> resize
// every join fits in both; only the stored image differs

go deeper

for a junior

Recall that passing a listing to a helper of the other direction runs the chain backwards, and that nothing necessarily complains when every stage takes and returns the same shape.

for a middle

Explain why the joins all still fit, and what the reversed chain actually produces - a watermark sized for the wrong image - so you can recognise the symptom from the output.

for a senior

Show the investigation: assert an observable property of the finished image, record what each stage received on one upload, and only then read the wiring. Then name the convention change that removes the class.

for a principal

Decide how much of this you solve by convention and naming versus by shaping stages so wrong orderings cannot be expressed, and be explicit about the adapter cost that second choice imposes.

This is the failure the two-direction world actually produces. Someone writes a listing in the order they think in, reaches for whichever helper is imported, and ships a chain that runs backwards. Note the shapes here differ from a chain that ends in stored bytes: all three stages are photo to photo - `resize`, `watermark` and `reduceQuality` - which is what makes the bug silent. ## Why it hides - **Every join still fits.** Photo meets photo at each hop, in any order, so no shape check has anything to complain about. - **Nothing throws.** Each stage does its job on whatever photo it is handed; a watermark applied to a full-size original is a perfectly valid operation. - **The wiring line looks right.** The listing reads in the intended order for the convention its author had in mind; only the helper it was passed to is wrong. - **The damage is visual.** The stored image has a watermark sized for the original and then shrunk, or a mark applied after quality reduction. Nobody notices until someone looks at an image. When the end shapes differ - a chain that ends by producing stored bytes - the reversed listing does not build at all, because a stage that takes a photo is handed bytes. Uniform shapes remove that protection entirely. ## Finding it 1. **Assert the output, not the wiring.** One test that runs the real chain on a known image and asserts an observable property - the mark occupies roughly the expected fraction of the final image, or the final dimensions are the target ones - fails immediately on a reversal. A test that only checks that three stages were composed passes either way. 2. **Read the helper, then the first argument.** In review, resolve the helper's direction first, then ask one question of the listing: *does this stage see the raw input?* One question, answered at the call site, catches the whole class. 3. **Instrument once.** If the chain is already in production and the images look subtly wrong, log the input dimensions each stage receives for a single upload. A stage that reports the original dimensions when it should have reported the resized ones names the defect without any code reading. ## Preventing it | Measure | What it buys | What it costs | |---|---|---| | One direction per codebase | The class of bug disappears; no listing can be handed to the wrong helper | A migration, and friction for people used to the other convention | | Direction in the helper's name | Reviewers resolve direction without leaving the line | Nothing, beyond agreeing on the names | | Distinct shapes at the chain's ends | A reversed listing is rejected outright at a join | Adapters where shapes would otherwise have been uniform | | One behavioural test per chain | Catches reversal, and every other wiring error, on the build | A test to maintain per chain | The first two are worth more than they look. "Direction in the name" means the helper is not called something neutral that each reader interprets by habit; a name built on **after** versus a name built on **then** carries the convention into every call site, so the reviewer does not have to remember which of two similarly named helpers this module exported. ## What not to rely on - **A comment above the helper.** It is read once, by the person who wrote it. - **Careful review alone.** The listing looks correct in isolation; that is the definition of this bug. - **The absence of errors.** A silent chain is exactly what a reversed uniform-shaped chain produces. - **Stage count checks.** The same three stages are present in both the correct and the reversed chain. ## What an interviewer is listening for Three beats, in order: **why the shapes do not catch it** (uniform stages satisfy every ordering), **what does catch it** (an assertion about the chain's observable result), and **what removes the class** (one direction, named, per codebase). A candidate who reaches only for "review more carefully" has not understood why the listing looked fine to the author. A candidate who claims a reversed chain would fail to build has generalised from chains whose end shapes happen to differ, and should be asked what happens when every stage returns the shape it took.

  • Would the same mistake in a chain that ends by producing stored bytes also be silent?
    No. There a stage produces bytes while its neighbours accept only photos, so the reversed listing breaks a join and is rejected rather than shipped. That contrast is the useful lesson: the shapes protect you exactly as far as they differ, and a chain of uniformly shaped stages gets no protection at all.
  • The chain is already live and images look subtly wrong - what is your first move?
    Reproduce with one known image and record what each stage receives, or run the two candidate orderings on it side by side. The reversed order announces itself immediately - a mark sized for the original, or applied after quality reduction. Only then go back to the listing, because the wiring line will look correct until you know which helper it was handed to.
  • Is renaming the helpers enough on its own?
    It removes the ambiguity at the call site, which is most of the value, but it does not stop someone from writing a listing in one order and choosing the other helper deliberately. Pair it with a behavioural test on each chain, and the reversal has to survive both a reader and the build.

saying these in an interview costs you the question

  • Assumes a reversed chain always fails to build
  • Blames the stage that looked wrong rather than the listing
  • Says same-typed stages protect a chain from a wrong direction
  • Thinks a comment on the helper prevents the mistake
  • Relies on reviewers spotting the reversal by eye
  • Tests that the stages were composed rather than the result