Skip to content

业务开发规范:让代码结构说话

业务代码写得好不好,不在于用了多少高级特性,而在于结构是否清晰、职责是否分明。

一个混乱的业务代码库,改一个需求要改几十个文件;一个规范的业务代码库,改一个需求只需要改对应的模块。

分层架构

最常见的三层架构:

层级职责注意
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);
    }
}

总结

  1. 分层清晰:Controller 不写业务,Service 不做数据访问
  2. 事务边界:事务控制在 Service 层
  3. 参数校验:入口处校验,不要等到业务层
  4. 异常统一:全局异常处理,避免 try-catch 散落各处

业务代码的质量,在于每个层级各司其职。

基于 VitePress 构建