skip to content

What do "vertical openness" and "vertical density" mean in code formatting, and how should blank lines and vertical distance between related declarations be used?

level: middleimportance: should knowfreq 48%

answer

  1. Blank line = new thought; none = one thought
  2. Declare variables near first use
  3. Instance vars: one well-known place
  4. Overloads adjacent = conceptual affinity
  5. Many stanzas → extract, don't space

basics

~10 s

Vertical openness means putting a blank line between separate thoughts so each stands out. Vertical density means keeping tightly-related lines packed together with no blank lines, so they read as one unit.

solid answer

~50 s

Vertical formatting uses blank space as punctuation. **Vertical openness**: separate concepts (imports vs. code, one function from the next, distinct logical stanzas inside a function) get a blank line, so the eye segments the file into paragraphs. **Vertical density**: lines that belong to one thought — a group of related field declarations, or a two-line guard clause — get no blank line between them, because a gap implies "different topic" and forces a needless re-orientation. Two companion rules: **vertical distance** — concepts that are related should sit close together; variables are declared as near their first use as possible, and instance variables are grouped in one well-known place; and **conceptual affinity** — functions that do similar things, share a naming scheme, or call each other should be near each other even without a call relationship. All of this is a heuristic; the failure mode is a comment-and-blank-line-riddled 200-line function where the right fix is extraction, not spacing.

go deeper

for a junior

Say blank lines separate distinct ideas and no blank line keeps one idea together; declare variables close to where you use them.

for a middle

Name openness, density, vertical distance, and conceptual affinity, and give a concrete example of each (grouped fields, overloads adjacent, loop variable in the loop).

for a senior

Add why formatters can't own this (semantic grouping isn't derivable from syntax) and the extraction anti-pattern where blank lines paper over an oversized function.

for a principal

Frame it as review-culture cost: whitespace heuristics only pay off if functions and files are small; when vertical distance fails across files it is a cohesion/packaging problem, not a formatting one.

### The core idea: whitespace is punctuation Code has no paragraphs, sentences, or section headings built into the language. Blank lines and adjacency are the only typographic tools available, so they take on that role. Two complementary heuristics from *Clean Code* name the two directions. ### Vertical openness **Definition:** insert a blank line between *distinct thoughts*. Typical boundaries that deserve a blank line: - Between the package/import block and the first declaration. - Between every two function/method definitions. - Between logical "stanzas" inside a longer function — e.g. after a block of validation, before the block that does the work, before the block that assembles the result. The effect is that when you defocus your eyes, the file resolves into blocks. Readers navigate by shape before they navigate by text, so those blocks are genuinely load-bearing. ### Vertical density **Definition:** lines that form *one* thought should be adjacent, with no blank line between them. A blank line is a signal that says "new topic". Sprinkling them inside a coherent group is like putting a paragraph break in the middle of a sentence — the reader stops, looks for the new topic, finds none, and continues, having paid for nothing. The classic offender is a set of related field declarations with a blank line (or worse, a one-line comment) between each; packed together they read as one table at a glance. ### Vertical distance **Definition:** concepts that are closely related should be *vertically close*, and the amount of separation should express how related they are. Concrete sub-rules: - **Variable declarations near first use.** Local variables are declared right before the code that uses them, not hoisted to the top of a long function. Loop-control variables are declared inside the loop statement. - **Instance variables in one conventional place.** Since they are used by *many* methods, they cannot be near all of them; the resolution is to put them all in one well-known location (top of the class in most conventions) so readers always know where to look. - **Dependent functions close, caller above callee.** If one function calls another, they belong near each other and, where the language permits, the caller goes first — this is what makes the newspaper/stepdown ordering work. ### Conceptual affinity **Definition:** put things near each other when they are *conceptually* related, even with no call or data dependency. Drivers of affinity include: a shared naming scheme (`assertEquals`, `assertTrue`, `assertNull`), performing variations of the same operation, or being overloads of the same name. Overloads in particular should always be adjacent — separating them by unrelated code is a common annoyance. ### Trade-offs, limits, and failure modes - **It is a heuristic, not a metric.** No tool measures 'openness'. Most auto-formatters deliberately *preserve* the author's blank lines (usually collapsing runs to a maximum of one or two) precisely because the intent is semantic and machines cannot infer it. So this rule survives only through review culture. - **Blank lines as a substitute for extraction is the anti-pattern.** If a function needs five blank-line-separated stanzas plus a comment above each stanza, each stanza is a function begging to be extracted with the comment as its name. Formatting cannot rescue a function that is too big; it can only make bigness slightly more tolerable. - **Variables near first use conflicts with older 'declare at top' styles.** Languages/eras that required declarations at block start or teams with that legacy convention will differ. Modern block-scoped languages make near-first-use both possible and preferred, because a declaration far from its use forces the reader to remember it. - **Vertical distance breaks down across files.** If two closely related functions live in different files or modules, no amount of blank-line discipline helps; that is a packaging/cohesion problem. - **Screen size matters.** The practical unit is 'can I see the caller and callee at once?' Very long functions push related things off-screen regardless of blank-line policy; short functions and short files make the whole family of rules nearly automatic. ### How to apply in review Good review comments here are specific: 'blank line between these two unrelated stanzas', 'these three fields are one group — drop the gaps', 'declare `total` right before the loop that fills it', 'move this overload next to its sibling'. Vague 'formatting is off' comments are noise, especially if a formatter already owns whitespace normalization.

  • Why can't a code formatter decide where blank lines belong?
    Because blank-line placement encodes *semantic* grouping — which lines the author considers one thought — and that is not derivable from syntax. Formatters therefore normalize only mechanical aspects (collapsing runs of blank lines to a maximum, requiring one between members) and otherwise preserve what the author wrote.
  • When is a blank-line-separated stanza inside a function a smell rather than good formatting?
    When the stanzas each have a comment header, or when there are many of them. That pattern means the function is doing several named things; extracting each stanza into a well-named function removes both the comment and the need for the spacing.
  • Instance variables are used by many methods, so 'declare near first use' can't apply — how is that resolved?
    By convention rather than proximity: group them all in one well-known location (top of the class in most languages, bottom in a few older conventions) so readers always know where to look.

Blank lines are paragraph breaks in prose: one between topics makes the page scannable; one dropped mid-sentence makes the reader stop and hunt for a new topic that isn't there.

context