共计 2574 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
在传统技能管理系统开发中,我们常遇到以下几个典型问题:

- 业务逻辑分散 :创建逻辑散落在 Controller、Service 各个角落,修改一处可能影响多处
- 状态管理混乱 :技能状态变更缺乏统一入口,容易产生脏数据
- 扩展困难 :新增技能类型需要修改核心代码,违反开闭原则
这些问题导致系统维护成本高、迭代速度慢,尤其当业务发展到需要支持数百种技能类型时,系统会变得难以维护。
架构设计
我们采用 DDD 分层架构来解决这些问题,整体设计如下:
┌─────────────────┐
│ 接口层 │ ◄── HTTP/RPC 接口、DTO 转换
├─────────────────┤
│ 应用层 │ ◄── 事务管理、流程编排
├─────────────────┤
│ 领域层 │ ◄── 核心业务逻辑、领域模型
├─────────────────┤
│ 基础设施层 │ ◄── 持久化、消息、工具类
└─────────────────┘
每层的具体职责:
- 接口层 :处理外部请求,进行参数校验和 DTO 转换
- 应用层 :协调领域对象完成业务用例,不包含业务逻辑
- 领域层 :包含实体、值对象、领域服务等核心业务元素
- 基础设施层 :提供技术实现,如数据库访问、消息队列等
核心实现
工厂模式封装创建逻辑
使用工厂模式将复杂创建逻辑封装起来:
public interface SkillFactory {Skill create(SkillCreateCommand command);
}
@Service
@RequiredArgsConstructor
public class SkillFactoryImpl implements SkillFactory {
private final Validator validator;
@Override
public Skill create(SkillCreateCommand command) {validator.validate(command);
// 根据类型选择不同的创建策略
switch (command.getType()) {
case "BASIC":
return BasicSkill.create(command);
case "ADVANCED":
return AdvancedSkill.create(command);
default:
throw new IllegalArgumentException("Unsupported skill type");
}
}
}
事件驱动设计
使用领域事件解耦后续处理流程:
public class SkillCreatedEvent {
private final String skillId;
private final String creator;
private final Instant createdAt;
// 构造器、getter 省略
}
@Entity
public class Skill {
// ... 其他属性和方法
public SkillCreatedEvent create() {
this.status = Status.CREATED;
return new SkillCreatedEvent(this.id, this.creator, Instant.now());
}
}
乐观锁处理并发
在 Repository 层实现乐观锁控制:
@Repository
public class SkillRepositoryImpl implements SkillRepository {
@PersistenceContext
private EntityManager em;
@Override
@Transactional
public Skill save(Skill skill) {if (skill.getVersion() == null) {em.persist(skill);
return skill;
} else {
// 乐观锁检查
return em.merge(skill);
}
}
}
质量保障
参数化单元测试
使用 JUnit5 进行边界测试:
@ParameterizedTest
@MethodSource("invalidCreateParams")
void shouldRejectInvalidCreateCommand(String name, String type) {SkillCreateCommand command = new SkillCreateCommand(name, type);
assertThatThrownBy(() -> validator.validate(command))
.isInstanceOf(ConstraintViolationException.class);
}
private static Stream<Arguments> invalidCreateParams() {
return Stream.of(Arguments.of(null, "BASIC"), // 名称为空
Arguments.of("test", "UNKNOWN") // 未知类型
);
}
性能测试
使用 JMeter 测试批量创建场景,重点关注:
- 单机 QPS 达到 1000+
- 99% 的请求响应时间 <200ms
- 错误率 <0.1%
避坑指南
- 避免贫血模型 :不要把业务逻辑都放到 Service 中,领域对象应该保持丰富行为
- 循环引用检测 :在创建技能时检查依赖关系是否成环
public void checkCircularDependency(Skill skill, Set<Skill> visited) {if (visited.contains(skill)) {throw new CircularDependencyException(); } visited.add(skill); skill.getDependencies().forEach(dep -> checkCircularDependency(dep, new HashSet<>(visited))); } - 幂等性保障 :使用唯一业务 ID 或 token 机制防止重复创建
总结与思考
这套架构已在生产环境支撑日均百万级的技能创建操作。通过 DDD 分层和事件驱动设计,系统获得了良好的扩展性——新增技能类型只需添加对应的工厂实现,不影响现有代码。
最后抛出开放性问题:当技能需要跨系统同步时,如何平衡一致性与性能?是采用强一致性的分布式事务,还是最终一致性 + 补偿机制?欢迎在评论区分享你的见解。
正文完
