一键导入
clean-code
Use when reviewing or writing code to enforce DRY, KISS, and YAGNI principles with Java-specific guidance.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when reviewing or writing code to enforce DRY, KISS, and YAGNI principles with Java-specific guidance.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when implementing Spring Boot 3.x applications. Provides hands-on implementation patterns for web, data, security, testing, and cloud-native development.
Review REST API contracts for HTTP semantics, versioning, backward compatibility, and response consistency. Use when user asks "review API", "check endpoints", "REST review", or before releasing API changes.
Use when designing Spring Boot 3.x application architecture, making technology decisions, or planning project structure. Provides architectural patterns and references for project setup, JPA, security, testing, and reactive programming.
Use when designing, reviewing, or modifying REST API endpoints to enforce proper HTTP verbs, status codes, versioning, and API contract best practices.
Use when implementing or reviewing code that benefits from established design patterns like Builder, Factory, Strategy, Observer, Decorator, or Adapter.
Use when designing Spring Boot 3.x application architecture, making technology decisions, or planning project structure. Provides architectural patterns and references for project setup, JPA, security, testing, and reactive programming.
| name | clean-code |
| description | Use when reviewing or writing code to enforce DRY, KISS, and YAGNI principles with Java-specific guidance. |
Extract repeated logic into reusable methods or classes.
@RestController
@RequestMapping("/api")
public class OrderController {
@PostMapping("/orders")
public ResponseEntity<Order> createOrder(@RequestBody OrderRequest request) {
if (request.getCustomerId() == null || request.getCustomerId().isBlank()) {
throw new IllegalArgumentException("Customer ID is required");
}
if (request.getAmount() == null || request.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
// ... create order
}
@PutMapping("/orders/{id}")
public ResponseEntity<Order> updateOrder(@PathVariable Long id, @RequestBody OrderRequest request) {
if (request.getCustomerId() == null || request.getCustomerId().isBlank()) {
throw new IllegalArgumentException("Customer ID is required");
}
if (request.getAmount() == null || request.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
// ... update order
}
}
public record OrderRequest(
@NotBlank(message = "Customer ID is required")
String customerId,
@NotNull(message = "Amount is required")
@Positive(message = "Amount must be positive")
BigDecimal amount,
@NotEmpty(message = "At least one item is required")
List<@Valid OrderItemRequest> items
) {}
public record OrderItemRequest(
@NotBlank String productId,
@Min(1) int quantity
) {}
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping
public ResponseEntity<OrderResponse> createOrder(@Valid @RequestBody OrderRequest request) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(orderService.create(request));
}
@PutMapping("/{id}")
public ResponseEntity<OrderResponse> updateOrder(
@PathVariable Long id,
@Valid @RequestBody OrderRequest request) {
return ResponseEntity.ok(orderService.update(id, request));
}
}
@Component
public class OrderMapper {
public Order toEntity(OrderRequest request) {
Order order = new Order();
order.setCustomerId(request.customerId());
order.setAmount(request.amount());
order.setItems(request.items().stream()
.map(this::toItemEntity)
.toList());
return order;
}
public OrderResponse toResponse(Order order) {
return new OrderResponse(
order.getId(),
order.getCustomerId(),
order.getAmount(),
order.getStatus().name(),
order.getCreatedAt()
);
}
private OrderItem toItemEntity(OrderItemRequest request) {
OrderItem item = new OrderItem();
item.setProductId(request.productId());
item.setQuantity(request.quantity());
return item;
}
}
Avoid unnecessary complexity. Prefer straightforward solutions.
public abstract class AbstractGenericCrudService<T, ID, R extends JpaRepository<T, ID>> {
protected final R repository;
protected final Function<T, ?> entityToDto;
protected final Function<?, T> dtoToEntity;
// ... 200 lines of generic plumbing
}
@Service
public class ProductService {
private final ProductRepository productRepository;
private final ProductMapper productMapper;
public ProductService(ProductRepository productRepository, ProductMapper productMapper) {
this.productRepository = productRepository;
this.productMapper = productMapper;
}
public ProductResponse findById(Long id) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Product", id));
return productMapper.toResponse(product);
}
public Page<ProductResponse> findAll(Pageable pageable) {
return productRepository.findAll(pageable)
.map(productMapper::toResponse);
}
@Transactional
public ProductResponse create(ProductRequest request) {
Product product = productMapper.toEntity(request);
Product saved = productRepository.save(product);
return productMapper.toResponse(saved);
}
}
// Simple, centralized exception handling
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse(ex.getMessage()));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult().getFieldErrors().stream()
.map(f -> f.getField() + ": " + f.getDefaultMessage())
.toList();
return ResponseEntity.badRequest()
.body(new ErrorResponse("Validation failed", errors));
}
}
public record ErrorResponse(String message, List<String> details) {
public ErrorResponse(String message) {
this(message, List.of());
}
}
Do not build features or abstractions until they are needed.
// Building a plugin system when you only have one implementation
public interface NotificationStrategy {
void send(Notification notification);
}
public class NotificationStrategyFactory {
private final Map<String, NotificationStrategy> strategies;
// ... when you only ever send emails
}
@Service
public class NotificationService {
private final JavaMailSender mailSender;
public NotificationService(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void sendOrderConfirmation(Order order, String recipientEmail) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(recipientEmail);
message.setSubject("Order Confirmation #" + order.getId());
message.setText("Your order has been confirmed. Total: " + order.getAmount());
mailSender.send(message);
}
}
public OrderResponse processOrder(OrderRequest request) {
// validate customer (10 lines)
// check inventory (15 lines)
// calculate price (20 lines)
// apply discounts (15 lines)
// create order (10 lines)
// send notification (10 lines)
// return response (5 lines)
}
@Service
public class OrderProcessingService {
private final CustomerService customerService;
private final InventoryService inventoryService;
private final PricingService pricingService;
private final OrderRepository orderRepository;
private final NotificationService notificationService;
private final OrderMapper orderMapper;
public OrderProcessingService(CustomerService customerService,
InventoryService inventoryService,
PricingService pricingService,
OrderRepository orderRepository,
NotificationService notificationService,
OrderMapper orderMapper) {
this.customerService = customerService;
this.inventoryService = inventoryService;
this.pricingService = pricingService;
this.orderRepository = orderRepository;
this.notificationService = notificationService;
this.orderMapper = orderMapper;
}
@Transactional
public OrderResponse processOrder(OrderRequest request) {
Customer customer = customerService.getVerifiedCustomer(request.customerId());
inventoryService.reserveItems(request.items());
BigDecimal total = pricingService.calculateTotal(request.items(), customer);
Order order = orderMapper.toEntity(request);
order.setTotalAmount(total);
order.setStatus(OrderStatus.CONFIRMED);
Order saved = orderRepository.save(order);
notificationService.sendOrderConfirmation(saved, customer.getEmail());
return orderMapper.toResponse(saved);
}
}
PascalCase - OrderService, ProductControllercamelCase - findById, calculateTotalUPPER_SNAKE_CASE - MAX_RETRY_COUNTpl.piomin.services.order.controlleris, has, can - isActive, hasPermissionList<Order> orders, Set<String> tags