关于 clean-code
用于依据 Clean Code 原则提升代码可读性和可维护性的技能,适合重构与代码审查,并提供命名、函数、重复代码和常见代码异味方面的指导。
主要功能
- 01应用 DRY、KISS 和 YAGNI 原则
- 02指导清晰命名与函数聚焦
- 03识别重复代码和常见代码异味
- 04提供重构方法和审查清单
适用场景
- 01重构代码以提升可读性
- 02审查可维护性与复杂度
- 03改进命名并减少重复逻辑
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ decebals/ claude-code-java --skill clean-code安装后在 Claude Code 中输入/clean-code确认已加载。
附带文件README.md
详细介绍
Clean Code 技能
遵循 Clean Code 原则,编写可读、易维护的代码。
适用场景
- 用户说“清理这段代码”/“重构”/“提高可读性”
- 侧重可维护性的代码审查
- 降低复杂度
- 改进命名
核心原则
| 原则 | 含义 | 违反迹象 |
|---|---|---|
| DRY | 不要重复自己 | 复制粘贴的代码块 |
| KISS | 保持简单 | 过度设计的解决方案 |
| YAGNI | 你不会需要它 | “以防万一”添加的功能 |
DRY - 不要重复自己
“系统中的每一条知识都必须有单一且明确的表示。”
违反示例
// ❌ 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
}
}
重构后
// ✅ 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 的例外情况
并非所有重复都是坏事。避免过早抽象:
// 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 - 保持简单
“最简单的解决方案通常就是最好的。”
违反示例
// ❌ 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);
}
}
重构后
// ✅ 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 检查清单
- 初级开发者能在 30 秒内看懂这段代码吗?
- 使用标准库是否有更简单的实现方式?
- 我是否在为可能永远不会发生的边缘情况增加复杂度?
YAGNI - 你不会需要它
“必要之前,不要添加功能。”
违反示例
// ❌ 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
重构后
// ✅ 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 的迹象
- “以后我们可能会需要这个”
- “我们把它做成可配置的吧,以防万一”
- “如果将来需要支持 X 怎么办?”
- 只有一个实现的抽象类
命名约定
变量
// ❌ 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;
布尔值
// ❌ BAD
boolean flag;
boolean status;
boolean check;
// ✅ GOOD - Use is/has/can/should prefix
boolean isActive;
boolean hasPermission;
boolean canEdit;
boolean shouldNotify;
方法
// ❌ 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();
类
// ❌ 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 { }
命名约定表
| 元素 | 约定 | 示例 |
|---|---|---|
| 类 | PascalCase,名词 | OrderService |
| 接口 | PascalCase,形容词或名词 | Comparable、List |
| 方法 | camelCase,动词 | calculateTotal() |
| 变量 | camelCase,名词 | customerEmail |
| 常量 | UPPER_SNAKE | MAX_RETRY_COUNT |
| 包 | 小写 | com.example.orders |
函数/方法
保持函数简短
// ❌ 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);
}
保持单一抽象层级
// ❌ 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);
}
限制参数数量
// ❌ 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) {
// ...
}
避免标志参数
// ❌ 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
}
注释
避免显而易见的注释
// ❌ BAD: Noise comments
// Set the user's name
user.setName(name);
// Increment counter
counter++;
// Check if user is null
if (user != null) {
// ...
}
有价值的注释
// ✅ 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);
让代码自己说明
// ❌ 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())) {
// ...
}
常见代码异味
| 异味 | 描述 | 重构方式 |
|---|---|---|
| 长方法 | 方法超过 20 行 | 提取方法 |
| 参数列表过长 | 参数超过 3 个 | 参数对象 |
| 重复代码 | 多处存在相同代码 | 提取方法/类 |
| 死代码 | 未使用的代码 | 删除 |
| 魔法数字 | 未说明含义的字面量 | 命名常量 |
| 上帝类 | 承担过多职责的类 | 提取类 |
| 特性嫉妒 | 方法使用另一个类的数据 | 移动方法 |
| 基本类型偏执 | 使用基本类型而非对象 | 值对象 |
魔法数字
// ❌ 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);
基本类型偏执
// ❌ 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
}
重构速查表
| 从 | 到 | 技术 |
|---|---|---|
| 长方法 | 短方法 | 提取方法 |
| 重复代码 | 单个方法 | 提取方法 |
| 复杂条件判断 | 多态 | 用多态替换条件判断 |
| 参数过多 | 对象 | 引入参数对象 |
| 临时变量 | 查询方法 | 用查询替换临时变量 |
| 解释代码的注释 | 自解释代码 | 重命名、提取 |
| 嵌套条件判断 | 提前返回 | 守卫子句 |
守卫子句
// ❌ 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 检查清单
审查代码时,请检查:
- 名称是否有意义且易于发音?
- 函数是否简短且专注?
- 是否存在重复代码?
- 是否存在魔法数字或字符串?
- 注释解释的是“为什么”,而非“是什么”吗?
- 代码是否处于一致的抽象层级?
- 是否能简化任何代码?
- 是否存在死代码/未使用的代码?
相关技能
solid-principles- 类结构的设计原则design-patterns- 常见问题的通用解决方案java-code-review- 全面的审查清单
评论
支持 Markdown