| name | clean-code |
| description | Clean Code principles (DRY, KISS, YAGNI), naming conventions, function design, and refactoring. Use when user says "clean this code", "refactor", "improve readability", or when reviewing code quality. |
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
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");
}
}
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");
}
}
}
Refactored
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());
}
public void updateUser(UserRequest request) {
emailValidator.validate(request.getEmail());
}
}
DRY Exceptions
Not all duplication is bad. Avoid premature abstraction:
public BigDecimal calculateShippingCost(Order order) {
return order.getWeight().multiply(SHIPPING_RATE);
}
public BigDecimal calculateInsuranceCost(Order order) {
return order.getValue().multiply(INSURANCE_RATE);
}
KISS - Keep It Simple
"The simplest solution is usually the best."
Violation
public class StringUtils {
public boolean isEmpty(String str) {
return Optional.ofNullable(str)
.map(String::trim)
.map(String::isEmpty)
.orElseGet(() -> Boolean.TRUE);
}
}
Refactored
public class StringUtils {
public boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
}
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
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();
}
Refactored
public interface UserRepository {
Optional<User> findById(Long id);
User save(User user);
}
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
int d;
String s;
List<User> list;
Map<String, Object> m;
int elapsedTimeInDays;
String customerName;
List<User> activeUsers;
Map<String, Object> sessionAttributes;
Booleans
boolean flag;
boolean status;
boolean check;
boolean isActive;
boolean hasPermission;
boolean canEdit;
boolean shouldNotify;
Methods
void process();
void handle();
void doIt();
User get();
void processPayment();
void handleLoginRequest();
void sendWelcomeEmail();
User findByEmail(String email);
List<Order> fetchPendingOrders();
Classes
class Data { }
class Info { }
class Manager { }
class Helper { }
class Utils { }
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
public void processOrder(Order order) {
}
public void processOrder(Order order) {
validateOrder(order);
calculateTotals(order);
applyDiscounts(order);
updateInventory(order);
sendNotifications(order);
}
Single Level of Abstraction
public void processOrder(Order order) {
validateOrder(order);
BigDecimal total = BigDecimal.ZERO;
for (OrderItem item : order.getItems()) {
total = total.add(item.getPrice().multiply(
BigDecimal.valueOf(item.getQuantity())));
}
sendEmail(order);
}
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
public User createUser(String firstName, String lastName,
String email, String phone,
String address, String city,
String country, String zipCode) {
}
public User createUser(CreateUserRequest request) {
}
public User createUser(UserBuilder builder) {
}
Avoid Flag Arguments
public void sendMessage(String message, boolean isUrgent) {
if (isUrgent) {
} else {
}
}
public void sendUrgentMessage(String message) {
}
public void queueMessage(String message) {
}
Comments
Avoid Obvious Comments
user.setName(name);
counter++;
if (user != null) {
}
Good Comments
for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
Thread.sleep((long) Math.pow(2, attempt) * 1000);
}
private Map<String, User> userCache = new ConcurrentHashMap<>();
applyDiscounts(order);
calculateTax(order);
Let Code Speak
if ((user.getRole() == 1 || user.getRole() == 2) &&
(action == 3 || action == 4 || action == 7)) {
}
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
if (user.getAge() >= 18) { }
if (order.getTotal() > 100) { }
Thread.sleep(86400000);
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
public void createUser(String email, String phone, String zipCode) {
}
createUser("12345", "john@email.com", "555-1234");
public record Email(String value) {
public Email {
if (!value.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
}
}
public record PhoneNumber(String value) {
}
public void createUser(Email email, PhoneNumber phone, ZipCode zipCode) {
}
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
public void processOrder(Order order) {
if (order != null) {
if (order.isValid()) {
if (order.hasItems()) {
}
}
}
}
public void processOrder(Order order) {
if (order == null) return;
if (!order.isValid()) return;
if (!order.hasItems()) return;
}
Clean Code Checklist
When reviewing code, check:
Related Skills
solid-principles - Design principles for class structure
design-patterns - Common solutions to recurring problems
java-code-review - Comprehensive review checklist