🎯

code-architecture-wrong-abstraction

🎯Skill

from flpbalada/my-opencode-config

VibeIndex|
What it does

Identifies when to avoid premature code abstraction by providing guidelines for creating clean, maintainable shared utilities and refactoring strategies.

πŸ“¦

Part of

flpbalada/my-opencode-config(40 items)

code-architecture-wrong-abstraction

Installation

πŸ“‹ No install commands found in docs. Showing default command. Check GitHub for actual instructions.
Quick InstallInstall with npx
npx skills add flpbalada/my-opencode-config --skill code-architecture-wrong-abstraction
1Installs
-
AddedFeb 4, 2026

Skill Details

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.

Overview

# Code Architecture: Avoiding Wrong Abstractions

Core Principle

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.

The Rule of Three

Don't abstract until code appears in at least 3 places. This provides enough context to identify genuine patterns vs coincidental similarities.

```jsx

// βœ… 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);

```

When to Abstract

βœ… Abstract When

  • Same code appears in 3+ places
  • Pattern has stabilized (requirements are clear)
  • Abstraction simplifies understanding
  • Use cases share identical behavior, not just similar structure

❌ Don't Abstract When

  • Code only appears in 1-2 places
  • Requirements are still evolving
  • Use cases need different behaviors (even if structure looks similar)
  • Abstraction would require parameters/conditionals for variations

The Wrong Abstraction Pattern

This is how wrong abstractions evolve:

```jsx

// 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

```

How to Fix Wrong Abstractions

The fastest way forward is back:

  1. Inline the abstraction back into each caller
  2. Delete the portions each caller doesn't need
  3. Accept temporary duplication for clarity
  4. Re-extract proper abstractions based on current understanding

```jsx

// 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

```

Hidden Costs of Abstraction

| 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 |

Facade Pattern: When It Becomes a Wrong Abstraction

Facades wrap complex subsystems behind a simple interface. They're useful but often become wrong abstractions when overused.

The Typography Component Trap

```tsx

// ❌ Facade that becomes limiting

Hello

// What if you need or ?

// Now you must extend the facade first:

Hello // Added prop

Hello // 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

};

```

When Facade Works

```tsx

// βœ… Good: Facade encapsulates complex logic

value={date}

onChange={setDate}

minDate={today}

/>

// Hides: localization, calendar rendering, keyboard nav, accessibility

// βœ… Good: Facade enforces design system constraints

// Ensures consistent styling, no arbitrary colors

```

When to Skip the Facade

```tsx

// βœ… Sometimes native HTML is clearer

Fine print

Highlighted text

// vs forcing everything through a facade:

... // ❌ Overengineered

```

Facade Trade-offs

| 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 |

The Junior Developer Test

If a junior must:

  1. Learn the facade API
  2. Then learn the underlying technology anyway
  3. Then extend the facade for edge cases

...the facade adds friction, not value. Sometimes ctrl+f and manual updates across files is simpler than maintaining a leaky abstraction.

Quick Reference

DO

  • Wait for 3+ occurrences before abstracting
  • Let patterns emerge naturally
  • Optimize for changeability, not DRY compliance
  • Test concrete features, not abstractions
  • Inline bad abstractions and start fresh

DON'T

  • Abstract based on structural similarity alone
  • Add parameters/conditionals to force fit new use cases
  • Preserve abstractions due to sunk cost fallacy
  • Fear temporary duplication

Key Philosophies

| 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 |

References

  • [The Wrong Abstraction - Sandi Metz](https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction)
  • [The Wet Codebase - Dan Abramov](https://www.deconstructconf.com/2019/dan-abramov-the-wet-codebase)
  • [AHA Programming - Kent C. Dodds](https://kentcdodds.com/blog/aha-programming)

More from this repository10

🎯
five-whys🎯Skill

Systematically uncovers root causes of problems through iterative questioning, revealing underlying issues beyond surface-level symptoms.

🎯
social-proof-psychology🎯Skill

Optimizes user trust and conversion by strategically displaying social validation through testimonials, user stats, and expert endorsements.

🎯
cognitive-fluency-psychology🎯Skill

Enhances user comprehension and engagement by applying cognitive fluency principles to simplify information processing across content and interfaces.

🎯
hooked-model🎯Skill

Designs habit-forming products by mapping user triggers, actions, rewards, and investments to create engaging, addictive product experiences.

🎯
cognitive-biases🎯Skill

Applies cognitive bias insights to optimize product design, user experiences, and decision-making strategies by leveraging psychological principles.

🎯
typescript-satisfies-operator🎯Skill

Validates TypeScript object types while preserving precise literal types, preventing type widening and catching type-related errors early.

🎯
typescript-best-practices🎯Skill

Enforces TypeScript best practices and coding standards through comprehensive linting and configuration rules for consistent, high-quality code.

🎯
status-quo-bias🎯Skill

Helps design product changes and migrations by understanding users' psychological resistance to change and creating strategies to overcome status quo bias.

🎯
kanban🎯Skill

Visualize and optimize team workflow by creating Kanban boards that track tasks, limit work-in-progress, and improve delivery efficiency.

🎯
theme-epic-story🎯Skill

I apologize, but I cannot generate a description without seeing the actual content or context of the "theme-epic-story" skill from the repository. Could you provide more details about what this spe...