skip to content

What does file and function length tell you about a codebase, and why do experienced engineers treat a growing file as a design signal rather than a formatting problem?

level: seniorimportance: should knowfreq 40%

answer

  1. Length = proxy for cohesion, not the goal
  2. Layout rules assume small files
  3. Banner comments & regions = compensation smell
  4. Split by responsibility, not at the line limit
  5. Hard limits get gamed → warn + baseline ratchet

basics

~20 s

Small files are easier to understand than large ones. A file that keeps growing usually means it has taken on several responsibilities, so the fix is splitting it up — not adding more comments, headers, or blank lines.

solid answer

~60 s

Length is a **proxy metric**: it correlates with, but does not define, the real property — how many distinct responsibilities a unit holds. Empirically, well-regarded codebases skew toward files of roughly 100–500 lines and functions well under a screen, because a unit you can hold entirely in working memory is one you can reason about without scrolling or note-taking. Why length is a design signal: the layout heuristics that make code readable all *degrade with size*. The newspaper metaphor needs a lead paragraph that fits on the first screen. Vertical distance needs caller and callee visible together. Blank-line grouping needs few enough groups to perceive at a glance. Past a few hundred lines, none of these help, and teams start compensating with banner comments, section headers, and extra spacing — which is treating a cohesion problem as a typography problem. The correct response is extraction: pull cohesive groups into their own functions, classes, or modules. Caveats: length limits enforced as hard CI failures encourage gaming (artificial splits, dumping-ground helper files), so most teams treat them as warnings or review prompts rather than gates.

go deeper

for a junior

Say small files and short functions are easier to understand, and that a file that keeps growing should probably be split rather than commented into sections.

for a middle

Connect length to the layout rules it undermines (newspaper ordering, vertical distance) and name the compensation smells: banner comments, regions, table-of-contents comments.

for a senior

Reframe length as a proxy for cohesion, insist on splitting by responsibility rather than at a line count, and discuss baseline/ratchet enforcement instead of hard gates.

for a principal

Talk about metric incentives explicitly (Goodhart: hard limits get gamed into helper dumping grounds), define legitimate exemptions, and use the number as a review prompt to ask how many reasons the unit has to change.

### Length as a proxy, not a goal Nobody actually cares about line counts. What they care about is **how much a reader must hold in their head to understand a unit of code**. Length is the cheapest available proxy for that, which is why it appears in every style guide despite being crude. The underlying property is **cohesion**: how tightly the parts of a unit belong together. A 400-line class where every method uses every field is more comprehensible than a 150-line class that is secretly three unrelated helpers sharing a file. Length flags candidates; cohesion decides. ### The empirical shape Martin's observation in *Clean Code* — supported by informal surveys of well-regarded projects — is that many admired systems are built from files in the low hundreds of lines, with a long tail of much smaller ones and very few giants. Functions trend far smaller still: a screenful (20–40 lines) is a common upper comfort bound, with many functions at 3–10 lines. These are *distributions*, not limits; the interesting signal is a codebase whose distribution has a fat tail of 1,000+ line files. ### Why length is specifically a *formatting-adjacent* topic Every layout heuristic in this area has an implicit size assumption baked in: - **Newspaper metaphor** — 'the top of the file gives the big picture' presupposes the top of the file is a meaningful fraction of it. In a 3,000-line file, the first screen is 1% of the content and summarizes nothing. - **Vertical distance** — 'callee close below caller' presupposes both fit on a screen. In a huge function, the declaration of a variable and its use are unavoidably far apart. - **Vertical openness/density** — blank-line grouping works when you can perceive a handful of groups. Thirty stanzas are not a structure; they are a wall. - **Conceptual affinity** — 'put related things near each other' becomes vacuous when everything is nominally in the same file but hundreds of lines apart. So size is not a separate topic bolted on; it is the **precondition** that makes the other rules effective. ### The compensation anti-patterns When a file grows past comprehensibility, teams reach for typographic fixes: - **Banner comments** — a line like `//====== VALIDATION ======` dividing a class into sections. Each banner names a responsibility that wants to be its own class. - **Regions/folding** (region markers in some languages, editor folding) — hides size rather than reducing it, and the hidden code stops getting read or reviewed. - **Extra blank lines and indentation gymnastics** — makes the wall taller, not shorter. - **A table-of-contents comment at the top** — an admission that the file needs an index, which files do not need when they are small. Each of these is a legible signal in code review: *the author felt the need to navigate their own file.* ### The correct responses 1. **Extract function** — a blank-line-delimited stanza with a comment above it is almost always a function; the comment becomes the name. 2. **Extract class/module** — a cluster of fields used only by a cluster of methods is a class trying to escape (this is exactly what low cohesion looks like structurally). 3. **Split by responsibility, not by size.** Cutting a 900-line file into three 300-line files at arbitrary boundaries produces three files with mutual dependencies and no conceptual identity — worse than the original, because now the coupling is across file boundaries and invisible. 4. **Accept legitimate large files.** Generated code, large exhaustive switch/mapping tables, data fixtures, and some parsers or state machines are genuinely long and genuinely cohesive. Blanket rules should exempt generated directories. ### Enforcement trade-offs Linters can measure length (rules named along the lines of `max-lines`, `max-lines-per-function`, `LongMethod`, `LargeClass`, `FileLength` across ecosystems). Considerations: - **Hard CI failure invites gaming.** Developers split at the line limit rather than at the responsibility boundary, or create catch-all 'helper' dumping grounds — the metric improves while cohesion worsens. Goodhart's law in miniature. - **Warnings plus a baseline** works better on legacy code: baseline existing violations so the build stays green, then fail only on *new* or *worsening* ones (a ratchet). Most tools support baseline files for exactly this. - **Review prompts are the highest-value use.** 'This file is now 800 lines — is it still one thing?' is a better intervention than an automated rejection, because a human can tell a cohesive parser from an incoherent god class and a linter cannot. ### How to answer the underlying question in an interview The distinguishing move is refusing the framing that length is the problem. Length is evidence. The question to ask about any long unit is: *how many reasons does this have to change?* If more than one, split along those reasons; if exactly one, the length may be fine and a hard limit would be actively harmful.

  • Should a team enforce a maximum file length as a build failure?
    Usually not as a hard gate. Length is a proxy for cohesion, and hard limits get gamed — people split at the line count rather than at the responsibility boundary, or create helper dumping grounds, improving the metric while worsening the design. A warning plus a baseline ratchet (fail only on new or worsening violations) plus a review prompt captures the value without the perverse incentive.
  • When is a very long file legitimately fine?
    Generated code, large exhaustive mapping or lookup tables, data fixtures, and some inherently linear artifacts like parsers or state machines can be long and still be one cohesive thing with one reason to change. Rules should exempt generated directories explicitly, and reviewers should judge on cohesion rather than on the number.
  • Someone adds banner comments like `//====== VALIDATION ======` to organize a growing class. What should a reviewer say?
    That each banner names a responsibility the class is holding, so the banners are a map of the extraction seams. Suggest pulling those sections into their own classes or modules and letting the type names replace the banners — the need to navigate your own file is the signal.

A chapter that needs its own table of contents has stopped being a chapter. The fix is more chapters, not a better index.

context