claude-code/claude-zh/skills/java-coding-standards/SKILL.md

4.8 KiB
Raw Permalink Blame History

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) / RecordsPascalCase (大駝峰)
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)。

請記住:保持程式碼具備意圖性、強型別且可觀察。在證明有必要進行微觀技術優化之前,應優先優化維護性。