agentleFS
kayamankayaman/skills/clean-code/SKILL.md

clean-code

Skill3 starsChanged 8 months agoCC0-1.0View on GitHub

Enforces clean code principles including meaningful naming, small focused functions, command-query separation, error handling with exceptions, and Kent Beck's four rules of simple design. Use when writing new code, refactoring existing code, reviewing pull requests for readability and maintainability, applying the Boy Scout Rule, or evaluating functions for single responsibility and appropriate abstraction level.

108 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use intelligent-routing, nextjs-react-expert and 9 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • SKB3002Skill

    intelligent-routing

    Automatic agent selection and intelligent task routing. Analyzes user requests and automatically selects the best specialist agent(s) without requiring explicit user mentions.

    Also in 5 projects that use this

  • SKB3002Skill

    nextjs-react-expert

    React and Next.js performance optimization from Vercel Engineering. Use when building React components, optimizing performance, eliminating waterfalls, reducing bundle size, reviewing code for performance issues, or implementing server/client-side optimizations.

    Also in 3 projects that use this

  • xfstudioSkill

    bash-pro

    Master of defensive Bash scripting for production automation, CI/CD

    Also in 4 projects that use this

  • xfstudioSkill

    code-refactoring-tech-debt

    You are a technical debt expert specializing in identifying, quantifying, and prioritizing technical debt in software projects. Analyze the codebase to uncover debt, assess its impact, and create acti

    Also in 4 projects that use this

  • flying-diceSkill

    clean-code-review

    Multi-agent clean code audit — each principle gets its own agent

    Also in 3 projects that use this

  • goca-seSkill

    batch-operations

    Apply a change safely across many files — refactors touching more than 5 files, library or API migrations, project-wide renames of symbols/imports/paths, or adding boilerplate to many files. Use when "do it all at once" risks context overflow or silent failures.

    Also in 3 projects that use this

  • +4 more from xfstudio

The file

Show its rules and text

We split this skill into the rules it gives an agent

34 rules. 0 are common, 27 are distinctive, and 7 are very specific to this project.

  • 0

    Common

    Most of the 101 edited versions we read keep these.

  • 27

    Distinctive

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    MUST use intention-revealing names — the name tells WHY it exists, WHAT it does, HOW it's used

    line 27
  2. Distinctive:

    MUST use pronounceable, searchable names — avoid abbreviations and single-letter variables (except loop counters)

    line 28
  3. Very specific:

    MUST use nouns for classes (Order, ShippingPolicy) and verbs for methods (calculateTotal, validateAddress)

    line 29
  4. Very specific:

    MUST pick one word per concept and use it consistently: don't mix fetch, retrieve, get for the same operation

    line 30
  5. Very specific:

    MUST NOT use Hungarian notation, type prefixes, or member prefixes (strName, m_count)

    line 31
  6. Distinctive:

    SHOULD use domain vocabulary — names from the problem domain or solution domain, never invented jargon

    line 32
  7. Distinctive:

    MUST do one thing — if a function does more than one thing, extract the other things

    line 47
  8. Distinctive:

    MUST operate at one level of abstraction — don't mix high-level orchestration with low-level details

    line 48
  9. Distinctive:

    SHOULD follow the Stepdown Rule: read like a top-down narrative, each function introducing the next level of detail

    line 49
  10. Distinctive:

    SHOULD have as few arguments as possible — zero (niladic) is ideal.

    line 50
  11. Distinctive:

    MUST NOT use boolean flag arguments — they signal the function does two things.

    line 51
  12. Distinctive:

    SHOULD be small enough to fit in your working memory — but prioritize clarity over arbitrary line counts

    line 52
  13. Distinctive:

    MUST NOT create hybrids — half object, half data structure — that have the worst of both worlds

    line 110
  14. Distinctive:

    SHOULD use objects when new types are more likely than new operations

    line 111
  15. Distinctive:

    SHOULD use data structures when new operations are more likely than new types

    line 112
  16. Very specific:

    MUST respect the Law of Demeter — no train wrecks: a.getB().getC().doSomething()

    line 113
  17. Distinctive:

    MUST use exceptions instead of error return codes — exceptions separate the happy path from error handling

    line 121
  18. Very specific:

    MUST write try-catch-finally first when the function involves operations that can fail

    line 122
  19. Distinctive:

    SHOULD use unchecked exceptions — checked exceptions violate OCP (every catch clause in the call chain must be updated)

    line 123
  20. Very specific:

    MUST NOT return null — use Null Object pattern, Optional/Maybe, or throw an exception

    line 124
  21. Very specific:

    MUST NOT pass null as a function argument — there's no reasonable expectation for handling it

    line 125
  22. Distinctive:

    SHOULD create exception classes organized by how callers HANDLE them, not by their source

    line 126
  23. Distinctive:

    Write a failing test before writing any production code

    line 147
  24. Distinctive:

    Write only enough of a test to demonstrate a failure

    line 148
  25. Distinctive:

    Write only enough production code to make the failing test pass

    line 149
  26. Distinctive:

    MUST test one concept per test — multiple assertions are fine if they all verify the same concept

    line 161
  27. Distinctive:

    MUST NOT test private methods directly — test through the public interface

    line 162
  28. Distinctive:

    SHOULD write a working solution first, then refactor incrementally

    line 183
  29. Distinctive:

    MUST have tests in place before refactoring — TDD provides the safety net

    line 184
  30. Distinctive:

    SHOULD apply the Boy Scout Rule: leave the code cleaner than you found it — small improvements compound over time

    line 185
  31. Distinctive:

    SHOULD prefer tidying (small, safe structural improvements) as a separate step from feature work (Beck, *Tidy First?*)

    line 186
  32. Distinctive:

    SHOULD apply clean code principles as guidelines balanced by context, not as rigid dogma

    line 202
  33. Distinctive:

    SHOULD NOT fragment a clear 20-line function into five 4-line functions if it reduces readability

    line 203
  34. Distinctive:

    When writing or reviewing code, verify:

    line 209

“Common” is measured: kept by at least 6 in 10 of the 101 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Clean Code

Reference: Clean Code (Martin), Tidy First? (Beck), A Philosophy of Software Design (Ousterhout), Refactoring (Fowler)

When to Apply

  • Writing new functions, classes, or modules
  • Refactoring existing code for readability and maintainability
  • Reviewing pull requests for naming, structure, and clarity
  • Deciding whether to add a comment or improve the code instead
  • Handling errors and edge cases in application code
  • Evaluating whether code complexity is justified

Naming

"If a name requires a comment, it does not reveal its intent."

Rules

  • MUST use intention-revealing names — the name tells WHY it exists, WHAT it does, HOW it's used
  • MUST use pronounceable, searchable names — avoid abbreviations and single-letter variables (except loop counters)
  • MUST use nouns for classes (Order, ShippingPolicy) and verbs for methods (calculateTotal, validateAddress)
  • MUST pick one word per concept and use it consistently: don't mix fetch, retrieve, get for the same operation
  • MUST NOT use Hungarian notation, type prefixes, or member prefixes (strName, m_count)
  • SHOULD use domain vocabulary — names from the problem domain or solution domain, never invented jargon
BadGoodWhy
delapsedTimeInDaysIntention-revealing
genymdhmsgenerationTimestampPronounceable
accountListaccountsDon't encode the container type
Manager, Processor, HandlerSpecific name for the actual responsibilityAvoid meaningless suffixes

Functions

Rules

  • MUST do one thing — if a function does more than one thing, extract the other things
  • MUST operate at one level of abstraction — don't mix high-level orchestration with low-level details
  • SHOULD follow the Stepdown Rule: read like a top-down narrative, each function introducing the next level of detail
  • SHOULD have as few arguments as possible — zero (niladic) is ideal; three or more requires justification
  • MUST NOT use boolean flag arguments — they signal the function does two things; split into two functions
  • SHOULD be small enough to fit in your working memory — but prioritize clarity over arbitrary line counts

Command-Query Separation (CQS)

Functions MUST either do something (command — changes state, returns void) or answer something (query — returns a value, no side effects). Never both.

# BAD — command and query mixed
def set_and_get_previous(value):
    previous = self.value
    self.value = value
    return previous

# GOOD — separated
def get_value(self):          # query
    return self.value

def set_value(self, value):   # command
    self.value = value

Comments

"Don't comment bad code — rewrite it." (Kernighan & Plaugher)

Acceptable Comments

TypeExampleWhy
Legal headers// Copyright 2024 Acme CorpRequired by policy
Explanation of intent// Use binary search because list is always sorted by insertion orderThe code shows WHAT; the comment explains WHY
Warning of consequences// This test takes 30 minutes to runPrevents accidental execution
TODO markers// TODO(#1234): Replace with batch API when availableTracks known improvement with issue reference
API documentationJavadoc/JSDoc for public APIsContract documentation for consumers

Comments That MUST Be Avoided

  • Redundant comments that restate the code: i++; // increment i
  • Misleading comments that describe what the code SHOULD do but doesn't
  • Commented-out code — version control preserves history; delete dead code
  • Journal comments — git log tracks changes; don't maintain a changelog in code
  • Closing brace comments — if you need them, your function is too long

Objects vs Data Structures

Objects and data structures are diametrically opposed (Martin). Choose deliberately.

ObjectsData Structures
ExposeBehavior (methods)Data (fields)
HideData (private state)Nothing
Easy to addNew types (add new class)New functions (add function operating on all types)
Hard to addNew behavior (must change all types)New types (must change all functions)
  • MUST NOT create hybrids — half object, half data structure — that have the worst of both worlds
  • SHOULD use objects when new types are more likely than new operations
  • SHOULD use data structures when new operations are more likely than new types
  • MUST respect the Law of Demeter — no train wrecks: a.getB().getC().doSomething()

Error Handling

Rules

  • MUST use exceptions instead of error return codes — exceptions separate the happy path from error handling
  • MUST write try-catch-finally first when the function involves operations that can fail
  • SHOULD use unchecked exceptions — checked exceptions violate OCP (every catch clause in the call chain must be updated)
  • MUST NOT return null — use Null Object pattern, Optional/Maybe, or throw an exception
  • MUST NOT pass null as a function argument — there's no reasonable expectation for handling it
  • SHOULD create exception classes organized by how callers HANDLE them, not by their source
# BAD — checking null return
user = repository.find_by_id(id)
if user is not None:
    # do something

# GOOD — exception or Optional
user = repository.find_by_id(id)  # raises NotFoundError
# or
user = repository.find_by_id(id)  # returns Optional<User>
user.if_present(lambda u: process(u))

Unit Tests

TDD Three Laws

  1. Write a failing test before writing any production code
  2. Write only enough of a test to demonstrate a failure
  3. Write only enough production code to make the failing test pass

F.I.R.S.T. Principles

PrincipleRule
FastTests MUST run quickly — slow tests don't get run
IndependentTests MUST NOT depend on each other or on execution order
RepeatableTests MUST produce the same result in any environment
Self-ValidatingTests MUST have a boolean output (pass/fail) — no manual log inspection
TimelyTests SHOULD be written just before the production code (TDD)
  • MUST test one concept per test — multiple assertions are fine if they all verify the same concept
  • MUST NOT test private methods directly — test through the public interface

Kent Beck's Four Rules of Simple Design

In priority order:

  1. Passes all the tests — a system that can't be verified MUST NOT be deployed
  2. Reveals intention — good names, small functions, standard patterns make the code self-documenting
  3. No duplication — every piece of knowledge has a single, authoritative representation
  4. Fewest elements — minimize classes and methods; counterbalance against over-decomposition

Rules 2–4 are applied during refactoring under the safety net of rule 1.


Successive Refinement

"To write clean code, you must first write dirty code and then clean it."

  • SHOULD write a working solution first, then refactor incrementally
  • MUST have tests in place before refactoring — TDD provides the safety net
  • SHOULD apply the Boy Scout Rule: leave the code cleaner than you found it — small improvements compound over time
  • SHOULD prefer tidying (small, safe structural improvements) as a separate step from feature work (Beck, Tidy First?)

Balancing Clean Code with Pragmatism

What Holds Up (2024 consensus)

Naming principles, SRP for functions, CQS, F.I.R.S.T. test principles, error handling with exceptions, the Boy Scout Rule, objects vs data structures distinction.

What Is Debated

  • Extreme function size ("2–4 lines") can produce unreadable names and excessive indirection — prioritize clarity over arbitrary limits
  • Performance in hot paths — Muratori demonstrated that Clean Code structural rules can produce 10–25x slower code in performance-critical scenarios; optimize hot paths pragmatically
  • Deep modules (Ousterhout) — sometimes a larger function with a simple interface is better than many tiny functions that fragment the logic
  • SHOULD apply clean code principles as guidelines balanced by context, not as rigid dogma
  • SHOULD NOT fragment a clear 20-line function into five 4-line functions if it reduces readability

Checklist

When writing or reviewing code, verify:

  • Names are intention-revealing, pronounceable, and consistent across the codebase
  • Functions do one thing at one level of abstraction
  • CQS is respected — functions either change state OR return a value, not both
  • No commented-out code, redundant comments, or journal entries
  • Comments explain WHY (intent), not WHAT (code restates itself)
  • Error handling uses exceptions, not return codes; no null returns or null parameters
  • Tests follow F.I.R.S.T. principles and cover one concept each
  • No hybrids — objects hide data and expose behavior, or data structures expose data
  • Law of Demeter is respected — no train wreck method chains
  • Code has been tidied after getting it working — Boy Scout Rule applied

Key References

BookAuthor(s)PublisherYear
Clean CodeRobert C. MartinPearson2008
Refactoring (2nd ed.)Martin FowlerAddison-Wesley2018
A Philosophy of Software Design (2nd ed.)John OusterhoutStanford2021
Tidy First?Kent BeckO'Reilly2023
Code That Fits in Your HeadMark SeemannAddison-Wesley2021
Five Lines of CodeChristian ClausenManning2021
The Pragmatic Programmer (2nd ed.)Hunt & ThomasAddison-Wesley2020
Implementation PatternsKent BeckAddison-Wesley2007

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.