4.8 KiB
4.8 KiB
| name | description |
|---|---|
| java-coding-standards | 針對 Spring Boot 服務的 Java 編碼標準:包含命名規範、不可變性、Optional 使用、串流 (Streams)、例外處理、泛型以及專案結構。 |
Java 編碼標準 (Java Coding Standards)
適用於 Spring Boot 服務中可讀且易於維護的 Java (17+) 程式碼標準。
何時啟用
- 在 Spring Boot 專案中編寫或審查 Java 程式碼。
- 執行有關命名、不可變性或例外處理的慣例。
- 使用 Records、Sealed Classes 或模式匹配 (Pattern Matching) (Java 17+)。
- 審查 Optional、串流或泛型的使用。
- 規劃套件結構與專案佈局。
核心原則
- 清晰重於取巧:程式碼應易於理解。
- 預設不可變:盡可能減少共享的可變狀態。
- 儘早報錯 (Fail Fast):拋出具備明確語義的例外。
- 一致性:保持命名與套件結構的一致性。
命名規範
// ✅ 類別 (Classes) / Records:PascalCase (大駝峰)
public class MarketService {}
public record Money(BigDecimal amount, Currency currency) {}
// ✅ 方法 / 欄位:camelCase (小駝峰)
private final MarketRepository marketRepository;
public Market findBySlug(String slug) {}
// ✅ 常數:UPPER_SNAKE_CASE (全大寫底線)
private static final int MAX_PAGE_SIZE = 100;
不可變性 (Immutability)
// ✅ 優先使用 Records 與 final 欄位
public record MarketDto(Long id, String name, MarketStatus status) {}
public class Market {
private final Long id;
private final String name;
// 僅提供 Getters,不提供 Setters
}
Optional 的使用
// ✅ find* 方法應回傳 Optional
Optional<Market> market = marketRepository.findBySlug(slug);
// ✅ 使用 map/flatMap 而非直接 get()
return market
.map(MarketResponse::from)
.orElseThrow(() -> new EntityNotFoundException("找不到指定的市場資料"));
串流 (Streams) 最佳實踐
// ✅ 使用串流進行轉換,保持細節簡潔,避免過長的鏈結
List<String> names = markets.stream()
.map(Market::name)
.filter(Objects::nonNull)
.toList();
// ❌ 避免過於複雜的嵌套串流;為了清晰起見,迴圈有時是更好的選擇
例外處理 (Exceptions)
- 針對領域錯誤使用未檢查例外 (Unchecked Exceptions);將技術性例外封裝並補足上下文。
- 建立領域特定的例外(例如:
MarketNotFoundException)。 - 避免使用廣泛的
catch (Exception ex),除非是為了在中心位置重新拋出或記錄。
throw new MarketNotFoundException(slug);
泛型與型別安全
- 避免使用原始型別 (Raw Types);務必宣告泛型參數。
- 在開發可重用的工具型函式時,優先考慮有界泛型 (Bounded Generics)。
public <T extends Identifiable> Map<Long, T> indexById(Collection<T> items) { ... }
專案結構 (Maven/Gradle)
src/main/java/com/example/app/
config/ # 配置類別
controller/ # REST API 控制器
service/ # 業務邏輯服務
repository/ # 資料存取層
domain/ # 實體與領域模型
dto/ # 資料傳輸物件
util/ # 工具類別
src/main/resources/
application.yml
src/test/java/... (與 main 目錄結構映射)
格式與風格
- 專案內必須一致使用 2 個或 4 個空格進行縮排。
- 每個檔案僅定義一個公開的頂層型別。
- 保持方法短小且聚焦於單一功能;適時提取輔助方法 (Helpers)。
- 成員排序:常數、欄位、建構子、公開方法、受保護方法、私有方法。
應避免的程式碼壞味道 (Code Smells)
- 過長的參數列表:應改用 DTO 或建構者模式 (Builder)。
- 深層嵌套:優先使用提早回傳 (Early Returns)。
- 魔術數字:應改用具名的常數。
- 靜態可變狀態:優先考慮使用依賴注入 (Dependency Injection)。
- 安靜的 Catch 塊:必須記錄日誌並採取行動,或重新拋出。
日誌紀錄 (Logging)
private static final Logger log = LoggerFactory.getLogger(MarketService.class);
log.info("擷取市場資料 slug={}", slug);
log.error("擷取市場資料失敗 slug={}", slug, ex);
空值 (Null) 處理
- 僅在不可避免時接受
@Nullable;否則應預設使用@NonNull。 - 在輸入端使用 Bean Validation(如
@NotNull,@NotBlank)。
測試期望
- 使用 JUnit 5 與 AssertJ 進行流暢的斷言 (Fluent Assertions)。
- 使用 Mockito 進行 Mock;盡可能避免使用部分 Mock (Partial Mocks)。
- 追求確定性的測試;不要在測試中使用隱含的休眠 (Sleep)。
請記住:保持程式碼具備意圖性、強型別且可觀察。在證明有必要進行微觀技術優化之前,應優先優化維護性。