业务开发规范:让代码结构说话
业务代码写得好不好,不在于用了多少高级特性,而在于结构是否清晰、职责是否分明。
一个混乱的业务代码库,改一个需求要改几十个文件;一个规范的业务代码库,改一个需求只需要改对应的模块。
分层架构
最常见的三层架构:
| 层级 | 职责 | 注意 |
|---|---|---|
| Controller | 接收请求、参数校验、返回结果 | 不要写业务逻辑 |
| Service | 业务逻辑、事务控制 | 核心层,保证事务边界 |
| Repository | 数据访问 | 只做 CURD,不要有业务判断 |
java
// Controller:只负责接收和返回
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
@GetMapping("/{id}")
public UserDTO getUser(@PathVariable Long id) {
return userService.getUser(id);
}
@PostMapping
public Result<Void> createUser(@RequestBody @Valid UserCreateDTO dto) {
userService.createUser(dto);
return Result.success();
}
}
// Service:处理业务逻辑
@Service
public class UserService {
private final UserRepository userRepository;
public UserDTO getUser(Long id) {
return userRepository.findById(id)
.map(this::toDTO)
.orElseThrow(() -> new UserNotFoundException(id));
}
@Transactional
public void createUser(UserCreateDTO dto) {
// 业务校验
validateUser(dto);
// 保存
User user = toEntity(dto);
userRepository.save(user);
}
}参数校验
参数校验要在入口处做,不要等到 Service 层才发现参数无效:
java
// Controller 层用 @Valid 触发校验
@PostMapping
public Result<Void> createUser(@RequestBody @Valid UserCreateDTO dto) {
// 校验失败自动抛出 MethodArgumentNotValidException
}
// DTO 中定义校验规则
public class UserCreateDTO {
@NotBlank(message = "姓名不能为空")
private String name;
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 0, message = "年龄不能为负")
private Integer age;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}异常处理
业务异常要有明确的含义:
java
// 统一异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public Result<Void> handleUserNotFound(UserNotFoundException e) {
return Result.error("USER_NOT_FOUND", e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidation(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return Result.error("VALIDATION_ERROR", message);
}
}总结
- 分层清晰:Controller 不写业务,Service 不做数据访问
- 事务边界:事务控制在 Service 层
- 参数校验:入口处校验,不要等到业务层
- 异常统一:全局异常处理,避免 try-catch 散落各处
业务代码的质量,在于每个层级各司其职。
