Code Quality Tools Deep Dive · 2 of 6

Formatters — Settle the Style Argument Once

A formatter rewrites code into a canonical layout. Indentation, line breaks, trailing commas, quote style — all decided by the tool, the same way, every time. The team stops arguing about style; PRs stop containing reformatting noise; new contributors save hours of "is this right?" anxiety. The cost is one config decision; the benefit is permanent.

PrettierBlackgofmtrustfmtSpotlessBiome
← Back to Testing
Quick Facts

What a Formatter Is

Basic Concepts

  • One-button reformatter. Run the tool; the file is rewritten in canonical style. Save in your editor; same thing happens.
  • Opinionated by design. The whole point is removing decisions. Tools that offer "300 config options" undo their own value — Black, gofmt, rustfmt explicitly minimize knobs.
  • Different from linters. Linters detect problems; formatters enforce layout. Modern fast tools (Biome, Ruff) do both, but the categories remain useful.
  • Why it matters: review time spent on style is review time not spent on correctness. Diffs full of whitespace are diffs nobody reads carefully.
By Stack

The Default Formatter, Per Ecosystem

StackFormatter(s)Notes
JavaScript / TypeScriptPrettier, BiomePrettier is the standard. Biome is Rust-based, faster, lint+format combined.
PythonBlack, Ruff FormatRuff Format is Black-compatible and dramatically faster — increasingly the default.
Gogofmt (built-in)The original opinionated formatter. go fmt is part of the toolchain.
RustrustfmtStandard, opinionated, included with the toolchain.
Java / KotlinSpotless, google-java-format, ktlint, ktfmtSpotless is a Gradle plugin orchestrating multiple formatters.
.NET (C#)dotnet format, CSharpierCSharpier is Prettier-style for C#.
RubyRuboCop, Rufo, StandardRuboCop with auto-correct serves as both linter and formatter for many.
Swiftswift-format, SwiftFormatswift-format is Apple's; SwiftFormat is the popular community tool.
PHPPHP-CS-Fixer, PintPint is Laravel's wrapper around PHP-CS-Fixer.
SQLSQLFluff, pgFormatterSQLFluff also lints; pgFormatter is Postgres-specific.
Markdown / YAML / TerraformPrettier (md), yamlfmt, terraform fmtDon't ship inconsistent docs and config either.
Working Practices

Make It Invisible

Format on Save

Editor integration is mandatory. VSCode, IntelliJ, Vim, Neovim, Emacs — every modern editor has format-on-save for the major formatters. Files are clean by the time they hit git. Reviewers never see unformatted code.

Pre-Commit Hook + CI Check

For when format-on-save is forgotten. pre-commit, Husky, lefthook reformat in place at commit time. CI runs prettier --check / black --check / gofmt -l as a fail-on-diff. The two together catch every case.

Adopt the Defaults

Don't tweak the formatter. Five-team companies have wasted entire weeks debating singleQuote: true vs false. The point of the tool is "you don't decide." Pick the defaults; move on.

One Big Reformat Commit

When introducing a formatter to a legacy codebase, do it in one dedicated commit. Add the SHA to .git-blame-ignore-revs so git blame still shows real authors. Don't sprinkle reformatting across feature PRs — it pollutes diffs forever.

Stay in Sync With Linter Style Rules

If the linter and the formatter disagree, every save toggles back and forth. ESLint + Prettier integrations (eslint-config-prettier) turn off ESLint style rules that conflict with Prettier. Use them.

Common Mistakes

Where Teams Go Wrong

  • "Optional" formatting. If only some people format, the format-on-save churn is endless. Make it mandatory in CI.
  • Heavy custom config. A 200-line .prettierrc turns the formatter into a linter and re-introduces style debates. Resist.
  • Skipping pre-commit. CI is the last line; pre-commit prevents the round-trip. Configure once per repo, not once per developer.
  • Forgetting .git-blame-ignore-revs. Reformat commit shows up as "Bob touched every line"; the actual author info is one commit deeper. The ignore file fixes this.
Continue

Other Code Quality Tools