Software Anti-Patterns & Design Pattern Misuse

Common software design anti-patterns, misuse of design patterns, code smells indicating trouble, and refactoring strategies to fix them.

  • JSON13,872 B
  • YAML10,480 B · −24%
  • TOON9,346 B · −33%

Common software anti-patterns and design-pattern misuse with aliases, symptoms, root cause, consequences, refactoring and related patterns: God Object, Singleton overuse, spaghetti code, golden hammer, premature optimization, copy-paste programming, lava flow and big ball of mud.

Use it when

  • You are reviewing code or architecture for design problems.
  • You need the vocabulary for a code-review comment.

Watch out for

  • Labeling code with an anti-pattern name is a judgment; explain the concrete problem it causes.
  • Some anti-patterns are rational short-term choices under deadline pressure.

The data

Anti patterns

NameAlso known asSymptomsRoot causeConsequencesRefactoringRelated patternsWhen genuinely neededPreventionExamplesHealthy approach
God ObjectBlob, Cosmic Know-It-All
  • Single class with thousands of lines
  • Class has more than 10-15 methods
  • Class references dozens of unrelated types
  • Every new feature touches this class first
Failure to decompose domain logic, premature optimization centralization, or gradual feature creep without refactoring.
  • Impossible to unit test effectively
  • Merge conflicts on every change
  • Single point of failure
  • Developer onboarding nightmare
Identify cohesive groups of methods → Extract Class for each group → Extract Interface for contracts → Use Facade pattern to simplify API if needed → Apply Dependency Injection to decoupleFacade (bad when used to wrap a God Object instead of fixing it)nullnullnullnull
Singleton Overuse (Singletonitis)null
  • Half the classes in project are Singletons
  • Global mutable state everywhere
  • Unit tests require complex setup or ordering
  • "Just make it a Singleton" is common team response
Convenience of global access mistaken for good design, misunderstanding of when shared state is truly needed.
  • Hidden coupling between seemingly unrelated code
  • Testing requires shared state cleanup between tests
  • Race conditions in multithreaded environments
  • Hard to swap implementations
Replace Singleton with Dependency Injection → Inject dependencies via constructor → For truly single-instance needs, use DI container's singleton scope → Avoid global state accessor patternnullLogging framework, configuration manager (immutable after load), hardware interface (OS has one instance), thread pool managernullnullnull
Spaghetti Codenull
  • Methods longer than 50 lines with nested control structures
  • GOTO or excessive break/continue usage
  • Global variables modified everywhere
  • No clear layer separation
  • Copy-paste code duplication
Lack of design, deadline pressure, insufficient refactoring, or working in a language without structured programming support.
  • Extreme maintenance cost
  • Bug introduction rate proportional to change size
  • Almost impossible to test
  • Developer attrition from frustration
Extract Method religiously (every 5-10 lines) → Replace Conditionals with Strategy Pattern → Introduce layered architecture → Remove global state → Add unit tests as safety net during refactoringnullnullEnforce cyclomatic complexity limits (CI gate: < 10 per method), mandatory code reviews, pair programming for complex featuresnullnull
Golden HammerLaw of Instrument ("If all you have is a hammer, everything looks like a nail")
  • Same technology/solution used for every problem
  • Forcing a pattern where it doesn't fit
  • Team dismisses alternatives without evaluation
  • Massive complexity from using wrong tool
Team comfort zone, resume-driven development, over-generalization of past success, lack of diverse technical exposure.
  • Over-engineered solutions for simple problems
  • Poor performance from inappropriate architecture
  • Hard to find/onboard developers for niche stack
Evaluate each problem independently → Document trade-off decisions → Use polyglot approach where justified → Invest in team technical diversitynullnullnullUsing microservices for a 3-page website, Event Sourcing for a CRUD app, Machine Learning when a simple rule sufficesnull
Premature Optimizationnull
  • Complex caching layers before performance is measured
  • Hand-rolled data structures when built-in works
  • Micro-optimizations in early development stages
  • "This might be slow" comments everywhere
Misapplication of "performance mindset", lack of profiling data, assumption-driven development.
  • Unnecessary code complexity
  • Introduces bugs in unmeasured code paths
  • Wasted development time (Pareto: 20% of code causes 80% of perf issues)
  • Harder to refactor later
Profile first, optimize second → Remove speculative complexity → Measure before/after → Apply Knuth's maxim: "Premature optimization is the root of all evil"nullnullnullnullDesign reasonable architecture upfront, implement simply, profile in production, optimize only measured bottlenecks
Copy-Paste Programmingnull
  • Identical code blocks in multiple locations
  • Bug fix applied in one place but not another
  • "Variations" of same function with minor changes
  • Codebase size grows faster than feature count
Deadline pressure, laziness, lack of refactoring culture, inadequate code review, absence of abstraction skills.
  • Bug fix multiplication (fix in N places)
  • Inconsistent behavior across duplicated blocks
  • Code review bloat
  • Technical debt snowball
Extract Method/Class for each duplicate → Parameterize variations → Template Method pattern for similar algorithms → Use code duplication detection tools (Simian, PMD-CPD)nullnullCI gate with duplication threshold, code review requirement, pair programming for complex logicnullnull
Lava Flownull
  • Dead code that no one understands
  • Commented-out code blocks
  • "TODO: remove this after testing" lasting months
  • Code paths that no longer execute but are maintained
  • "Don't touch that, it might break something"
Rapid prototyping without cleanup, developer turnover without knowledge transfer, fear of removing unknown code.
  • Increased maintenance burden
  • Confusion during debugging (which code actually runs?)
  • Binary size bloat
  • Dead code deceives readers about actual behavior
Systematically identify dead code via code coverage tools → Remove confirmed dead code → Add tests for live code → Use version control history as safety netnullnullRegular codebase cleanup sprints, enforce code coverage minimums, remove features entirely when deprecatednullnull
Big Ball of Mudnull
  • No clear architecture or layering
  • Every module depends on every other module
  • No separation of concerns
  • "Just import it directly" is standard practice
  • Change in one place breaks unrelated areas
Organic growth without architectural oversight, no refactoring, short-term thinking, "just make it work" culture.
  • Extreme fragility (butterfly effect bugs)
  • Cannot estimate feature development time
  • 100% regression testing needed for every change
  • Eventual rewrite (which will become another BBoM)
Strangler Fig pattern → Identify bounded contexts → Extract modules one by one → Define clear interfaces between modules → Add architectural tests to enforce boundariesnullnullArchitecture Decision Records (ADRs), architectural fitness functions, regular architecture reviews, CI-enforced module boundariesnullnull

Fields

The shape of this dataset, read from the data itself: every column, its type and a real value. Agents can use this to plan a query without fetching the whole document.

SectionFieldTypeExample
anti_patternsnamestringGod Object
anti_patternsalso_known_asstringBlob, Cosmic Know-It-All
anti_patternssymptomsarray[4 items]
anti_patternsroot_causestringFailure to decompose domain logic, premature op…
anti_patternsconsequencesarray[4 items]
anti_patternsrefactoringstringIdentify cohesive groups of methods → Extract C…
anti_patternsrelated_patternsstringFacade (bad when used to wrap a God Object inst…
anti_patternswhen_genuinely_neededstringLogging framework, configuration manager (immut…
anti_patternspreventionstringEnforce cyclomatic complexity limits (CI gate: …
anti_patternsexamplesstringUsing microservices for a 3-page website, Event…
anti_patternshealthy_approachstringDesign reasonable architecture upfront, impleme…

Fetch the same bytes

The static files contain the same reference rows as the API, with no API rate limit. Live metadata, such as view counts, may differ. Use the API for content negotiation; use the static files for a cacheable snapshot.

curl "https://yjtoon.yunusemrevurgun.com/api/dataset/design-pattern-anti-patterns?format=toon"
const res = await fetch(
  "https://yjtoon.yunusemrevurgun.com/static-data/dataset/design-pattern-anti-patterns.toon"
);
const toon = await res.text();

Rate limit: 120 requests per minute per IP, no key and no signup. API reference →

Topics

  • anti-patterns
  • code-smells
  • refactoring
  • software-design
  • bad-practices
  • technical-debt

Search the library

Search by a topic, title, or keyword.

Start with a collection

Browse all 205 datasets