Skip to content
C.W.K.
Stream
Lesson 02 of 05 · published

What It Cost to Give Up the Sliders

~13 min · migration, trade-offs, product, judgment

Level 0Loose Parts
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

The Choice: Grow a Seam or Accept the Loss

The shared panel persists its own geometry — mode, width, height — in browser local storage under a key prefix the app supplies. One converting app kept those values in its own settings store instead, and had exposed them: a mode picker and two size sliders, live in its settings popover.

Two options. Grow a persistence seam in the shared component so an app can supply its own storage backend, or accept the shared persistence and delete the controls.

The decision was to accept the loss. Three settings controls were deleted, along with the state fields and types behind them. The reasoning: the other apps live without those sliders, and edge-drag resize already does the job — so the controls were solving a problem the shared component solves differently rather than a problem it fails to solve.

Why Refusing the Seam Was the Cheaper Answer

A persistence seam sounds harmless. In practice it is a permanent widening of the contract: every consumer now has a storage strategy to choose or default, the shared component has two code paths to maintain and test, and the next feature touching persistence has to work in both. That cost is paid forever, by everyone, in exchange for one app keeping three controls.

And here is the part that made the decision look right in hindsight: the same question came up in all three conversions that followed, and cost nothing in any of them. Each of those apps also kept geometry in its own state — but none had exposed it to a user. Accepting shared persistence was invisible to them.

Had the seam been added for the first app, it would have been carried by four consumers to serve one, and the three later conversions would have quietly proved it unnecessary — after it was already load-bearing.

Price a proposed seam against all consumers, not against the one asking for it. The consumer in front of you has a concrete need and a name; the future consumers who will carry the seam are abstract and silent. That asymmetry makes every individual seam look worth it. The check is to ask what the next three conversions would do with it — and if the honest answer is 'nothing', the seam is being added for one app at everyone's expense.

Ask What Has Shipped, Not What Is Stored

The distinction that made the cost real in exactly one place is worth extracting. All four apps stored panel geometry. Only one had built an interface for it. The internal state was identical; the user-visible commitment was not.

When pricing a conversion, the question is not what an app holds but what it has promised. Internal state can be moved silently. A control somebody has used cannot, and that is where the actual cost lives — which means the pricing question is "what has this app shipped that a user could notice disappearing", not "what does this app store".

Code

The seam that was refused, and what refusing it cost·typescript
// THE SEAM THAT WAS PROPOSED - reasonable-looking, and permanent.
// Every consumer would now choose or default a storage strategy,
// and the shared component would carry two paths forever.
type PanelProps = {
  storage?: {                        // <- REFUSED
    get(key: string): string | null;
    set(key: string, value: string): void;
  };
};

// WHAT SHIPPED INSTEAD: one storage strategy, app-supplied prefix.
function usePanelGeometry(prefix: string) {
  const key = `${prefix}.panel`;
  const [geometry, setGeometry] = useState(() =>
    JSON.parse(localStorage.getItem(key) ?? "null") ?? DEFAULTS
  );
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(geometry));
  }, [key, geometry]);
  return [geometry, setGeometry] as const;
}


// WHAT THE CONVERTING APP DELETED - the actual invoice line:
//
//   - <ModePicker  value={pippaPanelMode}  onChange={...} />
//   - <SizeSlider  label="Width"  value={pippaPanelWidthPx}  ... />
//   - <SizeSlider  label="Height" value={pippaPanelHeightPx} ... />
//   - pippaPanelMode / WidthPx / HeightPx  from the settings store
//   - the three setters and their types
//
// The next three conversions asked the SAME question and deleted
// NOTHING, because none of them had ever rendered these controls.
// Their geometry was internal state, and internal state moves
// silently.


// THE PRICING QUESTION, which is not the one people ask:
//
//   not  "what does this app STORE?"        (all four: geometry)
//   but  "what has this app SHIPPED that a  (one of four: sliders)
//         user could notice disappearing?"

External links

Exercise

Find a configuration option in a shared component you maintain that exists because one consumer asked for it. Check how many consumers actually pass a non-default value. If the answer is one or zero, write down what removing it would cost that consumer — and what carrying it costs everyone else in code paths and test cases.
Hint
Count the test cases, not the lines of code. An option with two meaningful values doubles the state space of everything downstream of it, and that multiplication is where the real ongoing cost lives — not in the branch itself.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.