Skip to content

Code Quality Antipatterns Overview

Code quality antipatterns don’t cause immediate failures but make the codebase:

  • Hard to understand - New developers can’t figure out what’s happening
  • Hard to change - Simple modifications break unexpected things
  • Hard to test - Code has too many hidden dependencies
  • Hard to debug - Problems are obscured by complex patterns

Monkey Patching

Modifying built-in prototypes and global objects at runtime

Magic Numbers

Unexplained numeric literals scattered throughout code

Callback Hell

Deeply nested callbacks and mixed async patterns

God Middleware

Single middleware handling too many responsibilities

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Technical Debt Growth β”‚
β”‚ β”‚
β”‚ Time to add features β”‚
β”‚ β”‚ β”‚
β”‚ β”‚ β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ β”‚ β•±β•±β•±β•± β”‚
β”‚ └───────────────────────────────────────────────── β”‚
β”‚ Codebase age β†’ β”‚
β”‚ β”‚
β”‚ Without refactoring, every new feature takes longer β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
// Bad: Clever one-liner
const r = a.reduce((p, c) => (p[c.t] = (p[c.t] || 0) + c.v, p), {})
// Good: Readable logic
const totals = {}
for (const item of items) {
const type = item.type
totals[type] = (totals[type] || 0) + item.value
}
// Bad: Magic behavior
const user = getUser() // What if it returns null? Throws? Caches?
// Good: Explicit contract
const user = await userService.findById(id)
if (!user) {
throw new NotFoundError(`User ${id} not found`)
}
// Bad: Function does everything
function processOrder(order, user, inventory, payment, email) {
// 500 lines of mixed concerns
}
// Good: Focused functions
function validateOrder(order) { /* ... */ }
function checkInventory(items) { /* ... */ }
function processPayment(payment) { /* ... */ }
function sendConfirmation(email, order) { /* ... */ }
// Bad: Continue with bad data
function processUser(user) {
const name = user?.name || 'Unknown'
const email = user?.email || ''
// Silently continues with garbage data
}
// Good: Validate early
function processUser(user) {
if (!user) throw new Error('User is required')
if (!user.name) throw new Error('User name is required')
if (!user.email) throw new Error('User email is required')
// Now we know we have valid data
}

MetricHealthyWarningCritical
File lines< 200200-500> 500
Function lines< 3030-60> 60
Cyclomatic complexity< 1010-20> 20
Nesting depth< 33-5> 5
Parameters< 44-6> 6