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

245 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 编码风格规范
## 一、命名规范
| 类型 | 命名规则 | 示例 |
|------|---------|------|
| 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 规范
```java
/**
* 功能说明.
*
* @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 规范
```java
// 写命令 - 继承 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 规范
```java
// 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 规范
```java
// 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 操作 + 缓存更新
}
}
```
---
## 六、通用代码规范
### 条件判断
```java
// ✅
if (StringUtils.isNotBlank(name)) { ... }
if (Objects.nonNull(userId)) { ... }
// ❌
if (name != null && !name.isEmpty()) { ... }
if (userId != null) { ... }
```
### 金额
```java
// ✅
BigDecimal amount = new BigDecimal("100.00");
BigDecimal total = a.add(b);
// ❌ 禁止
double amount = 100.00;
```
### 返回分页
```java
return PageResult.of(records, total, cmd.getPageNum(), cmd.getPageSize());
```
### 异常
```java
// ✅
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`