你的 DDD 还在纸上谈兵?是时候落地了!

一、背景篇

在软件开发领域,随着业务需求的不断增长和复杂化,传统的单体架构逐渐暴露出扩展性差、维护困难等问题。

为了应对这些挑战,微服务架构应运而生。微服务架构的核心思想是"分而治之",就是将一个大型系统拆分成多个独立的小型服务,每个服务专注于一个特定的业务功能。这种拆分方式带来了许多好处,如更高的灵活性、更好的扩展性和更快的开发速度。

然而,随着微服务的广泛应用,一些问题也逐渐显现出来:

  1. 服务爆炸:微服务拆分过细,导致服务数量急剧增加,管理和维护成本也随之上升。
  2. 拆分不合理:服务拆分不合理,导致服务之间的耦合度过高,频繁的重构和调整成为常态。
  3. 数据一致性:微服务之间的数据一致性问题变得更加复杂,尤其是在分布式系统中。

为了解决这些问题,领域驱动设计(Domain-Driven Design,简称DDD)又实重新激活。这里说的是"激活",我们知道 DDD 并不是最近出有的,最初 DDD 是由Eric Evans在2003年提出的。由于它比较复杂,当时行业发展程度、面临的问题也都还不合适,所以并没有流行起来。

二、理论篇

2.1、DDD 的核心概念

  1. 领域(Domain)
    领域是业务的核心,包含了业务规则、业务实体、业务流程等。在 DDD 中,领域是软件设计的核心,所有的设计决策都应该围绕领域进行。
  2. 子域(Subdomain)
    子域是领域的一部分,通常对应于业务中的一个特定功能或模块。例如,在一个电商系统中,订单管理、用户管理、库存管理等都可以看作是不同的子域。
  3. 实体(Entity)
    实体是具有唯一标识的对象,它们的生命周期跨越多个业务操作。实体通常包含业务逻辑和状态。
  4. 值对象(Value Object)
    值对象是没有唯一标识的对象,它们通常用于表示业务概念中的值与前端交互。
  5. **聚合(Aggregate)
    **聚合是一组相关实体和值对象的集合,它们作为一个整体进行操作。聚合根(Aggregate Root)是聚合的入口点,负责维护聚合内部的一致性。
  6. 领域服务(Domain Service)
    领域服务用于封装不属于任何实体或值对象的业务逻辑。
  7. **领域事件(Domain Event)
    **领域事件用于表示领域中发生的特定事件。通过发布和订阅领域事件,可以实现业务逻辑的解耦和系统的扩展。
  8. **仓储(Repository)
    **仓储用于封装数据访问逻辑,提供对聚合的持久化和查询操作。仓储通常是接口,具体的实现放在基础设施层。
  9. 反腐层(Anti-Corruption Layer)

反腐层用于保护领域模型不受外部模型的影响,确保领域模型的纯洁性。

2.2、DDD 的四层架构

用户界面层(Interface)

负责处理用户交互,通常包括控制器(Controller)、视图(View)等组件。

应用层(Application)

定义系统的用例(Use Cases),但不包含具体的业务逻辑。应用层通常依赖于领域层来完成具体的业务操作。

领域层(Domain)

包含业务逻辑、业务实体、值对象、领域服务、聚合、仓储接口等。领域层是业务规则和业务逻辑的实现地。

基础设施层(Infrastructure)

提供技术支持,包括数据持久化、消息传递、外部服务调用等。基础设施层通常实现领域层中的仓储接口,并提供具体的持久化实现。

三、实战篇

系统业务功能包含用户和角色,功能比较简单,就是用户和角色创建、修改、删除。下面就一步步来实现

1、项目结构

csharp 复制代码
com
└── company
    └── um
        ├── ddd-infrastructure
        │   ├── dao
        │   │   ├── UserDAO.java
        │   │   └── RoleDAO.java
        │   ├── repository
        │   │   ├── UserRepository.java
        │   │   └── RoleRepository.java
        │   └── mapper
        │       ├── UserMapper.java
        │       └── RoleMapper.java
        ├── ddd-domain
        │   ├── entity
        │   │   ├── User.java
        │   │   └── Role.java
        │   ├── factory
        │   │   └── UserFactory.java
        │   ├── service
        │   │   └── RoleAssignmentService.java
        │   ├── event
        │   │   └── UserCreatedEvent.java
        │   └── exception
        │       └── DomainException.java
        ├── ddd-application
        │   ├── service
        │   │   ├── UserService.java
        │   │   └── RoleService.java
        │   └── dto
        │       ├── UserDTO.java
        │       └── RoleDTO.java
        └── ddd-interface
            ├── controller
            │   └── UserController.java
            └── vo
                ├── UserVO.java
                └── RoleVO.java

2、代码实现

1. 基础设施层 (ddd-infrastructure)
1.1 数据访问对象 (DAO)

UserDAO.java

csharp 复制代码
public interface UserDAO {
    void save(User user);
    User findById(Long id);
    void delete(User user);
}

RoleDAO.java

csharp 复制代码
public interface RoleDAO {
    void save(Role role);
    Role findById(Long id);
    void delete(Role role);
}
1.2 仓库 (Repository)

UserRepository.java

java 复制代码
public interface UserRepository {
    void save(User user);
    User findById(Long id);
    void delete(User user);
}

@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    private UserDAO userDAO;

    public void save(User user) {
        userDAO.save(user);
    }

    public User findById(Long id) {
        return userDAO.findById(id);
    }

    public void delete(User user) {
        userDAO.delete(user);
    }
}

RoleRepository.java

java 复制代码
public interface RoleRepository {
    void save(Role role);
    Role findById(Long id);
    void delete(Role role);
}

@Repository
public class RoleRepositoryImpl implements RoleRepository {
    @Autowired
    private RoleDAO roleDAO;

    public void save(Role role) {
        roleDAO.save(role);
    }

    public Role findById(Long id) {
        return roleDAO.findById(id);
    }

    public void delete(Role role) {
        roleDAO.delete(role);
    }
}
1.3 映射器 (Mapper)

UserMapper.java

java 复制代码
public interface UserMapper {
    UserDTO toDTO(User user);
    User toEntity(UserDTO userDTO);
}

@Component
public class UserMapperImpl implements UserMapper {
    public UserDTO toDTO(User user) {
        UserDTO userDTO = new UserDTO();
        userDTO.setId(user.getId());
        userDTO.setName(user.getName());
        // 其他属性映射
        return userDTO;
    }

    public User toEntity(UserDTO userDTO) {
        User user = new User();
        user.setId(userDTO.getId());
        user.setName(userDTO.getName());
        // 其他属性映射
        return user;
    }
}

RoleMapper.java

java 复制代码
public interface RoleMapper {
    RoleDTO toDTO(Role role);
    Role toEntity(RoleDTO roleDTO);
}

@Component
public class RoleMapperImpl implements RoleMapper {
    public RoleDTO toDTO(Role role) {
        RoleDTO roleDTO = new RoleDTO();
        roleDTO.setId(role.getId());
        roleDTO.setName(role.getName());
        // 其他属性映射
        return roleDTO;
    }

    public Role toEntity(RoleDTO roleDTO) {
        Role role = new Role();
        role.setId(roleDTO.getId());
        role.setName(roleDTO.getName());
        // 其他属性映射
        return role;
    }
}
2. 领域层 (ddd-domain)
2.1 实体 (Entity)

User.java

typescript 复制代码
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private Set<Role> roles = new HashSet<>();

    // 构造器、getter、setter 省略

    public void addRole(Role role) {
        roles.add(role);
        role.setUser(this);
    }

    public void removeRole(Role role) {
        roles.remove(role);
        role.setUser(null);
    }
}

Role.java

kotlin 复制代码
@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    // 构造器、getter、setter 省略

    public void setUser(User user) {
        this.user = user;
    }
}
2.2 工厂 (Factory)

UserFactory.java

typescript 复制代码
public class UserFactory {
    public static User createUser(Long id, String name) {
        User user = new User();
        user.setId(id);
        user.setName(name);
        // 其他属性设置
        return user;
    }
}
2.3 领域服务 (Domain Service)

RoleAssignmentService.java

typescript 复制代码
public class RoleAssignmentService {
    public void assignRoleToUser(User user, Role role) {
        if (user.hasRole(role)) {
            throw new DomainException("User already has the role");
        }
        user.addRole(role);
    }
}
2.4 领域事件 (Domain Event)

UserCreatedEvent.java

scala 复制代码
public class UserCreatedEvent extends Event {
    private User user;

    public UserCreatedEvent(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}
2.5 领域异常 (Domain Exception)

DomainException.java

scala 复制代码
public class DomainException extends RuntimeException {
    public DomainException(String message) {
        super(message);
    }
}
3. 应用层 (ddd-application)
3.1 应用服务 (Application Service)

UserService.java

java 复制代码
public interface UserService {
    void createUser(UserDTO userDTO);
    void updateUser(UserDTO userDTO);
    void deleteUser(Long id);
}

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EventPublisher eventPublisher;

    public void createUser(UserDTO userDTO) {
        User user = userMapper.toEntity(userDTO);
        userRepository.save(user);
        eventPublisher.publish(new UserCreatedEvent(user));
    }

    public void updateUser(UserDTO userDTO) {
        User user = userRepository.findById(userDTO.getId());
        if (user == null) {
            throw new RuntimeException("User not found");
        }
        user.setName(userDTO.getName());
        // 其他属性更新
        userRepository.save(user);
    }

    public void deleteUser(Long id) {
        User user = userRepository.findById(id);
        if (user == null) {
            throw new RuntimeException("User not found");
        }
        userRepository.delete(user);
    }
}

RoleService.java

java 复制代码
public interface RoleService {
    void createRole(RoleDTO roleDTO);
    void updateRole(RoleDTO roleDTO);
    void deleteRole(Long id);
}

@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private RoleMapper roleMapper;

    public void createRole(RoleDTO roleDTO) {
        Role role = roleMapper.toEntity(roleDTO);
        roleRepository.save(role);
    }

    public void updateRole(RoleDTO roleDTO) {
        Role role = roleRepository.findById(roleDTO.getId());
        if (role == null) {
            throw new RuntimeException("Role not found");
        }
        role.setName(roleDTO.getName());
        // 其他属性更新
        roleRepository.save(role);
    }

    public void deleteRole(Long id) {
        Role role = roleRepository.findById(id);
        if (role == null) {
            throw new RuntimeException("Role not found");
        }
        roleRepository.delete(role);
    }
}
3.2 数据传输对象 (DTO)

UserDTO.java

kotlin 复制代码
public class UserDTO {
    private Long id;
    private String name;
    // 其他属性
    // getter、setter 省略
}

RoleDTO.java

kotlin 复制代码
public class RoleDTO {
    private Long id;
    private String name;
    // 其他属性
    // getter、setter 省略
}
4. 表示层 (ddd-interface)
4.1 控制器 (Controller)

UserController.java

less 复制代码
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private UserMapper userMapper;

    @PostMapping
    public void createUser(@RequestBody UserDTO userDTO) {
        userService.createUser(userDTO);
    }

    @PutMapping
    public void updateUser(@RequestBody UserDTO userDTO) {
        userService.updateUser(userDTO);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}
4.2 值对象 (VO)

UserVO.java

kotlin 复制代码
public class UserVO {
    private Long id;
    private String name;
    // 其他属性
    // getter、setter 省略
}

RoleVO.java

kotlin 复制代码
public class RoleVO {
    private Long id;
    private String name;
    // 其他属性
    // getter、setter 省略
}

三、补充内容

1. 聚合与聚合根

在领域驱动设计中,聚合是业务一致性边界,聚合根是聚合的根实体,负责维护聚合内部的一致性。

在这个系统中,User 是聚合根,Role 是聚合中的实体。User 负责维护与 Role 之间的关系。

User.java

typescript 复制代码
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private Set<Role> roles = new HashSet<>();

    // 构造器、getter、setter 省略

    public void addRole(Role role) {
        roles.add(role);
        role.setUser(this);
    }

    public void removeRole(Role role) {
        roles.remove(role);
        role.setUser(null);
    }
}
2. 防腐层 (Anti-Corruption Layer)

防腐层用于隔离外部系统对领域层的影响,通常使用适配器模式来实现。

在这个系统中,假设我们使用的是JPA作为数据访问技术,可以在基础设施层添加一个防腐层,将JPA的具体实现隔离在防腐层中。

UserDAO.java

csharp 复制代码
public interface UserDAO {
    void save(User user);
    User findById(Long id);
    void delete(User user);
}

UserDAOJPAAdapter.java

typescript 复制代码
@Repository
public class UserDAOJPAAdapter implements UserDAO {
    @PersistenceContext
    private EntityManager entityManager;

    public void save(User user) {
        entityManager.persist(user);
    }

    public User findById(Long id) {
        return entityManager.find(User.class, id);
    }

    public void delete(User user) {
        entityManager.remove(user);
    }
}

我是栈江湖,如果你喜欢此文章,不要忘记点赞+关注

相关推荐
Java中文社群几秒前
SpringAI版本更新:向量数据库不可用的解决方案!
java·人工智能·后端
日月星辰Ace2 分钟前
蓝绿部署
运维·后端
D龙源4 分钟前
VSCode-IoC和DI
后端·架构
王磊鑫14 分钟前
重返JAVA之路——图书管理系统
java·开发语言
听闻风很好吃17 分钟前
Java设计模式之观察者模式:从入门到架构级实践
java·观察者模式·设计模式
艺杯羹19 分钟前
JDBC 初认识、速了解
java·数据库·jdbc
陵易居士20 分钟前
Spring如何解决项目中的循环依赖问题?
java·后端·spring
铁弹神侯27 分钟前
Maven相关名词及相关配置
java·maven
Aska_Lv33 分钟前
RocketMQ---core原理
后端
AronTing38 分钟前
10-Spring Cloud Alibaba 之 Dubbo 深度剖析与实战
后端·面试·架构