代碼品質決定專案成敗。這 10 條鐵律源自無數血淚教訓,能助你寫出更專業、可維護、高效能的 Java 代碼。
「代碼告訴你『怎麼做』,註解告訴你『為什麼做』。」
// ❌ 無用註解
i++; // i 加 1
// ✅ 好註解:解釋業務邏輯、非顯而易見的決策、TODO
/**
* 計算動態折扣率。
* 規則:VIP 客戶滿 1000 元打 9 折,普通客戶滿 2000 元打 95 折。
* 參考:營運部 2023-Q3 促銷方案 v2.1
*/
public BigDecimal calculateDiscount(Customer customer, BigDecimal amount) {
// VIP 邏輯...
}
「簡單是可靠的前提。」—— Edsger Dijkstra
// ❌ 極簡但難讀:單行複雜條件
if(newStatusCode.equals("SD") && (sellOffDate == null || todayDate.compareTo(sellOffDate)<0 || (lastUsedDate != null && todayDate.compareTo(lastUsedDate)>0)) || (newStatusCode.equals("OBS") && (OBSDate == null || todayDate.compareTo(OBSDate)<0))){ newStatusCode = "NYP"; }
// ✅ 清晰易讀:拆解條件、命名中間變數
boolean isSellOffValid = sellOffDate == null || todayDate.isBefore(sellOffDate);
boolean isLastUsedValid = lastUsedDate == null || todayDate.isAfter(lastUsedDate);
boolean isSDCase = "SD".equals(newStatusCode) && (isSellOffValid || isLastUsedValid);
boolean isOBSDateValid = OBSDate == null || todayDate.isBefore(OBSDate);
boolean isOBSCase = "OBS".equals(newStatusCode) && isOBSDateValid;
if (isSDCase || isOBSCase) {
newStatusCode = "NYP";
}
// ❌ 硬編碼:到處散落魔術字串/數字
if (status == 1) { ... }
if ("ACTIVE".equals(type)) { ... }
timeout = 30000;
// ✅ 常數集中管理
public class OrderConstants {
public static final int STATUS_NEW = 1;
public static final int STATUS_PAID = 2;
public static final String TYPE_ACTIVE = "ACTIVE";
public static final int DEFAULT_TIMEOUT_MS = 30_000;
}
// 使用
if (status == OrderConstants.STATUS_NEW) { ... }
timeout = OrderConstants.DEFAULT_TIMEOUT_MS;
| 領域 | 推薦方案 | 避免自造 |
|---|---|---|
| Web 框架 | Spring Boot, Quarkus, Micronaut | 自寫 MVC、路由、DI 容器 |
| ORM | JPA/Hibernate, MyBatis, jOOQ | 手寫 JDBC 封裝、SQL 建構器 |
| 序列化 | Jackson, Gson, Protobuf | 手寫 JSON 解析 |
| 日誌 | SLF4J + Logback/Log4j2 | System.out.println |
| 測試 | JUnit 5, Mockito, Testcontainers | 自寫斷言、Mock 框架 |
| 工具類 | Apache Commons, Guava, Hutool | 重複造 StringUtils、CollectionUtils |
但記住第 2 條:簡單專案 (3 個頁面) 不需要 Spring Boot,JSP/Servlet 或 SparkJava 即可。
// 10,000 次迴圈 // System.out.println: ~10,520 ms // 無輸出: ~1.2 ms // 差距:8,700 倍!
@Slf4j // Lombok 自動生成 private static final Logger log
public class OrderService {
public void process(Order order) {
log.info("開始處理訂單: id={}, amount={}", order.getId(), order.getAmount());
if (log.isDebugEnabled()) { // 避免字串拼接開銷
log.debug("訂單明細: {}", order.getItems()); // 只有 DEBUG 級別才拼接
}
// 業務邏輯...
}
}
// ❌ 迴圈中拼接:O(n²) 建立大量中間物件 String result = ""; for (String s : list) result += s; // ✅ StringBuilder:O(n) 線程不安全、單執行緒首選 StringBuilder sb = new StringBuilder(); for (String s : list) sb.append(s); String result = sb.toString(); // ✅ StringBuffer:線程安全版本 (較慢) // ✅ Java 8+ String.join()、Collectors.joining()
「沒有文檔的需求只是幻覺。」
@Test
void calculateDiscount_VipCustomer_OverThreshold_Returns90Percent() { }
@Test
void placeOrder_InsufficientStock_ThrowsOutOfStockException() { }
這 10 條鐵律不只是規範,更是專業素養的體現。知道不等於做到,請從今天開始,在每次 Code Review、每次提交、每次重構時刻意練習,內化為肌肉記憶。專業,是被信任的基石。