跳到主要内容

DDD 领域驱动设计指南

FreeKitModules 采用 DDD(领域驱动设计)架构,提供完整的分层实现。

架构分层

┌─────────────────────────────────────────┐
│ Controllers / API │ ← 接口层
├─────────────────────────────────────────┤
│ Application Services │ ← 应用层
├─────────────────────────────────────────┤
│ Domain Services / Entities / Events │ ← 领域层
├─────────────────────────────────────────┤
│ Infrastructure (FreeSql, Redis, etc.) │ ← 基础设施层
└─────────────────────────────────────────┘

实体设计

基类选择

基类适用场景
Entity<Guid>只需要主键
Entity<Guid>, ISoftDelete需要软删除
FullAuditEntity<Guid, Guid>完整审计(推荐)

示例:多租户文章

using IGeekFan.FreeKit.Extras.AuditEntity;

public class Article : FullAuditEntity<Guid, Guid>, ITenant
{
public Guid? TenantId { get; set; }
public string Title { get; set; } = default!;
public string Content { get; set; } = default!;
}

自动填充字段

继承 FullAuditEntity 后自动获得:

字段说明
IdGuid 主键
CreateUserId / CreateTime创建人/时间
UpdateUserId / UpdateUserName / UpdateTime修改人/时间
DeleteUserId / DeleteUserName / DeleteTime删除人/时间
IsDeleted软删除标记
TenantId租户 ID

领域事件

定义事件

public sealed record ArticlePublishedEvent(Guid ArticleId) : IDomainEvent;

触发事件

public sealed class Article : DomainEventBase
{
public Guid Id { get; set; }

public void Publish()
{
AddDomainEvent(new ArticlePublishedEvent(Id));
}

public override object[] GetKeys() => [Id];
}

处理事件

public class ArticlePublishedHandler : INotificationHandler<ArticlePublishedEvent>
{
public Task Handle(ArticlePublishedEvent e, CancellationToken ct)
{
// 发送通知、更新统计等
return Task.CompletedTask;
}
}

仓储模式

定义仓储接口

public interface IArticleRepository : IBaseRepository<Article, Guid>
{
}

使用仓储

public class ArticleService : IScopedDependency
{
private readonly IArticleRepository _repo;

public ArticleService(IArticleRepository repo)
{
_repo = repo;
}

public async Task<Article> GetByIdAsync(Guid id)
{
return await _repo.FindAsync(id);
}

public async Task<List<Article>> GetListAsync()
{
return await _repo.Select.ToListAsync();
}
}

事务管理

使用事务

[Transactional]
public async Task TransferAsync(Guid fromId, Guid toId, decimal amount)
{
var from = await _repo.FindAsync(fromId);
var to = await _repo.FindAsync(toId);

from.Balance -= amount;
to.Balance += amount;

await _repo.UpdateAsync(from);
await _repo.UpdateAsync(to);
// 异常自动回滚
}

事务配置

特性说明
[Transactional]默认新事务
[Transactional(IsDisabled = true)]禁用事务
[Transactional(Propagation = Propagation.ReQUIRES_NEW)]总是新事务

值对象

public class Address : ValueObject
{
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }

protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return ZipCode;
}
}

聚合根

public class Order : AggregateRootBase<Guid>
{
public Guid CustomerId { get; set; }
public List<OrderItem> Items { get; set; } = new();

public decimal TotalAmount => Items.Sum(i => i.Price * i.Quantity);

public void AddItem(Guid productId, int quantity, decimal price)
{
Items.Add(new OrderItem
{
ProductId = productId,
Quantity = quantity,
Price = price
});
}
}

依赖注入标记

配合 Autofac 自动注册服务:

// 每次请求新实例
public class ArticleService : IScopedDependency
{
}

// 单例
public class CacheService : ISingletonDependency
{
}

// 瞬时
public class EmailSender : ITransientDependency
{
}

最佳实践

实体设计原则

  1. 单一职责:一个实体只负责一个业务概念
  2. 值对象优先:没有独立身份的属性用值对象
  3. 聚合边界:明确聚合根和聚合内实体的关系
  4. 领域事件:跨聚合通信使用领域事件

命名规范

接口实现示例
Domain/IXxxManagerXxxManagerIArticleManager / ArticleManager
Application/IXxxServiceXxxServiceIArticleService / ArticleService
Controllers/XxxControllerArticleController

相关文档