从零掌握CleanArchitecture领域模型:实体与值对象实战

从零掌握CleanArchitecture领域模型:实体与值对象实战

【免费下载链接】CleanArchitecture CleanArchitecture 是一个基于.NET Core的应用程序模板项目,遵循干净架构原则。它为软件项目提供了一个清晰的分层结构,有助于分离关注点、提升可维护性和重用性。适合用于构建具有良好架构基础的中大型企业应用。 【免费下载链接】CleanArchitecture 项目地址: https://gitcode.com/GitHub_Trending/cl/CleanArchitecture

你还在为业务代码混乱不堪而头疼?团队协作时总因模型设计分歧争论不休?本文将通过CleanArchitecture项目的真实案例,带你彻底搞懂实体(Entity)与值对象(Value Object)的设计精髓,学会用领域驱动设计(DDD)思想构建稳定可靠的业务核心。读完本文你将掌握:实体与值对象的核心区别、实战设计技巧、以及如何在.NET项目中落地实现。

领域模型的基石:实体与值对象

在CleanArchitecture中,领域模型是业务规则的核心载体。项目采用经典分层架构,领域层(Core)包含了所有业务实体与值对象,如sample/src/NimblePros.SampleToDo.Core/ProjectAggregate/目录下的实现。这两种模式的正确应用,直接决定了系统的可维护性和扩展性。

项目架构分层

实体(Entity):有身份的业务对象

实体是具有唯一标识的业务对象,其生命周期内标识保持不变。以项目中的Project类为例:

public class Project : EntityBase<Project, ProjectId>, IAggregateRoot
{
    public ProjectName Name { get; private set; }
    private readonly List<ToDoItem> _items = [];
    public IEnumerable<ToDoItem> Items => _items.AsReadOnly();
    public ProjectStatus Status => _items.All(i => i.IsDone) ? ProjectStatus.Complete : ProjectStatus.InProgress;

    public Project(ProjectName name)
    {
        Name = name;
    }

    public Project AddItem(ToDoItem newItem)
    {
        Guard.Against.Null(newItem);
        _items.Add(newItem);
        var newItemAddedEvent = new NewItemAddedEvent(this, newItem);
        base.RegisterDomainEvent(newItemAddedEvent);
        return this;
    }
}

完整代码

实体的三大特征在代码中清晰体现:

  1. 唯一标识:继承EntityBase<Project, ProjectId>,使用强类型ProjectId作为标识
  2. 生命周期:通过AddItem等方法维护状态变化
  3. 领域行为:封装业务规则(如计算Status属性)

值对象:无身份的不可变数据容器

值对象用于描述业务属性,没有唯一标识,通过属性值判断相等性。项目中的ProjectName是典型实现:

[ValueObject<string>(conversions: Conversions.SystemTextJson)]
public partial struct ProjectName
{
    private static Validation Validate(in string name) => 
        String.IsNullOrEmpty(name) ? Validation.Invalid("Name cannot be empty") : Validation.Ok;
}

完整代码

值对象设计要点:

  • 不可变性:所有属性设置为只读
  • 值相等性:通过GetEqualityComponents实现值比较
  • 自我验证:在创建时验证数据有效性

实战应用:实体与值对象的协同工作

在CleanArchitecture中,实体与值对象通常配合使用。以项目任务管理场景为例:

// 创建项目(实体)
var project = new Project(new ProjectName("网站重构"));

// 添加任务(实体)
var task = new ToDoItem(Priority.High)
{
    Title = "设计首页原型",
    Description = "完成移动端响应式设计"
};
project.AddItem(task);

// 分配负责人(值对象操作)
task.AddContributor(contributorId);

实体与值对象的典型组合:

实体包含的值对象用途
ProjectProjectId, ProjectName项目基本信息
ToDoItemToDoItemId, Priority任务详情
ContributorPhoneNumber贡献者联系方式

最佳实践与避坑指南

1. 何时使用实体vs值对象

  • 实体:需要跟踪生命周期、有独立业务行为(如Project.AddItem
  • 值对象:仅描述属性、无业务行为、可整体替换(如PhoneNumber

2. 强类型ID的优势

项目广泛使用强类型ID,如ProjectIdToDoItemId

[ValueObject<int>]
public partial struct ToDoItemId;

完整代码

相比int类型ID,强类型ID避免了参数顺序错误,提升代码可读性。

3. 领域事件的集成

实体可通过注册领域事件实现跨对象通信:

// 在ToDoItem中标记完成时触发事件
public ToDoItem MarkComplete()
{
    if (!IsDone)
    {
        IsDone = true;
        RegisterDomainEvent(new ToDoItemCompletedEvent(this));
    }
    return this;
}

完整代码

总结与下一步

实体与值对象是CleanArchitecture的核心构建块,正确应用这两种模式能显著提升代码质量。通过本文介绍的:

  • 实体的身份标识与生命周期管理
  • 值对象的不可变性与自我验证
  • 强类型ID与领域事件的最佳实践

你已具备设计清晰领域模型的基础。建议进一步阅读:

掌握这些设计模式,让你的.NET项目架构更清晰、业务逻辑更健壮!收藏本文,关注后续关于仓储模式与领域服务的深度解析。

【免费下载链接】CleanArchitecture CleanArchitecture 是一个基于.NET Core的应用程序模板项目,遵循干净架构原则。它为软件项目提供了一个清晰的分层结构,有助于分离关注点、提升可维护性和重用性。适合用于构建具有良好架构基础的中大型企业应用。 【免费下载链接】CleanArchitecture 项目地址: https://gitcode.com/GitHub_Trending/cl/CleanArchitecture

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值