agentleFS
rundopsrundops/dops/.claude/skills/clean-code-design/SKILL.md

clean-code-design

Skill3 starsChanged 8 months agoMITView on GitHub

Clean Code design maxims for Go — DRY, KISS, YAGNI, separation of concerns, composition over inheritance, Law of Demeter. Use when making architectural decisions, creating new packages or modules, refactoring code structure, or reviewing overall code organization in Go projects.

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

17 rules. About 0 are common, 15 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈15

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not add configuration options "in case someone needs them later"

    line 14
  2. Distinctive:

    Do not build plugin architectures, feature flags, or extension points speculatively

    line 15
  3. Distinctive:

    If it's not in the spec, it doesn't get built.

    line 16
  4. Distinctive:

    If a junior developer can't understand the code in 5 minutes, it's too complex

    line 24
  5. Distinctive:

    Every piece of domain knowledge has a single authoritative representation

    line 29
  6. Distinctive:

    Before extracting, ask: "If one of these changes, must the other change too?" If no, they're not duplicates.

    line 31
  7. Distinctive:

    Do NOT apply DRY to tests — test readability beats test DRYness

    line 33
  8. Distinctive:

    Do not mix I/O with business logic:

    line 38
  9. Distinctive:

    Use struct embedding for code reuse, interfaces for polymorphism

    line 60
  10. Distinctive:

    Prefer small, composable types over large monolithic ones:

    line 61
  11. Very specific:

    No train wrecks: s.config.Database.Connection.Pool.Get() — each .

    line 75
  12. Distinctive:

    If you need data deep inside a structure, expose a method at the right level:

    line 76
  13. Distinctive:

    Avoid circular dependencies — if A imports B and B needs A, extract an interface package

    line 90
  14. Very specific:

    Keep main.go thin: parse flags, wire dependencies, call Run()

    line 92
  15. Distinctive:

    When implementing a spec, clean up the code you touch

    line 96
  16. Distinctive:

    Don't refactor unrelated code — scope cleanup to what you're working on

    line 98
  17. Distinctive:

    When in conflict, higher-numbered rules yield to lower-numbered ones.

    line 108

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “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 Design Principles for Go

Apply these principles when making structural or architectural decisions.

YAGNI — You Aren't Gonna Need It

  • Implement only what the current spec requires — nothing more
  • Do not add configuration options "in case someone needs them later"
  • Do not build plugin architectures, feature flags, or extension points speculatively
  • If it's not in the spec, it doesn't get built. Period.
  • The cost of building the wrong abstraction is higher than the cost of adding it later

KISS — Keep It Simple

  • The simplest solution that satisfies the spec is the best solution
  • Three similar lines of code are better than a premature abstraction
  • Choose boring technology over clever technology
  • If a junior developer can't understand the code in 5 minutes, it's too complex
  • Complexity debt compounds faster than technical debt

DRY — Don't Repeat Yourself

  • Every piece of domain knowledge has a single authoritative representation
  • DRY applies to knowledge, not just code — identical-looking code serving different purposes is NOT duplication
  • Before extracting, ask: "If one of these changes, must the other change too?" If no, they're not duplicates.
  • Apply DRY across: code, config, specs, build scripts
  • Do NOT apply DRY to tests — test readability beats test DRYness

Separation of Concerns

  • Each package has one clear purpose
  • Do not mix I/O with business logic:
    // Bad: business logic mixed with I/O
    func ProcessConfig(path string) error {
        data, err := os.ReadFile(path)  // I/O
        // ... validation logic ...      // business logic
        // ... transformation ...         // business logic
        return os.WriteFile(out, result, 0644)  // I/O
    }
    
    // Good: separated
    func LoadConfig(path string) ([]byte, error) { ... }     // I/O
    func ValidateConfig(data []byte) error { ... }            // logic
    func TransformConfig(data []byte) ([]byte, error) { ... } // logic
    func SaveConfig(path string, data []byte) error { ... }   // I/O
  • CLI parsing, business logic, and infrastructure are separate layers
  • For a Go CLI: cmd/ (CLI wiring) → internal/ (business logic) → adapters (I/O, external services)

Composition Over Inheritance

  • Go has no inheritance — this principle is built into the language
  • Use struct embedding for code reuse, interfaces for polymorphism
  • Prefer small, composable types over large monolithic ones:
    // Compose behaviors
    type DeployService struct {
        validator Validator
        pusher    Pusher
        notifier  Notifier
    }
  • Favor function parameters and return values over method receivers when behavior doesn't need state

Law of Demeter

  • A function should only call methods on: its receiver, its parameters, objects it creates, its direct fields
  • No train wrecks: s.config.Database.Connection.Pool.Get() — each . is a coupling point
  • If you need data deep inside a structure, expose a method at the right level:
    // Bad
    pool := s.config.Database.Connection.Pool
    conn := pool.Get()
    
    // Good
    conn, err := s.GetDBConnection()

Package Design

  • Packages are the unit of encapsulation in Go
  • Name packages by what they provide, not what they contain
  • Avoid circular dependencies — if A imports B and B needs A, extract an interface package
  • internal/ enforces visibility at the compiler level — use it
  • Keep main.go thin: parse flags, wire dependencies, call Run()

Boy Scout Rule

  • When implementing a spec, clean up the code you touch
  • Rename a confusing variable, extract a function, remove dead code
  • Don't refactor unrelated code — scope cleanup to what you're working on
  • Small, continuous improvements prevent decay

Kent Beck's Four Rules of Simple Design (Priority Order)

  1. Runs all the tests — all spec criteria pass
  2. Contains no duplication — shared concepts implemented once
  3. Expresses intent — code reads like the spec
  4. Minimizes classes/functions — no unnecessary abstractions

When in conflict, higher-numbered rules yield to lower-numbered ones.

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.