Skip to main content
skill CX Codex

clean-code · decebals — Claude Code skill: what it does, how to install

Guides your coding assistant to write readable code using DRY, KISS, and YAGNI principles. Useful when dealing with bloated methods and vague naming.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add decebals/claude-code-java --skill clean-code -a claude-code
Open on GitHub

What clean-code does

The skill directs coding assistants toward maintainable code through DRY, KISS, and YAGNI principles. It covers duplicate validation checks, warns against premature abstractions, and cuts out speculative methods written just in case. It also enforces conventions for variable names, boolean flags (is, has, can), and bans junk-drawer classes like Manager or Helper.

Keep in mind its scope. For decoupling classes or directing architectural dependencies, this skill is not enough; the author advises using solid-principles instead. The focus here remains strictly local: concise functions, obvious naming, and straightforward logic.

What it helps with

  • refactor bloated methods and nested logic
  • extract duplicated code without premature abstractions
  • fix ambiguous variable and class names
  • prune speculative methods added for hypothetical use cases

Example prompts for the agent

  • Clean this code and improve readability
  • Refactor this method to follow KISS and simplify the checks
  • Review variable naming and boolean flags in this file

How to install clean-code

1Skills CLI (Vercel)

npx skills add decebals/claude-code-java --skill clean-code -a claude-code

2Manually: put the files in place

~/.claude/skills/clean-code/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/clean-code/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about clean-code

How to install clean-code in Claude Code?

Run npx skills add decebals/claude-code-java --skill clean-code -a claude-code in your terminal, or place the file directly at ~/.claude/skills/clean-code/SKILL.md.

What does the clean-code skill do?

It instructs the agent to apply DRY, KISS, and YAGNI rules during refactoring. The assistant simplifies nested statements, tightens function scopes, and corrects generic names.

When should I use solid-principles instead?

Use solid-principles when managing class boundaries, interfaces, and dependency direction. The clean-code skill focuses on readability within functions, simple expressions, and clear naming.

Source text

SKILL.md · MIT
---
name: clean-code
description: 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.
license: MIT
---

# 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

| Principle | Meaning | Violation Sign |
|-----------|---------|----------------|
| **DRY** | Don't Repeat Yourself | Copy-pasted code blocks |
| **KISS** | Keep It Simple, Stupid | Over-engineered solutions |
| **YAGNI** | You Aren't Gonna Need It | Features "just in case" |

---

## DRY - Don't Repeat Yourself

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

### Violation

```java
// ❌ 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

```java
// ✅ 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:

```java
// 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

```java
// ❌ 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

```java
// ✅ 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

```java
// ❌ 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

```java
// ✅ 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

```java
// ❌ 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

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

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

### Methods

```java
// ❌ 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

```java
// ❌ 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

| Element | Convention | Example |
|---------|------------|---------|
| Class | PascalCase, noun | `OrderService` |
| Interface | PascalCase, adjective or noun | `Comparable`, `List` |
| Method | camelCase, verb | `calculateTotal()` |
| Variable | camelCase, noun | `customerEmail` |
| Constant | UPPER_SNAKE | `MAX_RETRY_COUNT` |
| Package | lowercase | `com.example.orders` |

---

## Functions / Methods

### Keep Functions Small

```java
// ❌ 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

```java
// ❌ 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

```java
// ❌ 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

```java
// ❌ 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

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

// Increment counter
counter++;

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

### Good Comments

```java
// ✅ 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

```java
// ❌ 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

| Smell | Description | Refactoring |
|-------|-------------|-------------|
| **Long Method** | Method > 20 lines | Extract Method |
| **Long Parameter List** | > 3 parameters | Parameter Object |
| **Duplicate Code** | Same code in multiple places | Extract Method/Class |
| **Dead Code** | Unused code | Delete it |
| **Magic Numbers** | Unexplained literals | Named Constants |
| **God Class** | Class doing too much | Extract Class |
| **Feature Envy** | Method uses another class's data | Move Method |
| **Primitive Obsession** | Primitives instead of objects | Value Objects |

### Magic Numbers

```java
// ❌ 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

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

createUser("12345", "[email protected]", "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

| From | To | Technique |
|------|-----|-----------|
| Long method | Short methods | Extract Method |
| Duplicate code | Single method | Extract Method |
| Complex conditional | Polymorphism | Replace Conditional with Polymorphism |
| Many parameters | Object | Introduce Parameter Object |
| Temp variables | Query method | Replace Temp with Query |
| Comments explaining code | Self-documenting code | Rename, Extract |
| Nested conditionals | Early return | Guard Clauses |

### Guard Clauses

```java
// ❌ 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

© decebals · MIT · decebals/claude-code-java

Similar skills

Everything for Code review and refactoring →

clean-code by other authors comes first.

clean-code sickn33 This skill guides code writing, review, and refactoring around Clean Code principles. Use it for legacy changes, pull requests, and test-focused work. CX Codex +1 12,400installs clean-code wondelai A skill that gives coding agents a readability standard: names that carry intent, small functions, disciplined comments, one error-handling style. CX Codex +1 6,600installs clean-code pproenca A skill that feeds the agent 48 rules on naming, functions, errors and tests, drawn from Robert C. Martin's book with modern fixes. Useful during reviews and refactors. CX Codex +1 842installs clean-code davila7 Gives the agent a set of clean-code rules: small functions, intent-revealing names, no obvious comments, no needless abstraction. Useful when you want working code, not a tutorial. 7,176installs typescript-clean-code bmad-labs A skill for reviewing and refactoring TypeScript: code smell catalogs, four detection layers, and step-by-step workflows. CX Codex +1 628installs clean-code-guard amElnagdy Reviews fresh code against Clean Code and SOLID, flags the mistakes LLMs keep repeating, and runs in three modes: guard pass, live, review. CX Codex +1 4,700installs clean-code-principles AsyrafHussin A skill for architecture review and code quality: SOLID, DRY, KISS, design patterns. Useful when refactoring or weighing design decisions. CX Codex +1 1,800installs code-refactoring-refactor-clean sickn33 Analyzes code smells and plans stepwise refactoring based on SOLID and clean code principles. Helps clean tangled modules before introducing new features. CX Codex +1 1,200installs pragmatic-programmer wondelai A skill that applies the meta-principles from The Pragmatic Programmer: DRY, orthogonality, tracer bullets, contracts. Useful for architecture reviews and estimates. CX Codex +1 5,800installs safe-refactor JuliusBrussee Restructures code while preserving existing behavior, enforcing verification boundaries before structural edits. CX Codex +1 106,500installs

From the same set10

java-code-review A skill that walks Java code through a checklist: null safety, exceptions, concurrency, resource leaks. Handy before you merge a PR. CX Codex +1 1,000installs concurrency-review Reviews Java multi-threaded code for race conditions, deadlocks, and thread safety. Covers classic locks alongside Virtual Threads and CompletableFuture. CX Codex +1 345installs solid-principles Inspects Java code against SOLID principles and helps break down overloaded classes. Useful during architectural reviews and design refactoring. CX Codex +1 345installs architecture-review A skill that reviews a Java project at the macro level: package layout, module boundaries, dependency direction and layering. Useful once a codebase grows past the point where you can hold its structure in your head. CX Codex +1 338installs design-patterns Practical design patterns reference for Java with production-ready code examples. Guides coding agents to implement Builder, Factory, or Strategy during refactoring. CX Codex +1 336installs spring-boot-patterns A skill that hands your agent the package layout and templates for Spring Boot controllers, services and repositories. Useful when new code gets written or reviewed. CX Codex +1 322installs java-migration Walks a project through Java LTS upgrades: assess the codebase, fix the build, compile, test. Useful when legacy code has to reach Java 21 or 25. CX Codex +1 321installs performance-smell-detection Flags code-level performance smells in Java, covering streams, collections, boxing, and regex compiled inside loops. Helps during code reviews of performance-critical paths. CX Codex +1 310installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor