| name | coding-standards |
| description | 代碼實作階段觸發。強制執行統一的編碼規範,支援 Java、TypeScript、Go 多語言。包含 Input/Output 模式、依賴注入、不可變物件等規範,確保代碼風格一致性。 |
Coding Standards Skill
觸發時機
- 編寫新代碼時
- 代碼審查階段
- 生成 Application Service / Use Case 時
- 被 Sub-agent (command/query/reactor) 呼叫時
核心任務
強制執行統一的編碼規範,確保 AI 生成的代碼風格高度一致,降低人類審閱成本。
多語言支援
根據專案語言選擇對應的規範:
Claude Code Sub-agent 整合
當被其他 Sub-agent 呼叫時,本 Skill 提供語言特定的編碼規範:
command-sub-agent 呼叫 → 提供 Use Case / Command Handler 的編碼規範
query-sub-agent 呼叫 → 提供 Query Handler / Read Model 的編碼規範
reactor-sub-agent 呼叫 → 提供 Event Handler 的編碼規範
規範 1:Input/Output Inner Class 模式
目的
- 明確定義方法的輸入輸出契約
- 提高代碼可讀性和可維護性
- 便於單元測試
標準模式
public class CreateOrderUseCase {
public static class Input {
private final CustomerId customerId;
private final List<OrderItemRequest> items;
private final ShippingAddress address;
public Input(CustomerId customerId,
List<OrderItemRequest> items,
ShippingAddress address) {
Objects.requireNonNull(customerId, "customerId must not be null");
Objects.requireNonNull(items, "items must not be null");
if (items.isEmpty()) {
throw new IllegalArgumentException("items must not be empty");
}
this.customerId = customerId;
this.items = List.copyOf(items);
this.address = address;
}
public CustomerId getCustomerId() { return customerId; }
public List<OrderItemRequest> getItems() { return items; }
public ShippingAddress getAddress() { return address; }
}
public static class Output {
private final OrderId orderId;
private final OrderStatus status;
private final LocalDateTime createdAt;
public Output(OrderId orderId, OrderStatus status, LocalDateTime createdAt) {
this.orderId = orderId;
this.status = status;
this.createdAt = createdAt;
}
public OrderId getOrderId() { return orderId; }
public OrderStatus getStatus() { return status; }
public LocalDateTime getCreatedAt() { return createdAt; }
}
public Output execute(Input input) {
}
}
禁止模式
public OrderResult createOrder(String customerId, List<Item> items, String address) {
}
public Map<String, Object> createOrder(Map<String, Object> params) {
}
規範 2:@Bean not @Component
目的
- 集中管理依賴注入配置
- 明確的依賴關係可視化
- 便於測試時替換實作
標準模式
@Configuration
public class UseCaseConfiguration {
@Bean
public CreateOrderUseCase createOrderUseCase(
OrderRepository orderRepository,
InventoryService inventoryService,
EventPublisher eventPublisher) {
return new CreateOrderUseCase(
orderRepository,
inventoryService,
eventPublisher
);
}
@Bean
public CancelOrderUseCase cancelOrderUseCase(
OrderRepository orderRepository,
PaymentGateway paymentGateway) {
return new CancelOrderUseCase(orderRepository, paymentGateway);
}
}
public class CreateOrderUseCase {
private final OrderRepository orderRepository;
private final InventoryService inventoryService;
private final EventPublisher eventPublisher;
public CreateOrderUseCase(
OrderRepository orderRepository,
InventoryService inventoryService,
EventPublisher eventPublisher) {
this.orderRepository = orderRepository;
this.inventoryService = inventoryService;
this.eventPublisher = eventPublisher;
}
}
禁止模式
@Service
public class CreateOrderUseCase {
@Autowired
private OrderRepository orderRepository;
}
例外情況
以下情況可使用 @Component 系列註解:
| 類型 | 允許使用 | 說明 |
|---|
| Controller | @RestController | 展示層入口點 |
| Repository 實作 | @Repository | Infrastructure 層 |
| Event Listener | @Component | 技術性元件 |
| Scheduled Task | @Component | 技術性元件 |
規範 3:命名規範
Use Case / Command Handler 命名
CreateOrderUseCase
CancelOrderUseCase
UpdateCustomerProfileUseCase
CreateOrderCommandHandler
CancelOrderCommandHandler
GetOrderByIdQueryHandler
ListOrdersByCustomerQueryHandler
方法命名
public Output execute(Input input)
public void handle(CreateOrderCommand command)
public OrderDto handle(GetOrderByIdQuery query)
規範 4:不可變物件 (Immutable Objects)
Input/Output 必須是不可變的
public static class Input {
private final CustomerId customerId;
private final List<OrderItemRequest> items;
public Input(CustomerId customerId, List<OrderItemRequest> items) {
this.customerId = customerId;
this.items = List.copyOf(items);
}
public CustomerId getCustomerId() { return customerId; }
public List<OrderItemRequest> getItems() {
return items;
}
}
規範 5:例外處理模式
使用 Domain Exception
public class OrderNotFoundException extends DomainException {
public OrderNotFoundException(OrderId orderId) {
super("Order not found: " + orderId.getValue());
}
}
public class InsufficientInventoryException extends DomainException {
public InsufficientInventoryException(ProductId productId, int requested, int available) {
super(String.format(
"Insufficient inventory for product %s: requested %d, available %d",
productId.getValue(), requested, available
));
}
}
檢查清單
新增 Use Case 時
代碼審查時
自動檢查規則 (供 Linter 使用)
rules:
- id: no-component-on-usecase
pattern: "@(Component|Service).*class.*UseCase"
message: "Use @Bean configuration instead of @Component on UseCase classes"
severity: error
- id: no-autowired-field
pattern: "@Autowired\\s+private"
message: "Use constructor injection instead of field injection"
severity: error
- id: require-input-output-class
pattern: "class.*UseCase.*execute\\((?!Input)"
message: "UseCase.execute() should accept Input inner class"
severity: warning