agentleFS
decebalsdecebals/claude-code-java/skills/clean-code/SKILL.md

clean-code

Skill763 starsChanged 56 days agoMITView on GitHub

Clean Code principles (DRY, KISS, YAGNI), naming, function design and readability. Use when code is hard to read, with long methods, unclear names, duplication or deep nesting. For how responsibilities are split across classes and which way dependencies point, use solid-principles instead.

We split this skill into the rules it gives an agent

3 rules. 0 are common, 3 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 94 edited versions we read keep these.

  • 3

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Write readable, maintainable code following Clean Code principles.

    line 9
  2. Distinctive:

    Not all duplication is bad.

    line 94
  3. Distinctive:

    When reviewing code, check:

    line 544

“Common” is measured: kept by at least 6 in 10 of the 94 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 Skill

Write readable, maintainable code following Clean Code principles.

When to Use

  • User says "clean this code" / "refactor" / "improve readability"
  • Code review focusing on maintainability
  • Reducing complexity
  • Improving naming

Core Principles

PrincipleMeaningViolation Sign
DRYDon't Repeat YourselfCopy-pasted code blocks
KISSKeep It Simple, StupidOver-engineered solutions
YAGNIYou Aren't Gonna Need ItFeatures "just in case"

DRY - Don't Repeat Yourself

"Every piece of knowledge must have a single, unambiguous representation in the system."

Violation

// ❌ BAD: Same validation logic repeated
public class UserController {

    public void createUser(UserRequest request) {
        if (request.getEmail() == null || request.getEmail().isBlank()) {
            throw new ValidationException("Email is required");
        }
        if (!request.getEmail().contains("@")) {
            throw new ValidationException("Invalid email format");
        }
        // ... create user
    }

    public void updateUser(UserRequest request) {
        if (request.getEmail() == null || request.getEmail().isBlank()) {
            throw new ValidationException("Email is required");
        }
        if (!request.getEmail().contains("@")) {
            throw new ValidationException("Invalid email format");
        }
        // ... update user
    }
}

Refactored

// ✅ GOOD: Single source of truth
public class EmailValidator {

    public void validate(String email) {
        if (email == null || email.isBlank()) {
            throw new ValidationException("Email is required");
        }
        if (!email.contains("@")) {
            throw new ValidationException("Invalid email format");
        }
    }
}

public class UserController {
    private final EmailValidator emailValidator;

    public void createUser(UserRequest request) {
        emailValidator.validate(request.getEmail());
        // ... create user
    }

    public void updateUser(UserRequest request) {
        emailValidator.validate(request.getEmail());
        // ... update user
    }
}

DRY Exceptions

Not all duplication is bad. Avoid premature abstraction:

// These look similar but serve different purposes - OK to duplicate
public BigDecimal calculateShippingCost(Order order) {
    return order.getWeight().multiply(SHIPPING_RATE);
}

public BigDecimal calculateInsuranceCost(Order order) {
    return order.getValue().multiply(INSURANCE_RATE);
}
// Don't force these into one method - they'll evolve differently

KISS - Keep It Simple

"The simplest solution is usually the best."

Violation

// ❌ BAD: Over-engineered for simple task
public class StringUtils {

    public boolean isEmpty(String str) {
        return Optional.ofNullable(str)
            .map(String::trim)
            .map(String::isEmpty)
            .orElseGet(() -> Boolean.TRUE);
    }
}

Refactored

// ✅ GOOD: Simple and clear
public class StringUtils {

    public boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    // Or use existing library
    // return StringUtils.isBlank(str);  // Apache Commons
    // return str == null || str.isBlank();  // Java 11+
}

KISS Checklist

  • Can a junior developer understand this in 30 seconds?
  • Is there a simpler way using standard libraries?
  • Am I adding complexity for edge cases that may never happen?

YAGNI - You Aren't Gonna Need It

"Don't add functionality until it's necessary."

Violation

// ❌ BAD: Building for hypothetical future
public interface Repository<T, ID> {
    T findById(ID id);
    List<T> findAll();
    List<T> findAll(Pageable pageable);
    List<T> findAll(Sort sort);
    List<T> findAllById(Iterable<ID> ids);
    T save(T entity);
    List<T> saveAll(Iterable<T> entities);
    void delete(T entity);
    void deleteById(ID id);
    void deleteAll(Iterable<T> entities);
    void deleteAll();
    boolean existsById(ID id);
    long count();
    // ... 20 more methods "just in case"
}

// Current usage: only findById and save

Refactored

// ✅ GOOD: Only what's needed now
public interface UserRepository {
    Optional<User> findById(Long id);
    User save(User user);
}

// Add methods when actually needed, not before

YAGNI Signs

  • "We might need this later"
  • "Let's make it configurable just in case"
  • "What if we need to support X in the future?"
  • Abstract classes with one implementation

Naming Conventions

Variables

// ❌ BAD
int d;                  // What is d?
String s;               // Meaningless
List<User> list;        // What kind of list?
Map<String, Object> m;  // What does it map?

// ✅ GOOD
int elapsedTimeInDays;
String customerName;
List<User> activeUsers;
Map<String, Object> sessionAttributes;

Booleans

// ❌ BAD
boolean flag;
boolean status;
boolean check;

// ✅ GOOD - Use is/has/can/should prefix
boolean isActive;
boolean hasPermission;
boolean canEdit;
boolean shouldNotify;

Methods

// ❌ BAD
void process();           // Process what?
void handle();            // Handle what?
void doIt();              // Do what?
User get();               // Get from where?

// ✅ GOOD - Verb + noun, descriptive
void processPayment();
void handleLoginRequest();
void sendWelcomeEmail();
User findByEmail(String email);
List<Order> fetchPendingOrders();

Classes

// ❌ BAD
class Data { }           // Too vague
class Info { }           // Too vague
class Manager { }        // Often a god class
class Helper { }         // Often a dumping ground
class Utils { }          // Static method dumping ground

// ✅ GOOD - Noun, specific responsibility
class User { }
class OrderProcessor { }
class EmailValidator { }
class PaymentGateway { }
class ShippingCalculator { }

Naming Conventions Table

ElementConventionExample
ClassPascalCase, nounOrderService
InterfacePascalCase, adjective or nounComparable, List
MethodcamelCase, verbcalculateTotal()
VariablecamelCase, nouncustomerEmail
ConstantUPPER_SNAKEMAX_RETRY_COUNT
Packagelowercasecom.example.orders

Functions / Methods

Keep Functions Small

// ❌ BAD: 50+ line method doing multiple things
public void processOrder(Order order) {
    // validate order (10 lines)
    // calculate totals (15 lines)
    // apply discounts (10 lines)
    // update inventory (10 lines)
    // send notifications (10 lines)
    // ... and more
}

// ✅ GOOD: Small, focused methods
public void processOrder(Order order) {
    validateOrder(order);
    calculateTotals(order);
    applyDiscounts(order);
    updateInventory(order);
    sendNotifications(order);
}

Single Level of Abstraction

// ❌ BAD: Mixed abstraction levels
public void processOrder(Order order) {
    validateOrder(order);  // High level

    // Low level mixed in
    BigDecimal total = BigDecimal.ZERO;
    for (OrderItem item : order.getItems()) {
        total = total.add(item.getPrice().multiply(
            BigDecimal.valueOf(item.getQuantity())));
    }

    sendEmail(order);  // High level again
}

// ✅ GOOD: Consistent abstraction level
public void processOrder(Order order) {
    validateOrder(order);
    calculateTotal(order);
    sendConfirmation(order);
}

private BigDecimal calculateTotal(Order order) {
    return order.getItems().stream()
        .map(item -> item.getPrice().multiply(
            BigDecimal.valueOf(item.getQuantity())))
        .reduce(BigDecimal.ZERO, BigDecimal::add);
}

Limit Parameters

// ❌ BAD: Too many parameters
public User createUser(String firstName, String lastName,
                       String email, String phone,
                       String address, String city,
                       String country, String zipCode) {
    // ...
}

// ✅ GOOD: Use parameter object
public User createUser(CreateUserRequest request) {
    // ...
}

// Or builder
public User createUser(UserBuilder builder) {
    // ...
}

Avoid Flag Arguments

// ❌ BAD: Boolean flag changes behavior
public void sendMessage(String message, boolean isUrgent) {
    if (isUrgent) {
        // send immediately
    } else {
        // queue for later
    }
}

// ✅ GOOD: Separate methods
public void sendUrgentMessage(String message) {
    // send immediately
}

public void queueMessage(String message) {
    // queue for later
}

Comments

Avoid Obvious Comments

// ❌ BAD: Noise comments
// Set the user's name
user.setName(name);

// Increment counter
counter++;

// Check if user is null
if (user != null) {
    // ...
}

Good Comments

// ✅ GOOD: Explain WHY, not WHAT

// Retry with exponential backoff to avoid overwhelming the server
// during high load periods (see incident #1234)
for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
    Thread.sleep((long) Math.pow(2, attempt) * 1000);
    // ...
}

// TODO: Replace with Redis cache after infrastructure upgrade (Q2 2026)
private Map<String, User> userCache = new ConcurrentHashMap<>();

// WARNING: Order matters! Discounts must be applied before tax calculation
applyDiscounts(order);
calculateTax(order);

Let Code Speak

// ❌ BAD: Comment explaining bad code
// Check if the user is an admin or has special permission
// and the action is allowed for their role
if ((user.getRole() == 1 || user.getRole() == 2) &&
    (action == 3 || action == 4 || action == 7)) {
    // ...
}

// ✅ GOOD: Self-documenting code
if (user.hasAdminPrivileges() && action.isAllowedFor(user.getRole())) {
    // ...
}

Common Code Smells

SmellDescriptionRefactoring
Long MethodMethod > 20 linesExtract Method
Long Parameter List> 3 parametersParameter Object
Duplicate CodeSame code in multiple placesExtract Method/Class
Dead CodeUnused codeDelete it
Magic NumbersUnexplained literalsNamed Constants
God ClassClass doing too muchExtract Class
Feature EnvyMethod uses another class's dataMove Method
Primitive ObsessionPrimitives instead of objectsValue Objects

Magic Numbers

// ❌ BAD
if (user.getAge() >= 18) { }
if (order.getTotal() > 100) { }
Thread.sleep(86400000);

// ✅ GOOD
private static final int ADULT_AGE = 18;
private static final BigDecimal FREE_SHIPPING_THRESHOLD = new BigDecimal("100");
private static final long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);

if (user.getAge() >= ADULT_AGE) { }
if (order.getTotal().compareTo(FREE_SHIPPING_THRESHOLD) > 0) { }
Thread.sleep(ONE_DAY_MS);

Primitive Obsession

// ❌ BAD: Primitives everywhere
public void createUser(String email, String phone, String zipCode) {
    // No validation, easy to mix up parameters
}

createUser("12345", "john@email.com", "555-1234");  // Wrong order, compiles!

// ✅ GOOD: Value objects
public record Email(String value) {
    public Email {
        if (!value.contains("@")) {
            throw new IllegalArgumentException("Invalid email");
        }
    }
}

public record PhoneNumber(String value) {
    // validation
}

public void createUser(Email email, PhoneNumber phone, ZipCode zipCode) {
    // Type-safe, self-validating
}

Refactoring Quick Reference

FromToTechnique
Long methodShort methodsExtract Method
Duplicate codeSingle methodExtract Method
Complex conditionalPolymorphismReplace Conditional with Polymorphism
Many parametersObjectIntroduce Parameter Object
Temp variablesQuery methodReplace Temp with Query
Comments explaining codeSelf-documenting codeRename, Extract
Nested conditionalsEarly returnGuard Clauses

Guard Clauses

// ❌ BAD: Deeply nested
public void processOrder(Order order) {
    if (order != null) {
        if (order.isValid()) {
            if (order.hasItems()) {
                // actual logic buried here
            }
        }
    }
}

// ✅ GOOD: Guard clauses
public void processOrder(Order order) {
    if (order == null) return;
    if (!order.isValid()) return;
    if (!order.hasItems()) return;

    // actual logic at top level
}

Clean Code Checklist

When reviewing code, check:

  • Are names meaningful and pronounceable?
  • Are functions small and focused?
  • Is there any duplicated code?
  • Are there magic numbers or strings?
  • Are comments explaining "why" not "what"?
  • Is the code at consistent abstraction level?
  • Can any code be simplified?
  • Is there dead/unused code?

Related Skills

  • solid-principles - Design principles for class structure
  • design-patterns - Common solutions to recurring problems
  • java-code-review - Comprehensive review checklist

Download now (ZIP)

  • Other versions101 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 2

    1. iCesofT/awesome-ai★ 197% same
    2. mvonline/claude-skills★ 099% same

    Wrote their own version · 99

    1. superplanehq/superplane★ 8.5ksame name
    2. vudovn/ag-kit★ 8.2ksame name
    3. vudovn/antigravity-kit★ 8.2ksame name
    4. Openpanel-dev/openpanel★ 7.2ksame name
    5. ciembor/agent-rules-books★ 2.8ksame name
    6. wondelai/skills★ 2.2ksame name
    7. operately/operately★ 609same name
    8. liza-mas/liza★ 414same name
    9. Mindrally/skills★ 275same name
    10. techygarg/lattice★ 209same name

    89 more not listed

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • Used alongsideProjects with it also use intelligent-routing, nextjs-react-expert and 10 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

      rust-pro

      Master Rust 1.75+ with modern async patterns, advanced type system

      Also in 5 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

    • 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

    • jornalistainclusivoSkill

      design-spec

      How to author a DESIGN.md file — the machine-readable design-token + human-rationale format that must exist before any UI is built. YAML front-matter token schema (colors, typography, spacing, rounded, components), type system, token references, and canonical section order.

      Also in 3 projects that use this

    • +6 more from xfstudio
  • In this repository17 other files it gives its agents.

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.