원클릭으로
java-coding-standards
適用於 Spring Boot 與 Quarkus 服務的 Java 編碼標準:命名、不可變性、Optional 使用方式、Streams、例外處理、泛型、CDI、Reactive 模式與專案結構。會依框架自動套用對應慣例。
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
適用於 Spring Boot 與 Quarkus 服務的 Java 編碼標準:命名、不可變性、Optional 使用方式、Streams、例外處理、泛型、CDI、Reactive 模式與專案結構。會依框架自動套用對應慣例。
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
從棕地專案(brownfield project)的既有程式碼中回推、產生、補齊規格文件。 適用於任何前端(Vue / React / Angular / 任意框架)與後端(Node.js / Python / Go / 任意語言)專案, 不限定框架或語言。 當使用者提到「回推規格」、「補規格書」、「產生規格文件」、「從 code 生成文件」、 「reverse engineer spec」、「recover specification」、「建立文件」、 「幫我寫規格」、「這段 code 的規格是什麼」、「分析這個模組」, 或者使用者給了一段程式碼或一個專案目錄要求產出文件時,都應觸發本技能。 也適用於使用者想對某個特定檔案、元件、API、模組產生規格描述的情境。 即使使用者只說「幫我看看這段 code」但上下文暗示需要文件化,也應主動觸發。 Chinese triggers: "規格書", "規格文件", "產生規格", "文件化", "棕地專案", "逆向工程文件"
依據 8 大核心原則審查程式碼的註解品質——解釋 Why 而非 What、說明魔法數字與 Hack 的原因、標示 Caveat 與副作用、TODO/FIXME 標籤規範、公開 API 合約文件、記錄未採納方案(Why Not)、連結外部脈絡、以及保持註解新鮮度。當使用者說「幫我審查/檢查/看一下這段程式碼的註解」、「這段程式碼有沒有文件」、「review my comments」、「這樣寫 OK 嗎」並貼上含有值得評估的註解的程式碼時,主動觸發此 Skill。進行 Code Review 且評估範圍包含文件品質時也應觸發。輸出為結構化審查報告,不修改程式碼。
Vue 官方 Style Guide 的規則知識庫,涵蓋 Priority A–D 共 26 條規則(多字元件命名、詳細 prop 定義、keyed v-for、避免 v-if 與 v-for 同元素、scoped 樣式、元件檔案組織與命名 casing、self-closing、多屬性換行、模板簡單表達式、computed 拆分、options/屬性順序、避免隱式父子通訊等),Composition API 與 Options API 範例並陳。撰寫或修改 Vue/Nuxt 程式碼時用來讓產出一開始就符合規範;審查既有 .vue 元件時用來找出違規。只要使用者在新增、修改、重構或審查 Vue 單檔元件(SFC)、template、props、v-for、元件命名、emit/事件、SFC 樣式時,就主動使用本 skill——即使使用者沒有明講「style guide」「規範」「best practice」。涉及 Vue 元件的 code review 也應納入本 skill 的檢查項目。
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes. New files are written to `/Users/dannychou/danObsidian/ai-draft/` by default unless the user specifies a different output path.
通用軟體開發工作流程,適用於新增功能、修正功能、重構等程式開發需求。 以棕地專案為預設情境(保護既有行為、最小擾動),同時支援綠地專案豁免。 涵蓋五個階段:需求分析、程式碼探索、設計(計畫)、開發(棕地 TDD 任務清單)、驗證。 每個階段會產生對應的 Markdown 文件(analysis.md、plan.md、task.md、followups.md)供下一階段參考。 當使用者提出功能開發、Bug 修復、重構等需求時,主動使用此 Skill 引導整個開發流程。 觸發情境:「新增功能」、「修正功能」、「開發需求」、「implement」、「fix」、「refactor」、「建立需求」、「開發流程」。
Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.
| name | java-coding-standards |
| description | 適用於 Spring Boot 與 Quarkus 服務的 Java 編碼標準:命名、不可變性、Optional 使用方式、Streams、例外處理、泛型、CDI、Reactive 模式與專案結構。會依框架自動套用對應慣例。 |
適用於 Spring Boot 與 Quarkus 服務中可讀、可維護的 Java 17+ 程式碼標準。
套用標準前,先從 build file 判斷使用的框架:
quarkus → 套用 [QUARKUS] 慣例spring-boot → 套用 [SPRING] 慣例以下章節提供 Spring Boot、Quarkus 與共用 Java 範例,涵蓋命名、不可變性、依賴注入、Reactive 程式碼、例外處理、專案結構、日誌、設定與測試。
// PASS: Class / Record 使用 PascalCase
public class MarketService {}
public record Money(BigDecimal amount, Currency currency) {}
// PASS: Method / Field 使用 camelCase
private final MarketRepository marketRepository;
public Market findBySlug(String slug) {}
// PASS: 常數使用 UPPER_SNAKE_CASE
private static final int MAX_PAGE_SIZE = 100;
// PASS: [QUARKUS] JAX-RS resource 命名為 *Resource,不使用 *Controller
public class MarketResource {}
// PASS: [SPRING] REST controller 命名為 *Controller
public class MarketController {}
// PASS: 優先使用 record 與 final field
public record MarketDto(Long id, String name, MarketStatus status) {}
public class Market {
private final Long id;
private final String name;
// 僅提供 getter,不提供 setter
}
// PASS: [QUARKUS] Panache active-record entity 使用 public field,這是 Quarkus 慣例
@Entity
public class Market extends PanacheEntity {
public String name;
public MarketStatus status;
// Panache 會在 build time 產生 accessor;public field 是慣用寫法
}
// PASS: [QUARKUS] Panache MongoDB entity
@MongoEntity(collection = "markets")
public class Market extends PanacheMongoEntity {
public String name;
public MarketStatus status;
}
// PASS: find* 方法回傳 Optional
// [SPRING]
Optional<Market> market = marketRepository.findBySlug(slug);
// [QUARKUS] Panache
Optional<Market> market = Market.find("slug", slug).firstResultOptional();
// PASS: 使用 map / flatMap,避免直接 get()
return market
.map(MarketResponse::from)
.orElseThrow(() -> new EntityNotFoundException("Market not found"));
// PASS: Streams 適合用於資料轉換,pipeline 應保持簡短
List<String> names = markets.stream()
.map(Market::name)
.filter(Objects::nonNull)
.toList();
// FAIL: 避免複雜巢狀 streams;可讀性不足時改用 loop
// PASS: [SPRING] Constructor injection,優先於 field 上使用 @Autowired
@Service
public class MarketService {
private final MarketRepository marketRepository;
public MarketService(MarketRepository marketRepository) {
this.marketRepository = marketRepository;
}
}
// PASS: [QUARKUS] Constructor injection
@ApplicationScoped
public class MarketService {
private final MarketRepository marketRepository;
@Inject
public MarketService(MarketRepository marketRepository) {
this.marketRepository = marketRepository;
}
}
// PASS: [QUARKUS] Package-private field injection 可接受,可避免 proxy 問題
@ApplicationScoped
public class MarketService {
@Inject
MarketRepository marketRepository;
}
// FAIL: [SPRING] 避免使用 @Autowired field injection
@Autowired
private MarketRepository marketRepository; // 改用 constructor injection
// FAIL: [QUARKUS] 需要 interception 或 lazy init 時,不使用 @Singleton
@Singleton // non-proxyable,改用 @ApplicationScoped
public class MarketService {}
// PASS: Reactive endpoint 回傳 Uni / Multi
@GET
@Path("/{slug}")
public Uni<Market> findBySlug(@PathParam("slug") String slug) {
return Market.find("slug", slug)
.<Market>firstResult()
.onItem().ifNull().failWith(() -> new MarketNotFoundException(slug));
}
// PASS: 使用 non-blocking pipeline 組合流程
public Uni<OrderConfirmation> placeOrder(OrderRequest req) {
return validateOrder(req)
.chain(valid -> persistOrder(valid))
.chain(order -> notifyFulfillment(order));
}
// FAIL: 不要在 Uni / Multi pipeline 中執行 blocking call
public Uni<Market> find(String slug) {
Market m = Market.find("slug", slug).firstResult(); // BLOCKING,會破壞 event loop
return Uni.createFrom().item(m);
}
// FAIL: 避免對 shared Uni 重複 subscribe
Uni<Market> shared = fetchMarket(slug);
shared.subscribe().with(m -> log(m));
shared.subscribe().with(m -> cache(m)); // double subscribe,應使用 Uni.memoize()
MarketNotFoundExceptioncatch (Exception ex),除非會集中重新拋出或記錄throw new MarketNotFoundException(slug);
// [SPRING]
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MarketNotFoundException.class)
public ResponseEntity<ErrorResponse> handle(MarketNotFoundException ex) {
return ResponseEntity.status(404).body(ErrorResponse.from(ex));
}
}
// [QUARKUS] 選項 A:ExceptionMapper
@Provider
public class MarketNotFoundMapper implements ExceptionMapper<MarketNotFoundException> {
@Override
public Response toResponse(MarketNotFoundException ex) {
return Response.status(404).entity(ErrorResponse.from(ex)).build();
}
}
// [QUARKUS] 選項 B:@ServerExceptionMapper(RESTEasy Reactive)
@ServerExceptionMapper
public RestResponse<ErrorResponse> handle(MarketNotFoundException ex) {
return RestResponse.status(Status.NOT_FOUND, ErrorResponse.from(ex));
}
public <T extends Identifiable> Map<Long, T> indexById(Collection<T> items) { ... }
src/main/java/com/example/app/
config/
controller/
service/
repository/
domain/
dto/
util/
src/main/resources/
application.yml
src/test/java/... (mirrors main)
src/main/java/com/example/app/
config/ # @ConfigMapping、@ConfigProperty beans、Producers
resource/ # JAX-RS resources,不使用 "controller"
service/
repository/ # PanacheRepository implementations;若未使用 active record
domain/ # JPA / Panache entities、MongoDB entities
dto/
util/
mapper/ # MapStruct mappers;若有使用
src/main/resources/
application.properties # Quarkus 慣例;YAML 可搭配 quarkus-config-yaml
import.sql # Hibernate dev / test 自動匯入資料
src/test/java/... (mirrors main)
@ApplicationScoped 時誤用 @Singleton,會破壞 proxying 與 interceptionquarkus-resteasy-reactive 與 quarkus-resteasy classic,應選定一種 stack// [SPRING] SLF4J
private static final Logger log = LoggerFactory.getLogger(MarketService.class);
log.info("fetch_market slug={}", slug);
log.error("failed_fetch_market slug={}", slug, ex);
// [QUARKUS] JBoss Logging,預設支援 build-time zero-cost
private static final Logger log = Logger.getLogger(MarketService.class);
log.infof("fetch_market slug=%s", slug);
log.errorf(ex, "failed_fetch_market slug=%s", slug);
// [QUARKUS] 替代方案:使用 @Inject 簡化 logging
@Inject
Logger log; // CDI-injected,作用域對應宣告的 class
@Nullable;其他情況使用 @NonNull@NotNull、@NotBlank@BeanParam、@RestForm 與 request body parameters 上套用 @Valid// [SPRING] @ConfigurationProperties
@ConfigurationProperties(prefix = "market")
public record MarketProperties(int maxPageSize, Duration cacheTtl) {}
// [QUARKUS] @ConfigMapping,type-safe,build-time validated
@ConfigMapping(prefix = "market")
public interface MarketConfig {
int maxPageSize();
Duration cacheTtl();
}
// [QUARKUS] 使用 @ConfigProperty 注入簡單值
@ConfigProperty(name = "market.max-page-size", defaultValue = "100")
int maxPageSize;
@WebMvcTest 測試 controller slice,使用 @DataJpaTest 測試 repository slice@SpringBootTest 保留給完整 integration test@MockBean 替換 Spring context 中的 bean@QuarkusTest@QuarkusTest 保留給 CDI integration test@InjectMock 替換 integration test 中的 CDI bean@QuarkusTestResource 管理自訂外部服務生命週期// [SPRING] Controller test
@WebMvcTest(MarketController.class)
class MarketControllerTest {
@Autowired MockMvc mockMvc;
@MockBean MarketService marketService;
}
// [QUARKUS] Integration test
@QuarkusTest
class MarketResourceTest {
@InjectMock
MarketService marketService;
@Test
void should_return_404_when_market_not_found() {
given().when().get("/markets/unknown").then().statusCode(404);
}
}
// [QUARKUS] Unit test,不使用 CDI,不使用 @QuarkusTest
@ExtendWith(MockitoExtension.class)
class MarketServiceTest {
@Mock MarketRepository marketRepository;
@InjectMocks MarketService marketService;
}
記住:程式碼應具備明確意圖、型別安全與可觀測性。除非已有證據證明需要微優化,否則優先追求可維護性。