Cola架构深度解析:企业级应用架构设计指南
目录
架构演进背景
传统架构的痛点
在企业级应用开发中,我们经常遇到以下问题:
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架构通过以下方式解决上述问题:
- 清晰的分层设计:每层职责明确,依赖关系清晰
- 领域驱动设计:业务逻辑集中在领域层
- 依赖倒置:通过接口解耦,提高可测试性
- 统一规范:提供标准的分层和命名规范
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实践,为企业级应用开发提供了一套完整的解决方案。
核心优势
- 清晰的职责划分:每层都有明确的职责,降低耦合度
- 易于维护:业务逻辑集中在领域层,便于理解和修改
- 可测试性强:各层可以独立测试,提高代码质量
- 可扩展性好:新功能可以按照既定规范快速开发
- 团队协作友好:统一的架构规范,降低沟通成本
适用场景
- 中大型企业级应用
- 业务复杂度较高的系统
- 需要长期维护的项目
- 多人协作开发的项目
学习建议
- 理论学习:深入理解DDD和分层架构概念
- 实践练习:通过实际项目练习架构设计
- 代码规范:遵循统一的命名和结构规范
- 持续改进:根据项目需求不断优化架构
架构演进
graph LR
A[传统三层架构] --> B[Cola四层架构]
B --> C[微服务架构]
C --> D[云原生架构]
A1[业务逻辑分散] --> B1[业务逻辑集中]
B1 --> C1[服务拆分]
C1 --> D1[容器化部署]
通过本案例的学习,您应该对Cola架构有了全面的了解。在实际项目中,可以根据具体需求对架构进行适当调整,但核心的分层思想和DDD实践应该保持一致。
项目地址 :[gitee.com/youhei/cola...]