clean-code
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClean 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
- 用户提及“clean this code”/“refactor”/“improve readability”
- 聚焦可维护性的代码评审
- 降低复杂度
- 优化命名
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(不要重复自己) | 复制粘贴的代码块 |
| KISS | Keep It Simple, Stupid(保持简单) | 过度设计的解决方案 |
| YAGNI | You Aren't Gonna Need It(你不会用到它) | “以防万一”添加的功能 |
DRY - Don't Repeat Yourself
DRY - Don't Repeat Yourself
"Every piece of knowledge must have a single, unambiguous representation in the system."
"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
}
}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
}
}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
DRY例外情况
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并非所有重复都是坏的。避免过早抽象:
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 differentlyKISS - Keep It Simple
KISS - 保持简单
"The simplest solution is usually the best."
"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);
}
}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+
}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
KISS检查清单
- 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?
- 初级开发者能在30秒内理解这段代码吗?
- 是否可以用标准库实现更简单的方案?
- 我是否在为可能永远不会出现的边缘情况增加复杂度?
YAGNI - You Aren't Gonna Need It
YAGNI - 你不会用到它
"Don't add functionality until it's necessary."
"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 savejava
// ❌ 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 saveRefactored
重构后
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 beforejava
// ✅ GOOD: Only what's needed now
public interface UserRepository {
Optional<User> findById(Long id);
User save(User user);
}
// Add methods when actually needed, not beforeYAGNI Signs
YAGNI识别迹象
- "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
- “我们以后可能会需要这个”
- “让我们把它做成可配置的,以防万一”
- “如果我们以后需要支持X怎么办?”
- 只有一个实现的抽象类
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;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;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();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 { }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 | |
| Interface | PascalCase, adjective or noun | |
| Method | camelCase, verb | |
| Variable | camelCase, noun | |
| Constant | UPPER_SNAKE | |
| Package | lowercase | |
| 元素 | 规范 | 示例 |
|---|---|---|
| 类 | PascalCase,名词 | |
| 接口 | PascalCase,形容词或名词 | |
| 方法 | camelCase,动词 | |
| 变量 | camelCase,名词 | |
| 常量 | UPPER_SNAKE | |
| 包 | 小写 | |
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);
}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);
}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) {
// ...
}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
}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) {
// ...
}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);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())) {
// ...
}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 |
| 代码异味 | 描述 | 重构方案 |
|---|---|---|
| 长方法 | 方法超过20行 | 提取方法 |
| 长参数列表 | 参数超过3个 | 引入参数对象 |
| 重复代码 | 多处存在相同代码 | 提取方法/类 |
| 死代码 | 未使用的代码 | 删除代码 |
| 魔法值 | 无解释的字面量 | 命名常量 |
| 上帝类 | 类承担过多职责 | 提取类 |
| 特性依恋 | 方法过度依赖另一个类的数据 | 移动方法 |
| 原始类型痴迷 | 使用原始类型而非对象 | 值对象 |
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);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", "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
}java
// ❌ 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
重构快速参考
| 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
}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
相关技能
- - Design principles for class structure
solid-principles - - Common solutions to recurring problems
design-patterns - - Comprehensive review checklist
java-code-review
- - 类结构设计原则
solid-principles - - 常见问题的通用解决方案
design-patterns - - 全面的评审检查清单
java-code-review