aslan-server/claude/ai-context/CODING_STYLE.md
2026-03-22 23:19:22 +08:00

6.3 KiB
Raw Blame History

编码风格规范

一、命名规范

类型 命名规则 示例
Controller {功能}RestController LotteryActivityRestController
Service 接口 {功能}Service LotteryActivityRestService
Service 实现 {功能}ServiceImpl LotteryActivityRestServiceImpl
写操作执行器 {功能}CmdExe{功能}Exe LotteryDrawExe
查询执行器 {功能}QryExe LotteryRecordQryExe
写命令 {功能}Cmd LotteryDrawCmd
查询命令 {功能}QryCmd LotteryRecordQryCmd
返回对象 {功能}CO LotteryDrawResultCO
DAO {实体名}DAO LotteryTicketDAO
Entity {实体名} LotteryTicket
数据库服务 {功能}DatabaseService LotteryActivityDatabaseService
Gateway {功能}Gateway + {功能}GatewayImpl LotteryActivityGateway

二、Controller 规范

/**
 * 功能说明.
 *
 * @author xxx
 * @eo.api-type http
 * @eo.groupName 模块名.子模块名
 * @eo.path /模块/资源
 */
@RestController
@RequestMapping(value = "/user/user-profile", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class UserProfileRestController extends BaseController {

    private final UserProfileService userProfileService;

    /**
     * 接口说明.
     *
     * @eo.name 接口名称
     * @eo.url /具体路径GET 无路径时留空)
     * @eo.method get/post/put/delete
     * @eo.request-type formdataGET/ jsonPOST/PUT
     */
    @GetMapping
    public UserProfileDTO getProfile(UserProfileQryCmd cmd) {
        return userProfileService.getUserProfile(cmd);
    }

    @PostMapping("/draw")
    public LotteryDrawResultCO draw(@RequestBody @Validated LotteryDrawCmd cmd) {
        return lotteryService.draw(cmd);
    }
}

关键点

  • 继承 BaseController
  • @RequiredArgsConstructor(构造器注入)
  • API 文档用 @eo. 注解,不用 Swagger
  • GET 请求参数直接用 Cmd 对象接收(无 @RequestBody
  • POST/PUT 用 @RequestBody @Validated

三、Cmd / CO 规范

// 写命令 - 继承 AppExtCommand包含 reqUserId 等公共字段)
@Data
public class LotteryDrawCmd extends AppExtCommand {
    @NotNull
    private Long activityId;

    @Min(1) @Max(10)
    private Integer drawCount;
}

// 查询命令 - 分页继承 PageQueryCmd
@Data
public class LotteryRecordQryCmd extends PageQueryCmd {
    private Long activityId;
}

// 返回对象
@Data
public class LotteryDrawResultCO {
    private Long prizeId;
    private String prizeName;
}

规则

  • 校验注解用 jakarta.validation.constraints.*(不用 javax
  • Cmd 需要用户身份时继承 AppExtCommand,通过 cmd.getReqUserId() 获取当前用户

四、Service / CmdExe 规范

// ServiceImpl - 门面,调用 CmdExe
@Service
@RequiredArgsConstructor
@Slf4j
public class LotteryActivityRestServiceImpl implements LotteryActivityRestService {
    private final LotteryDrawExe lotteryDrawExe;
    private final LotteryRecordQryExe recordQryExe;

    @Override
    public LotteryDrawResultCO draw(LotteryDrawCmd cmd) {
        return lotteryDrawExe.execute(cmd);
    }
}

// CmdExe - 核心业务逻辑
@Component
@RequiredArgsConstructor
@Slf4j
public class LotteryDrawExe {
    private final LotteryActivityDatabaseService lotteryDbService;

    @Transactional
    public LotteryDrawResultCO execute(LotteryDrawCmd cmd) {
        // 1. 参数校验
        // 2. 业务逻辑
        // 3. 记录日志
        log.info("用户抽奖: userId={}, activityId={}", cmd.getReqUserId(), cmd.getActivityId());
        // 4. 返回结果
    }
}

五、Infrastructure 规范

// DAO - 继承 BaseDAO
public interface LotteryTicketDAO extends BaseDAO<LotteryTicket> {}

// DatabaseService - 简单场景直接用
@Service
@RequiredArgsConstructor
public class LotteryActivityDatabaseService {
    private final LotteryTicketDAO ticketDAO;

    public void consumeTicket(Long userId, Long activityId) {
        LambdaQueryWrapper<LotteryTicket> wrapper = new LambdaQueryWrapper<LotteryTicket>()
            .eq(Objects.nonNull(userId), LotteryTicket::getUserId, userId)
            .eq(Objects.nonNull(activityId), LotteryTicket::getActivityId, activityId);
        // ...
    }
}

// Gateway - 复杂场景:锁 + 缓存 + 多数据源
@Component
@RequiredArgsConstructor
public class LotteryActivityGatewayImpl implements LotteryActivityGateway {
    private final LotteryTicketDAO ticketDAO;
    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public void consumeTicketWithLock(Long userId, Long activityId) {
        String lockKey = "lottery:lock:" + userId;
        // 分布式锁 + DB 操作 + 缓存更新
    }
}

六、通用代码规范

条件判断

// ✅
if (StringUtils.isNotBlank(name)) { ... }
if (Objects.nonNull(userId)) { ... }

// ❌
if (name != null && !name.isEmpty()) { ... }
if (userId != null) { ... }

金额

// ✅
BigDecimal amount = new BigDecimal("100.00");
BigDecimal total = a.add(b);

// ❌ 禁止
double amount = 100.00;

返回分页

return PageResult.of(records, total, cmd.getPageNum(), cmd.getPageSize());

异常

// ✅
throw new BusinessException("抽奖券不足");

// ❌
throw new RuntimeException("抽奖券不足");

Redis Key 规范

缓存:      {module}:{entity}:{id}           user:info:10001
排行榜:    ranking:{type}:{period}:{date}   ranking:send_gift:day:20240101
分布式锁:  {module}:lock:{bizId}            coin:lock:10001

七、新功能开发顺序(黄金路径)

  1. 定义 Cmd / COother-client
  2. 定义 Service 接口other-client
  3. 实现 CmdExeother-application
  4. 实现 ServiceImplother-application
  5. 创建 Controllerother-adapter
  6. 按需创建 DatabaseService 或 Gatewayother-infrastructure
  7. 如需跨服务调用,添加 Inner API

八、质量检查清单

  • 命名清晰,无 a/b/temp 类命名
  • 参数校验(@Validated@NotNull
  • 写操作有 @Transactional
  • 金额操作有幂等性保障bizNo
  • 并发场景有分布式锁
  • 关键操作有 log.info / log.error
  • 业务异常用 BusinessException
  • 无魔法值(常量或枚举)
  • 分页查询用 PageResult