skills/code-architecture-wrong-abstraction/SKILL.md
Guides when to abstract vs duplicate code. Use this skill when creating shared utilities, deciding between DRY/WET approaches, or refactoring existing abstractions.
npx skillsauth add Chris-Maskey/opencode-config code-architecture-wrong-abstractionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Prefer duplication over the wrong abstraction. Wait for patterns to emerge before abstracting.
Premature abstraction creates confusing, hard-to-maintain code. Duplication is far cheaper to fix than unwinding a wrong abstraction.
Don't abstract until code appears in at least 3 places. This provides enough context to identify genuine patterns vs coincidental similarities.
// ✅ Correct: Wait for the pattern to emerge
// First occurrence - just write it
const userTotal = items.reduce((sum, item) => sum + item.price, 0);
// Second occurrence - still duplicate
const cartTotal = products.reduce((sum, p) => sum + p.price, 0);
// Third occurrence - NOW consider abstraction
const calculateTotal = (items, priceKey = 'price') =>
items.reduce((sum, item) => sum + item[priceKey], 0);
This is how wrong abstractions evolve:
// 1️⃣ Developer A spots duplication and extracts it
function processData(data) {
return data.map(transform).filter(validate);
}
// 2️⃣ New requirement is "almost" compatible
function processData(data, options = {}) {
let result = data.map(options.customTransform || transform);
if (options.skipValidation) return result;
return result.filter(options.customValidate || validate);
}
// 3️⃣ More variations pile up...
function processData(data, options = {}) {
let result = data;
if (options.preProcess) result = options.preProcess(result);
result = result.map(options.customTransform || transform);
if (!options.skipValidation) {
result = result.filter(options.customValidate || validate);
}
if (options.postProcess) result = options.postProcess(result);
if (options.sort) result = result.sort(options.sortFn);
return options.limit ? result.slice(0, options.limit) : result;
}
// ❌ Now it's incomprehensible spaghetti
The fastest way forward is back:
// Before: One bloated function trying to do everything
processData(users, { customTransform: formatUser, skipValidation: true });
processData(orders, { sort: true, sortFn: byDate, limit: 10 });
// After: Inline and simplify each use case
const formattedUsers = users.map(formatUser);
const recentOrders = orders.sort(byDate).slice(0, 10);
// Later: If true patterns emerge, abstract properly
| Benefit | Hidden Cost | |---------|-------------| | Code reuse | Accidental coupling between unrelated modules | | Single source of truth | Layers of indirection obscure bugs | | DRY compliance | Organizational inertia makes refactoring painful |
Facades wrap complex subsystems behind a simple interface. They're useful but often become wrong abstractions when overused.
// ❌ Facade that becomes limiting
<Typography variant="body" size="sm">Hello</Typography>
// What if you need <small> or <mark>?
// Now you must extend the facade first:
<Typography variant="body" size="sm" as="small">Hello</Typography> // Added prop
<Typography variant="body" size="sm" as="mark">Hello</Typography> // Another prop
// ❌ Facade keeps growing with every edge case
type TypographyProps = {
variant: 'h1' | 'h2' | 'body' | 'caption';
size: 'sm' | 'md' | 'lg';
as?: 'p' | 'span' | 'small' | 'mark' | 'strong' | 'em'; // Growing...
weight?: 'normal' | 'bold';
color?: 'primary' | 'secondary' | 'muted';
// ... more props for every HTML text feature
};
// ✅ Good: Facade encapsulates complex logic
<DatePicker
value={date}
onChange={setDate}
minDate={today}
/>
// Hides: localization, calendar rendering, keyboard nav, accessibility
// ✅ Good: Facade enforces design system constraints
<Button variant="primary" size="md">Submit</Button>
// Ensures consistent styling, no arbitrary colors
// ✅ Sometimes native HTML is clearer
<small className="text-muted">Fine print</small>
<mark>Highlighted text</mark>
// vs forcing everything through a facade:
<Typography variant="small" highlight>...</Typography> // ❌ Overengineered
| Use Facade When | Skip Facade When | |-----------------|------------------| | Hiding complex logic (APIs, state) | Wrapping simple HTML elements | | Enforcing design constraints | One-off styling needs | | Team needs consistent patterns | Juniors need to learn the underlying tech | | Behavior is stable and well-defined | Requirements are still evolving |
If a junior must:
...the facade adds friction, not value. Sometimes ctrl+f and manual updates across files is simpler than maintaining a leaky abstraction.
| Approach | Meaning | When to Use | |----------|---------|-------------| | DRY | Don't Repeat Yourself | After patterns stabilize | | WET | Write Everything Twice | Default starting point | | AHA | Avoid Hasty Abstractions | Guiding principle |
tools
Anti-patterns and mistakes to avoid as a product manager. Use when evaluating leadership behaviors, improving team dynamics, reflecting on management practices, or onboarding new product managers.
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
testing
Design effective CTAs using visual attention and gaze psychology principles. Use when designing landing pages, button hierarchies, conversion elements, or optimizing user attention flow through interfaces.
tools
Run agent-browser + Chrome inside Vercel Sandbox microVMs for browser automation from any Vercel-deployed app. Use when the user needs browser automation in a Vercel app (Next.js, SvelteKit, Nuxt, Remix, Astro, etc.), wants to run headless Chrome without binary size limits, needs persistent browser sessions across commands, or wants ephemeral isolated browser environments. Triggers include "Vercel Sandbox browser", "microVM Chrome", "agent-browser in sandbox", "browser automation on Vercel", or any task requiring Chrome in a Vercel Sandbox.