Cola架构深度解析:企业级应用架构设计指南

Cola架构深度解析:企业级应用架构设计指南

目录

  1. 架构演进背景
  2. Cola架构核心思想
  3. 分层架构详解
  4. 领域驱动设计实践
  5. 设计模式应用
  6. 伪代码实现示例
  7. 架构对比分析
  8. 实战案例解析
  9. 最佳实践总结
  10. 常见问题解答

架构演进背景

传统架构的痛点

在企业级应用开发中,我们经常遇到以下问题:

1. 业务逻辑分散
java 复制代码
// 传统Controller中的业务逻辑
@RestController
public class UserController {
    @PostMapping("/users")
    public Result createUser(@RequestBody UserRequest request) {
        // 业务验证逻辑
        if (StringUtils.isEmpty(request.getEmail())) {
            return Result.error("邮箱不能为空");
        }
        if (!EmailUtils.isValid(request.getEmail())) {
            return Result.error("邮箱格式不正确");
        }
        
        // 业务规则检查
        User existingUser = userService.findByEmail(request.getEmail());
        if (existingUser != null) {
            return Result.error("邮箱已存在");
        }
        
        // 业务处理逻辑
        User user = new User();
        user.setEmail(request.getEmail());
        user.setName(request.getName());
        user.setPassword(BCrypt.hashpw(request.getPassword(), BCrypt.gensalt()));
        user.setStatus(UserStatus.ACTIVE);
        user.setCreatedTime(new Date());
        
        // 数据持久化
        userService.save(user);
        
        // 发送欢迎邮件
        emailService.sendWelcomeEmail(user.getEmail());
        
        return Result.success(user);
    }
}

问题分析:

  • 业务逻辑散落在Controller层
  • 验证逻辑、业务规则、数据处理混在一起
  • 难以进行单元测试
  • 代码复用性差
2. 分层混乱
java 复制代码
// 典型的"大泥球"架构
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private EmailService emailService;
    
    public User createUser(UserRequest request) {
        // 数据访问逻辑
        UserPO userPO = new UserPO();
        userPO.setEmail(request.getEmail());
        userPO.setName(request.getName());
        userPO.setPassword(encryptPassword(request.getPassword()));
        userPO.setStatus(1);
        userPO.setCreatedTime(new Date());
        
        // 缓存逻辑
        String cacheKey = "user:" + request.getEmail();
        redisTemplate.opsForValue().set(cacheKey, userPO, 3600);
        
        // 消息发送逻辑
        Message message = new Message();
        message.setType("USER_CREATED");
        message.setContent(userPO);
        messageQueue.send(message);
        
        return convertToUser(userPO);
    }
}

问题分析:

  • 业务逻辑、数据访问、缓存、消息发送混在一起
  • 违反单一职责原则
  • 难以进行分层测试
  • 技术实现与业务逻辑耦合

Cola架构的解决方案

Cola架构通过以下方式解决上述问题:

  1. 清晰的分层设计:每层职责明确,依赖关系清晰
  2. 领域驱动设计:业务逻辑集中在领域层
  3. 依赖倒置:通过接口解耦,提高可测试性
  4. 统一规范:提供标准的分层和命名规范

Cola架构核心思想

1. 分层架构原则

Cola架构采用四层架构模式,每层都有明确的职责:

graph TB subgraph "用户接口层 (User Interface Layer)" A[Controller] B[Facade] C[Assembler] end subgraph "应用层 (Application Layer)" D[ApplicationService] E[CommandHandler] F[QueryHandler] end subgraph "领域层 (Domain Layer)" G[Entity] H[ValueObject] I[DomainService] J[Repository Interface] end subgraph "基础设施层 (Infrastructure Layer)" K[Repository Implementation] L[Gateway] M[Config] end A --> D B --> D C --> D D --> G D --> I I --> J J --> K K --> L

2. 依赖倒置原则

java 复制代码
// 领域层定义接口
public interface UserRepository {
    void save(User user);
    Optional<User> findById(UserId userId);
    Optional<User> findByEmail(Email email);
}

// 基础设施层实现接口
@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public void save(User user) {
        UserPO userPO = convertToPO(user);
        userMapper.insert(userPO);
    }
    
    @Override
    public Optional<User> findById(UserId userId) {
        UserPO userPO = userMapper.selectById(userId.getValue());
        return userPO != null ? Optional.of(convertToDomain(userPO)) : Optional.empty();
    }
}

3. 领域驱动设计

Cola架构强调领域模型的重要性:

java 复制代码
// 聚合根 - 用户聚合
public class User {
    private UserId id;
    private Email email;
    private PhoneNumber phoneNumber;
    private String name;
    private UserStatus status;
    
    // 业务方法
    public void updateInfo(String name, PhoneNumber phoneNumber) {
        if (name != null && !name.trim().isEmpty()) {
            this.name = name.trim();
        }
        if (phoneNumber != null) {
            this.phoneNumber = phoneNumber;
        }
    }
    
    public void enable() {
        this.status = UserStatus.ENABLED;
    }
    
    public void disable() {
        this.status = UserStatus.DISABLED;
    }
    
    public boolean isAvailable() {
        return status != null && status.isEnabled();
    }
}

// 值对象 - 邮箱
public class Email {
    private final String value;
    
    public Email(String email) {
        if (email == null || email.trim().isEmpty()) {
            throw new IllegalArgumentException("邮箱不能为空");
        }
        if (!isValidEmail(email)) {
            throw new IllegalArgumentException("邮箱格式不正确");
        }
        this.value = email.trim().toLowerCase();
    }
    
    private boolean isValidEmail(String email) {
        return email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    }
}

分层架构详解

1. 用户接口层 (User Interface Layer)

用户接口层负责处理外部请求,包括HTTP请求、消息队列消息等。

职责范围
  • 接收和验证用户输入
  • 数据格式转换
  • 权限控制
  • 异常处理
伪代码示例
java 复制代码
// Controller - 处理HTTP请求
@RestController
public class UserController {
    
    @PostMapping("/users")
    public Response<UserDTO> createUser(@Valid @RequestBody UserCreateCmd cmd) {
        // 1. 参数验证(通过@Valid注解)
        // 2. 调用应用服务
        UserDTO result = userApplicationService.createUser(cmd);
        // 3. 返回统一响应格式
        return Response.success(result);
    }
}

// Facade - 业务门面
public interface UserFacade {
    Response<UserDTO> createUser(UserCreateCmd cmd);
    Response<UserDTO> updateUser(Long userId, UserUpdateCmd cmd);
    Response<String> login(UserLoginCmd cmd);
}

// Assembler - 数据转换器
public class UserAssembler {
    public static UserDTO toDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId().getValue());
        dto.setEmail(user.getEmail().getValue());
        dto.setName(user.getName());
        return dto;
    }
    
    public static User toDomain(UserCreateCmd cmd) {
        return User.create(
            Email.of(cmd.getEmail()),
            PhoneNumber.of(cmd.getPhoneNumber()),
            cmd.getName(),
            cmd.getPassword()
        );
    }
}

2. 应用层 (Application Layer)

应用层协调业务流程,不包含业务逻辑,只做流程编排。

职责范围
  • 事务管理
  • 权限控制
  • 流程编排
  • 跨聚合协调
伪代码示例
java 复制代码
@Service
public class UserApplicationService implements UserFacade {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserDomainService userDomainService;
    
    @Autowired
    private EmailGateway emailGateway;
    
    @Transactional
    public Response<UserDTO> createUser(UserCreateCmd cmd) {
        try {
            // 1. 创建领域对象
            Email email = Email.of(cmd.getEmail());
            PhoneNumber phoneNumber = PhoneNumber.of(cmd.getPhoneNumber());
            
            // 2. 调用领域服务验证业务规则
            userDomainService.validateUserRegistration(email, phoneNumber);
            
            // 3. 创建用户聚合根
            User user = User.create(email, phoneNumber, cmd.getName(), cmd.getPassword());
            
            // 4. 保存用户
            userRepository.save(user);
            
            // 5. 发送欢迎邮件(异步)
            emailGateway.sendWelcomeEmail(user.getEmail());
            
            // 6. 转换为DTO返回
            return Response.success(UserAssembler.toDTO(user));
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
}

3. 领域层 (Domain Layer)

领域层是系统的核心,包含业务逻辑和业务规则。

职责范围
  • 业务逻辑实现
  • 业务规则验证
  • 领域模型定义
  • 业务不变性保证
伪代码示例
java 复制代码
// 聚合根
public class User {
    private UserId id;
    private Email email;
    private PhoneNumber phoneNumber;
    private String name;
    private UserStatus status;
    private LocalDateTime createdTime;
    
    // 业务方法
    public static User create(Email email, PhoneNumber phoneNumber, String name, String password) {
        User user = new User();
        user.email = email;
        user.phoneNumber = phoneNumber;
        user.name = name;
        user.password = encryptPassword(password);
        user.status = UserStatus.ENABLED;
        user.createdTime = LocalDateTime.now();
        return user;
    }
    
    public void updateInfo(String name, PhoneNumber phoneNumber) {
        // 业务规则:用户名不能为空
        if (name != null && !name.trim().isEmpty()) {
            this.name = name.trim();
        }
        if (phoneNumber != null) {
            this.phoneNumber = phoneNumber;
        }
    }
    
    public void enable() {
        this.status = UserStatus.ENABLED;
    }
    
    public void disable() {
        this.status = UserStatus.DISABLED;
    }
    
    public boolean isAvailable() {
        return status != null && status.isEnabled();
    }
}

// 领域服务
@Service
public class UserDomainService {
    
    @Autowired
    private UserRepository userRepository;
    
    public void validateUserRegistration(Email email, PhoneNumber phoneNumber) {
        // 业务规则:邮箱不能重复
        if (userRepository.existsByEmail(email)) {
            throw new IllegalArgumentException("邮箱已被注册");
        }
        
        // 业务规则:手机号不能重复
        if (phoneNumber != null && userRepository.existsByPhoneNumber(phoneNumber)) {
            throw new IllegalArgumentException("手机号已被注册");
        }
    }
    
    public User validateUserLogin(String loginId, String password) {
        User user = findUserByLoginId(loginId);
        
        if (user == null) {
            throw new IllegalArgumentException("用户不存在");
        }
        
        if (!user.isAvailable()) {
            throw new IllegalArgumentException("用户已被禁用");
        }
        
        if (!user.checkPassword(password)) {
            throw new IllegalArgumentException("密码错误");
        }
        
        return user;
    }
}

4. 基础设施层 (Infrastructure Layer)

基础设施层提供技术实现,包括数据持久化、外部服务调用等。

职责范围
  • 数据持久化
  • 外部服务调用
  • 技术配置
  • 缓存实现
伪代码示例
java 复制代码
// 仓储实现
@Repository
public class UserRepositoryImpl implements UserRepository {
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public void save(User user) {
        UserPO userPO = convertToPO(user);
        if (user.getId() == null) {
            userMapper.insert(userPO);
            user.setId(UserId.of(userPO.getId()));
        } else {
            userMapper.updateById(userPO);
        }
    }
    
    @Override
    public Optional<User> findById(UserId userId) {
        UserPO userPO = userMapper.selectById(userId.getValue());
        return userPO != null ? Optional.of(convertToDomain(userPO)) : Optional.empty();
    }
    
    private UserPO convertToPO(User user) {
        UserPO po = new UserPO();
        po.setId(user.getId() != null ? user.getId().getValue() : null);
        po.setEmail(user.getEmail().getValue());
        po.setPhoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber().getValue() : null);
        po.setName(user.getName());
        po.setStatus(user.getStatus().getCode());
        return po;
    }
    
    private User convertToDomain(UserPO po) {
        User user = new User();
        user.setId(UserId.of(po.getId()));
        user.setEmail(Email.of(po.getEmail()));
        user.setPhoneNumber(po.getPhoneNumber() != null ? PhoneNumber.of(po.getPhoneNumber()) : null);
        user.setName(po.getName());
        user.setStatus(UserStatus.fromCode(po.getStatus()));
        return user;
    }
}

// 外部服务网关
@Component
public class EmailGateway {
    
    @Autowired
    private EmailService emailService;
    
    public void sendWelcomeEmail(Email email) {
        try {
            WelcomeEmailMessage message = new WelcomeEmailMessage();
            message.setTo(email.getValue());
            message.setSubject("欢迎注册");
            message.setContent("欢迎您注册我们的系统!");
            
            emailService.send(message);
        } catch (Exception e) {
            // 记录日志,但不影响主流程
            log.error("发送欢迎邮件失败", e);
        }
    }
}

领域驱动设计实践

1. 聚合设计

聚合是DDD中的核心概念,它定义了一组相关对象的边界。

graph TB subgraph "用户聚合 (User Aggregate)" A[User - 聚合根] B[UserId - 值对象] C[Email - 值对象] D[PhoneNumber - 值对象] E[UserStatus - 值对象] end subgraph "订单聚合 (Order Aggregate)" F[Order - 聚合根] G[OrderId - 值对象] H[OrderItem - 实体] I[Money - 值对象] end A --> B A --> C A --> D A --> E F --> G F --> H F --> I
聚合设计原则
java 复制代码
// 聚合根 - 保证业务不变性
public class User {
    private UserId id;
    private Email email;
    private PhoneNumber phoneNumber;
    private String name;
    private UserStatus status;
    private List<UserRole> roles; // 聚合内的实体
    
    // 业务方法 - 保证业务规则
    public void updateInfo(String name, PhoneNumber phoneNumber) {
        // 业务规则:用户名不能为空
        if (name != null && !name.trim().isEmpty()) {
            this.name = name.trim();
        }
        if (phoneNumber != null) {
            this.phoneNumber = phoneNumber;
        }
    }
    
    public void addRole(UserRole role) {
        // 业务规则:不能重复添加角色
        if (roles.stream().anyMatch(r -> r.getRoleId().equals(role.getRoleId()))) {
            throw new IllegalArgumentException("角色已存在");
        }
        roles.add(role);
    }
}

2. 领域服务

领域服务处理跨聚合的业务逻辑。

java 复制代码
// 领域服务 - 处理跨聚合业务逻辑
@Service
public class UserDomainService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private RoleRepository roleRepository;
    
    public void assignRoleToUser(UserId userId, RoleId roleId) {
        // 1. 获取用户聚合
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        // 2. 获取角色聚合
        Role role = roleRepository.findById(roleId)
            .orElseThrow(() -> new IllegalArgumentException("角色不存在"));
        
        // 3. 业务规则:检查用户是否已有该角色
        if (user.hasRole(roleId)) {
            throw new IllegalArgumentException("用户已有该角色");
        }
        
        // 4. 业务规则:检查角色是否可用
        if (!role.isAvailable()) {
            throw new IllegalArgumentException("角色不可用");
        }
        
        // 5. 执行业务操作
        user.addRole(UserRole.create(roleId, role.getName()));
        userRepository.save(user);
    }
}

3. 仓储模式

仓储模式抽象了数据访问逻辑。

java 复制代码
// 仓储接口 - 定义在领域层
public interface UserRepository {
    void save(User user);
    Optional<User> findById(UserId userId);
    Optional<User> findByEmail(Email email);
    boolean existsByEmail(Email email);
    List<User> findUsersByRole(RoleId roleId);
}

// 仓储实现 - 在基础设施层
@Repository
public class UserRepositoryImpl implements UserRepository {
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public void save(User user) {
        UserPO userPO = convertToPO(user);
        if (user.getId() == null) {
            userMapper.insert(userPO);
            user.setId(UserId.of(userPO.getId()));
        } else {
            userMapper.updateById(userPO);
        }
    }
    
    @Override
    public Optional<User> findById(UserId userId) {
        UserPO userPO = userMapper.selectById(userId.getValue());
        return userPO != null ? Optional.of(convertToDomain(userPO)) : Optional.empty();
    }
}

设计模式应用

1. 门面模式 (Facade Pattern)

门面模式为复杂的子系统提供统一的接口。

java 复制代码
// 门面接口 - 定义业务能力
public interface UserFacade {
    Response<UserDTO> createUser(UserCreateCmd cmd);
    Response<UserDTO> updateUser(Long userId, UserUpdateCmd cmd);
    Response<String> login(UserLoginCmd cmd);
}

// 门面实现 - 应用服务
@Service
public class UserApplicationService implements UserFacade {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserDomainService userDomainService;
    
    @Override
    @Transactional
    public Response<UserDTO> createUser(UserCreateCmd cmd) {
        try {
            // 1. 创建领域对象
            Email email = Email.of(cmd.getEmail());
            PhoneNumber phoneNumber = PhoneNumber.of(cmd.getPhoneNumber());
            
            // 2. 验证业务规则
            userDomainService.validateUserRegistration(email, phoneNumber);
            
            // 3. 创建用户聚合
            User user = User.create(email, phoneNumber, cmd.getName(), cmd.getPassword());
            
            // 4. 保存用户
            userRepository.save(user);
            
            // 5. 发送欢迎邮件
            emailGateway.sendWelcomeEmail(user.getEmail());
            
            return Response.success(UserAssembler.toDTO(user));
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
}

2. 策略模式 (Strategy Pattern)

策略模式定义算法族,使算法可以互相替换。

java 复制代码
// 密码加密策略接口
public interface PasswordEncryptionStrategy {
    String encrypt(String password);
    boolean matches(String rawPassword, String encodedPassword);
}

// BCrypt加密策略
@Component
public class BCryptEncryptionStrategy implements PasswordEncryptionStrategy {
    
    @Override
    public String encrypt(String password) {
        return BCrypt.hashpw(password, BCrypt.gensalt());
    }
    
    @Override
    public boolean matches(String rawPassword, String encodedPassword) {
        return BCrypt.checkpw(rawPassword, encodedPassword);
    }
}

// 密码服务
@Service
public class PasswordService {
    
    @Autowired
    private PasswordEncryptionStrategy encryptionStrategy;
    
    public String encryptPassword(String password) {
        return encryptionStrategy.encrypt(password);
    }
    
    public boolean checkPassword(String rawPassword, String encodedPassword) {
        return encryptionStrategy.matches(rawPassword, encodedPassword);
    }
}

架构对比分析

1. 传统三层架构 vs Cola架构

graph TB subgraph "传统三层架构" A1[Controller层] A2[Service层] A3[DAO层] A1 --> A2 A2 --> A3 end subgraph "Cola四层架构" B1[用户接口层] B2[应用层] B3[领域层] B4[基础设施层] B1 --> B2 B2 --> B3 B3 --> B4 end
对比分析
方面 传统三层架构 Cola架构
分层数量 3层 4层
业务逻辑位置 分散在Controller和Service 集中在领域层
依赖方向 上层依赖下层 依赖倒置,下层依赖上层接口
可测试性 较差,层间耦合严重 较好,通过接口解耦
可维护性 业务逻辑分散,难以维护 业务逻辑集中,易于维护
扩展性 修改影响面大 修改影响面小

2. 代码对比示例

传统架构代码
java 复制代码
// Controller层 - 包含业务逻辑
@RestController
public class UserController {
    
    @PostMapping("/users")
    public Result createUser(@RequestBody UserRequest request) {
        // 业务验证
        if (StringUtils.isEmpty(request.getEmail())) {
            return Result.error("邮箱不能为空");
        }
        
        // 业务规则检查
        User existingUser = userService.findByEmail(request.getEmail());
        if (existingUser != null) {
            return Result.error("邮箱已存在");
        }
        
        // 业务处理
        User user = new User();
        user.setEmail(request.getEmail());
        user.setName(request.getName());
        user.setPassword(BCrypt.hashpw(request.getPassword(), BCrypt.gensalt()));
        user.setStatus(UserStatus.ACTIVE);
        user.setCreatedTime(new Date());
        
        // 数据持久化
        userService.save(user);
        
        // 发送邮件
        emailService.sendWelcomeEmail(user.getEmail());
        
        return Result.success(user);
    }
}
Cola架构代码
java 复制代码
// Controller层 - 只做数据转换和路由
@RestController
public class UserController {
    
    @Autowired
    private UserFacade userFacade;
    
    @PostMapping("/users")
    public Response<UserDTO> createUser(@Valid @RequestBody UserCreateCmd cmd) {
        return userFacade.createUser(cmd);
    }
}

// 应用层 - 流程编排
@Service
public class UserApplicationService implements UserFacade {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserDomainService userDomainService;
    
    @Transactional
    public Response<UserDTO> createUser(UserCreateCmd cmd) {
        try {
            // 创建领域对象
            Email email = Email.of(cmd.getEmail());
            PhoneNumber phoneNumber = PhoneNumber.of(cmd.getPhoneNumber());
            
            // 验证业务规则
            userDomainService.validateUserRegistration(email, phoneNumber);
            
            // 创建用户聚合
            User user = User.create(email, phoneNumber, cmd.getName(), cmd.getPassword());
            
            // 保存用户
            userRepository.save(user);
            
            // 发送欢迎邮件
            emailGateway.sendWelcomeEmail(user.getEmail());
            
            return Response.success(UserAssembler.toDTO(user));
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
}

最佳实践总结

1. 分层设计原则

依赖倒置原则
java 复制代码
// 错误示例 - 领域层依赖基础设施层
public class UserService {
    @Autowired
    private UserMapper userMapper; // 直接依赖具体实现
    
    public void saveUser(User user) {
        UserPO userPO = convertToPO(user);
        userMapper.insert(userPO);
    }
}

// 正确示例 - 依赖倒置
public class UserService {
    @Autowired
    private UserRepository userRepository; // 依赖抽象接口
    
    public void saveUser(User user) {
        userRepository.save(user);
    }
}
单一职责原则
java 复制代码
// 错误示例 - 职责混乱
public class UserService {
    public void createUser(UserRequest request) {
        // 参数验证
        if (StringUtils.isEmpty(request.getEmail())) {
            throw new IllegalArgumentException("邮箱不能为空");
        }
        
        // 业务逻辑
        User user = new User();
        user.setEmail(request.getEmail());
        
        // 数据访问
        userMapper.insert(user);
        
        // 发送邮件
        emailService.sendWelcomeEmail(user.getEmail());
        
        // 记录日志
        logService.logUserCreation(user);
    }
}

// 正确示例 - 职责分离
public class UserApplicationService {
    @Autowired
    private UserDomainService userDomainService;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private EmailGateway emailGateway;
    
    @Transactional
    public void createUser(UserCreateCmd cmd) {
        // 1. 验证业务规则
        userDomainService.validateUserRegistration(cmd.getEmail(), cmd.getPhoneNumber());
        
        // 2. 创建用户聚合
        User user = User.create(cmd.getEmail(), cmd.getPhoneNumber(), cmd.getName(), cmd.getPassword());
        
        // 3. 保存用户
        userRepository.save(user);
        
        // 4. 发送欢迎邮件
        emailGateway.sendWelcomeEmail(user.getEmail());
    }
}

2. 领域建模最佳实践

聚合设计
java 复制代码
// 聚合根设计
public class User {
    private UserId id;
    private Email email;
    private PhoneNumber phoneNumber;
    private String name;
    private UserStatus status;
    private List<UserRole> roles; // 聚合内的实体
    
    // 业务方法
    public void updateInfo(String name, PhoneNumber phoneNumber) {
        // 业务规则验证
        if (name != null && !name.trim().isEmpty()) {
            this.name = name.trim();
        }
        if (phoneNumber != null) {
            this.phoneNumber = phoneNumber;
        }
    }
    
    public void addRole(UserRole role) {
        // 业务规则:不能重复添加角色
        if (roles.stream().anyMatch(r -> r.getRoleId().equals(role.getRoleId()))) {
            throw new IllegalArgumentException("角色已存在");
        }
        roles.add(role);
    }
    
    // 业务查询方法
    public boolean hasRole(RoleId roleId) {
        return roles.stream().anyMatch(role -> role.getRoleId().equals(roleId));
    }
    
    public boolean isAvailable() {
        return status != null && status.isEnabled();
    }
}
值对象设计
java 复制代码
// 值对象 - 不可变对象
public class Email {
    private final String value;
    
    public Email(String email) {
        if (email == null || email.trim().isEmpty()) {
            throw new IllegalArgumentException("邮箱不能为空");
        }
        if (!isValidEmail(email)) {
            throw new IllegalArgumentException("邮箱格式不正确");
        }
        this.value = email.trim().toLowerCase();
    }
    
    public String getValue() {
        return value;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Email email = (Email) obj;
        return Objects.equals(value, email.value);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(value);
    }
    
    private boolean isValidEmail(String email) {
        return email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    }
}

3. 数据转换最佳实践

转换器设计
java 复制代码
// 数据转换器
public class UserAssembler {
    
    public static UserDTO toDTO(User user) {
        if (user == null) {
            return null;
        }
        
        UserDTO dto = new UserDTO();
        dto.setId(user.getId().getValue());
        dto.setEmail(user.getEmail().getValue());
        dto.setPhoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber().getValue() : null);
        dto.setName(user.getName());
        dto.setStatus(user.getStatus().getDescription());
        dto.setEmailVerified(user.getEmailVerified());
        dto.setPhoneVerified(user.getPhoneVerified());
        dto.setLastLoginTime(user.getLastLoginTime());
        dto.setLastLoginIp(user.getLastLoginIp());
        dto.setCreatedTime(user.getCreatedTime());
        dto.setUpdatedTime(user.getUpdatedTime());
        return dto;
    }
    
    public static User toDomain(UserCreateCmd cmd) {
        return User.create(
            Email.of(cmd.getEmail()),
            cmd.getPhoneNumber() != null ? PhoneNumber.of(cmd.getPhoneNumber()) : null,
            cmd.getName(),
            cmd.getPassword()
        );
    }
    
    public static UserPO toPO(User user) {
        if (user == null) {
            return null;
        }
        
        UserPO po = new UserPO();
        po.setId(user.getId() != null ? user.getId().getValue() : null);
        po.setEmail(user.getEmail().getValue());
        po.setPhoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber().getValue() : null);
        po.setName(user.getName());
        po.setPassword(user.getPassword());
        po.setStatus(user.getStatus().getCode());
        po.setEmailVerified(user.getEmailVerified());
        po.setPhoneVerified(user.getPhoneVerified());
        po.setLastLoginTime(user.getLastLoginTime());
        po.setLastLoginIp(user.getLastLoginIp());
        po.setCreatedTime(user.getCreatedTime());
        po.setUpdatedTime(user.getUpdatedTime());
        return po;
    }
    
    public static User toDomain(UserPO po) {
        if (po == null) {
            return null;
        }
        
        User user = new User();
        user.setId(UserId.of(po.getId()));
        user.setEmail(Email.of(po.getEmail()));
        user.setPhoneNumber(po.getPhoneNumber() != null ? PhoneNumber.of(po.getPhoneNumber()) : null);
        user.setName(po.getName());
        user.setPassword(po.getPassword());
        user.setStatus(UserStatus.fromCode(po.getStatus()));
        user.setEmailVerified(po.getEmailVerified());
        user.setPhoneVerified(po.getPhoneVerified());
        user.setLastLoginTime(po.getLastLoginTime());
        user.setLastLoginIp(po.getLastLoginIp());
        user.setCreatedTime(po.getCreatedTime());
        user.setUpdatedTime(po.getUpdatedTime());
        return user;
    }
}

常见问题解答

1. 什么时候使用Cola架构?

适用场景:

  • 中大型企业级应用
  • 业务复杂度较高的系统
  • 需要长期维护的项目
  • 多人协作开发的项目
  • 需要快速迭代的业务系统

不适用场景:

  • 简单的CRUD应用
  • 原型验证项目
  • 个人学习项目
  • 业务逻辑简单的系统

2. 如何平衡架构复杂度和开发效率?

建议:

  • 从小项目开始实践
  • 逐步引入DDD概念
  • 先实现核心业务功能
  • 再完善架构设计
  • 团队统一架构规范

3. 如何处理跨聚合的业务逻辑?

解决方案:

  • 使用领域服务处理跨聚合逻辑
  • 通过事件机制解耦聚合
  • 在应用层协调多个聚合
  • 避免聚合间的直接依赖

4. 如何保证数据一致性?

策略:

  • 使用事务保证单聚合内的一致性
  • 通过事件机制保证跨聚合的最终一致性
  • 使用Saga模式处理分布式事务
  • 合理设计聚合边界

5. 如何提高代码的可测试性?

方法:

  • 依赖注入和接口抽象
  • 单元测试覆盖业务逻辑
  • 集成测试验证完整流程
  • Mock外部依赖
  • 测试数据构建器模式

实战案例:用户管理系统

让我们通过一个完整的用户管理系统来学习Cola架构的实际应用。

业务需求

  • 用户注册(包含邮箱验证)
  • 用户登录(支持邮箱和手机号)
  • 用户信息修改
  • 用户查询(支持分页和条件查询)
  • 用户状态管理(启用/禁用)

技术栈

  • Spring Boot 2.7.x
  • MyBatis Plus
  • MySQL 8.0
  • Redis
  • Maven

项目结构

graph TB subgraph "cola-user-system" A[启动类] B[用户接口层] C[应用层] D[领域层] E[基础设施层] end subgraph "用户接口层" B1[Controller] B2[DTO] B3[Facade] end subgraph "应用层" C1[ApplicationService] C2[CommandHandler] C3[QueryHandler] end subgraph "领域层" D1[Entity] D2[ValueObject] D3[DomainService] D4[Repository接口] end subgraph "基础设施层" E1[Repository实现] E2[Gateway] E3[Config] end A --> B B --> C C --> D D --> E

核心代码示例

1. 用户聚合根
java 复制代码
public class User {
    private UserId id;
    private Email email;
    private PhoneNumber phoneNumber;
    private String name;
    private UserStatus status;
    private LocalDateTime createdTime;
    
    public static User create(Email email, PhoneNumber phoneNumber, String name, String password) {
        User user = new User();
        user.email = email;
        user.phoneNumber = phoneNumber;
        user.name = name;
        user.password = encryptPassword(password);
        user.status = UserStatus.ENABLED;
        user.createdTime = LocalDateTime.now();
        return user;
    }
    
    public void updateInfo(String name, PhoneNumber phoneNumber) {
        if (name != null && !name.trim().isEmpty()) {
            this.name = name.trim();
        }
        if (phoneNumber != null) {
            this.phoneNumber = phoneNumber;
        }
    }
    
    public boolean isAvailable() {
        return status != null && status.isEnabled();
    }
}
2. 应用服务
java 复制代码
@Service
public class UserApplicationService implements UserFacade {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserDomainService userDomainService;
    
    @Transactional
    public Response<UserDTO> createUser(UserCreateCmd cmd) {
        try {
            // 1. 创建领域对象
            Email email = Email.of(cmd.getEmail());
            PhoneNumber phoneNumber = PhoneNumber.of(cmd.getPhoneNumber());
            
            // 2. 验证业务规则
            userDomainService.validateUserRegistration(email, phoneNumber);
            
            // 3. 创建用户聚合
            User user = User.create(email, phoneNumber, cmd.getName(), cmd.getPassword());
            
            // 4. 保存用户
            userRepository.save(user);
            
            // 5. 发送欢迎邮件
            emailGateway.sendWelcomeEmail(user.getEmail());
            
            return Response.success(UserAssembler.toDTO(user));
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
}
3. 领域服务
java 复制代码
@Service
public class UserDomainService {
    
    @Autowired
    private UserRepository userRepository;
    
    public void validateUserRegistration(Email email, PhoneNumber phoneNumber) {
        if (userRepository.existsByEmail(email)) {
            throw new IllegalArgumentException("邮箱已被注册");
        }
        if (phoneNumber != null && userRepository.existsByPhoneNumber(phoneNumber)) {
            throw new IllegalArgumentException("手机号已被注册");
        }
    }
}

总结

Cola架构通过清晰的分层设计和DDD实践,为企业级应用开发提供了一套完整的解决方案。

核心优势

  1. 清晰的职责划分:每层都有明确的职责,降低耦合度
  2. 易于维护:业务逻辑集中在领域层,便于理解和修改
  3. 可测试性强:各层可以独立测试,提高代码质量
  4. 可扩展性好:新功能可以按照既定规范快速开发
  5. 团队协作友好:统一的架构规范,降低沟通成本

适用场景

  • 中大型企业级应用
  • 业务复杂度较高的系统
  • 需要长期维护的项目
  • 多人协作开发的项目

学习建议

  1. 理论学习:深入理解DDD和分层架构概念
  2. 实践练习:通过实际项目练习架构设计
  3. 代码规范:遵循统一的命名和结构规范
  4. 持续改进:根据项目需求不断优化架构

架构演进

graph LR A[传统三层架构] --> B[Cola四层架构] B --> C[微服务架构] C --> D[云原生架构] A1[业务逻辑分散] --> B1[业务逻辑集中] B1 --> C1[服务拆分] C1 --> D1[容器化部署]

通过本案例的学习,您应该对Cola架构有了全面的了解。在实际项目中,可以根据具体需求对架构进行适当调整,但核心的分层思想和DDD实践应该保持一致。


项目地址 :[gitee.com/youhei/cola...]

相关推荐
IT_陈寒3 小时前
🔥5个必学的JavaScript性能黑科技:让你的网页速度提升300%!
前端·人工智能·后端
莫克4 小时前
java文件上传
后端
LeonMinkus4 小时前
dubbo3使用grpc开发分布式服务
后端
一只韩非子4 小时前
Spring AI Alibaba 快速上手教程:10 分钟接入大模型
java·后端·ai编程
起风了___5 小时前
20 分钟搞定:Jenkins + Docker 一键流水线,自动构建镜像并部署到远程服务器
后端
用户4099322502125 小时前
如何在 FastAPI 中巧妙覆盖依赖注入并拦截第三方服务调用?
后端·ai编程·trae
泉城老铁5 小时前
Spring Boot中实现多线程分片下载
java·spring boot·后端
泉城老铁5 小时前
Spring Boot中实现多文件打包下载
spring boot·后端·架构
泉城老铁5 小时前
Spring Boot中实现大文件分片下载和断点续传功能
java·spring boot·后端