Skip to content

Lazy Class

The code smell in which a class (or function, module, package) carries too little responsibility to justify the overhead it imposes — the defect living in the economy, not the behaviour, so a correct, clearly-named boundary can still be flagged when its carried value fails to clear its enumerable tax.

Core Idea

Lazy class is the code smell in which a component — typically a class, but the diagnosis extends to functions, modules, and packages — exists while carrying too little responsibility to justify its overhead. Every abstraction has a cost: a name to learn, a file to navigate, an interface to keep stable, a test surface. When earned value (complexity hidden, reuse enabled, a concept named, a contract enforced) falls below that overhead, the boundary is anti-economical. The canonical fix is to inline it and delete it.

How would you explain it like I'm…

The One-Crayon Box

Imagine a toy box that holds just one crayon, and you have to open it every time you want to draw. It's easier to just keep the crayon with your other crayons. A lazy class is a part of a computer program like that box: it does so little that it's more trouble than it's worth.

The Do-Almost-Nothing Piece

Programmers split code into pieces, and each piece has a name people must learn and a place they must go to find it. That's worth it when the piece does real work, like hiding something tricky or being used in many places. A lazy class is a piece that does almost nothing, like just passing a job along to someone else. It isn't broken, but it costs more to keep than it helps. The fix is to fold it back into the code that uses it and delete it.

Underworked Abstraction Smell

A lazy class is a code smell: a class, function or module that carries too little responsibility to justify its overhead. Every abstraction costs something — a name to remember, a file to open, an interface to keep stable, tests to maintain. It earns that cost by hiding complexity, being reused, naming a real concept, or enforcing a boundary. A wrapper that just forwards calls, or a helper used once for a single line, doesn't. It is the opposite of a god class, which does too much; healthy code sits in between. The usual fix is to inline it into its caller.

 

Lazy class is the code smell in which a component — usually a class, but also a function, module or package — exists while carrying too little responsibility to pay for its overhead. Abstractions impose costs: naming, navigation, onboarding vocabulary, interface stability and test surface. They are justified by real work such as encapsulating complexity, enabling reuse across callers, naming a domain concept, or enforcing a contract that limits coupling. The diagnostic is the ratio of responsibility to overhead, not correctness or naming: a forwarding wrapper, a behavior-less data class, or a single-use one-line utility are lazy because inlining them would be cheaper. Martin Fowler catalogued it in Refactoring (1999), with inline class or inline function as the canonical remedy. It is the low-end complement of god class. It often arises from speculative generality — anticipated variation that never came — and survives through inertia.

Scope of Application

Lazy class lives across the code-quality and maintainability subfields of software, recurring at every construct level a codebase exposes.

  • Object-oriented code — wrapper classes forwarding to one implementation; data classes with no behaviour.
  • Functional and procedural code — the inline-function twin: a one-line helper used by one caller.
  • Module and package structure — a single-function module or a package holding one constant.
  • Public-API and plugin surfaces — where the hidden-currency exception lives: a thin boundary kept because an external contract pays its overhead.

Clarity

Naming lazy class makes legible a cost the prevailing instinct treats as zero: abstraction has a price that must be earned. It decouples the defect from the question reviewers usually ask — a lazy class can be perfectly correct and clearly named and still be a defect, because the flaw is in its economy. It also gives abstraction-sizing two poles instead of one: lazy class at the low end, god class at the high end, with a healthy abstraction occupying the middle band of responsibility.

Manages Complexity

Judging whether each small component earns its place is otherwise an open, criterion-less debate, so reviewers reach for correctness and naming, which a thin abstraction can satisfy while still being a defect. Lazy class compresses that to one quantity: the ratio of responsibility carried to overhead imposed. It then gives the problem a single axis with two poles, so placing a component reads off a short decided menu — inline, merge with a sibling, grow deliberately, or keep for an external constraint — rather than relitigating each case.

Abstract Reasoning

The smell licenses a diagnostic on economy, not correctness — inferring whether carried responsibility clears the enumerable tax and flagging a defect even when the code works and reads fine. Its boundary-drawing move places a component on the single responsibility axis (lazy versus god class) to select its fix, and discriminates lazy class from its neighbours (lava flow, speculative generality) by mechanism. Its interventionist move defaults to inlining but requires a hidden-currency check — a stable API, plugin seam, or versioning boundary paying overhead in an invisible currency.

Knowledge Transfer

Within software the smell transfers as mechanism across all code-quality work and every construct level — class, function, module, package are one diagnosis at different granularities, with the responsibility axis, fix menu, and hidden-currency exception carrying intact; the vocabulary (Fowler's inline-class, code smells, responsibility-driven design) is software-internal but fully portable. Beyond software the general balance recurs — ceremonial offices, redundant statutory clauses, thin curriculum units — but "lazy class" does not transport: the diagnosis lands under parent primes Abstraction, parsimony, and Minimalism, while the named smell stays software's version of the balance.

Relationships to Other Abstractions

Local relationship map for Lazy ClassParents appear above the current abstraction, mutual partners to the right, and children below. Node labels state whether each abstraction is prime or domain-specific; colors identify relation types.Lazy ClassDOMAINPrime abstraction: Economies of Scale — is a decomposition ofEconomiesof ScalePRIMEDomain-specific abstraction: Code Smell — is a kind ofCode SmellDOMAIN

Current abstraction Lazy Class Domain-specific

Parents (2) — outgoing typed relations

  • Lazy Class is a kind of Code Smell Domain-specific

    Lazy Class is the code-smell species whose low responsibility-to-overhead ratio suggests that an abstraction boundary has not earned its maintenance cost.

  • Lazy Class is a decomposition of Economies of Scale Prime

    Lazy class is the software-boundary case in which fixed abstraction overhead is spread over too little carried responsibility to reach an efficient scale.

Hierarchy paths (6) — routes to 6 parentless roots

Neighborhood in Abstraction Space

Lazy Class sits in a moderately populated region (55th percentile for distinctiveness): it has near-neighbors but no dense thicket of look-alikes.

Family — Software Evolution Laws & Code Smells (17 abstractions)

Nearest neighbors

Computed from structural-signature embeddings · 2026-10-25