R1.17.1generic names attracting extra dutiesdesign

The more generic a component's name, the easier it is to dump unrelated duties into it

Aliases: catch-all component · dumping ground · Card dumping

What it is

A component’s name is an invitation stating what may come in. Components called Card, Item, Box, Common, Widget have almost no refusal: a list row, a marketing tile, a settings group, an empty-state illustration — all look like “a card”, so all walk into the same door. Generic names attracting extra duties is not the author wanting a kitchen sink; the name never declared a boundary, so callers use the widest literal reading. The less specific the name, the more likely it becomes a junk drawer.

A duty is a set of behaviours and constraints, not whether it looks similar. A settings group has its own heading rank and collapse keyboard; a marketing tile has a media ratio and a whole-tile hit target. Both “look like cards” and must not share a name that cannot refuse either.

Why it happens

People search the name at the call site, then read the interface. Card stops the search because the word covers the rectangle in front of them. If the interface has no signal “I am not X”, new duties grow in as props or slots: first clickable, then collapsible, then mediaRatio. Each addition has a real product reason; the name never narrowed, so reasons can stack without limit. The implementation becomes a union of patterns that do not know each other, and each pattern’s constraints (keyboard, empty state, density) dilute in the union.

A specific name blocks: SettingsGroup will not be fetched for a home-page promo. The block is a feature — it keeps guests not on the invitation outside. A generic name pushes the blocking onto the caller’s self-control; self-control fails under schedule pressure, and the junk drawer forms.

Where it stops holding

Real layout primitives (stack, grid, divider) are generic on purpose; their duty is layout, not business. A more specific name would invite business into them. Experimental local components used in one file, not in the library, have their short-name harm stopped by the file boundary. Decorative brand shells that explicitly say “no behaviour, no state” may keep a generic name if behaviour entry points are refused by types. Renaming alone will not cure duties already grown in — after the name narrows, old duties remain and must be moved to the component they belong in, not just rebadged.

Applying it

  • Every library name must read as a refusal: after the name, one can name at least two things “this does not handle”. If that list is empty, rename before talking interface.
  • When a new need arrives, ask first whether the existing name already refuses it. Refused → new component; not refused → props may be added. “It is a rectangle anyway” is not a reason to join Card.
  • Audit call sites of Card / Item / Box / Common and cluster by task. Two or more incompatible keyboards or empty states under one name: split, and give each half a specific name.
  • How to check: send the component name to someone who has not read the implementation; ask them to list “what I would use it for” and “what I must not”. An empty second list means the name is attracting duties. Then sample ten call sites and count how many open mutually exclusive behaviours with switches — each exclusive pair is a duty the name should have blocked and did not.

Related

  • Same group: R1.17.2 Extra indirection added for reuse raises the cost of understanding · R1.17.3 Inline duplication is sometimes cheaper than the wrong abstraction
  • Adjacent: R1.08 Premature abstraction · R1.02 Component library and variants
  • Search terms: generic names attracting extra duties · catch-all component · component naming

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/R1.17.1