在.NET Core中实现领域驱动设计(DDD):电商订单管理示例


领域驱动设计(DDD)是一种通过深入理解业务领域来指导系统设计的架构模式。在.NET Core中应用DDD的思想,可以帮助开发者在复杂的业务场景下构建高内聚、低耦合的系统架构。本篇文章将通过一个电商系统中的订单管理模块为例,展示如何在.NET Core中实现DDD,深入理解聚合根、实体、值对象、应用层、领域服务等DDD核心概念。

一、项目背景

假设我们正在构建一个电商系统,其中最基础的业务对象之一就是“订单”。订单管理包括多个操作,如创建订单、添加订单项、更新订单状态等。为了使系统易于维护和扩展,我们将使用领域驱动设计(DDD)来组织代码。具体地,我们会使用以下核心概念来构建这一部分功能:

  • 领域模型(Domain Model):包括订单(Order)、订单项(OrderItem)等实体。
  • 聚合根(Aggregate Root):订单(Order)是聚合根,负责管理订单项。
  • 值对象(Value Object):可能涉及到一些不可变的对象,如货币金额、地址等(本示例中未深入展开)。
  • 领域服务(Domain Service):处理与业务逻辑相关的操作。
  • 应用层(Application Layer):协调领域服务和外部资源(如数据库)的交互。
  • 仓储(Repository):负责持久化和加载领域对象。
  • Web层(Web Layer):提供API接口供外部系统访问。

目录结构

首先,为了组织好代码,我们可以遵循以下推荐的项目结构:

ECommerceApp/
│
├── Application/          // 用于封装应用程序服务层
│   └── OrderService.cs   // 业务逻辑服务层
│
├── Domain/               // 包含领域模型和业务规则
│   ├── Order.cs          // 订单实体
│   ├── OrderItem.cs      // 订单项实体
│   ├── IOrderRepository.cs // 订单仓储接口
│   └── OrderStatus.cs    // 订单状态(枚举)
│
├── Infrastructure/       // 数据访问层(实现仓储接口)
│   └── OrderRepository.cs  // 订单仓储实现
│
├── Web/                  // ASP.NET Core 控制器和API层
│   └── OrderController.cs // 控制器
│
└── ECommerceApp.sln      // 解决方案文件

二、领域模型(Domain)

在DDD中,领域模型是应用程序的核心,它定义了业务逻辑和业务规则。我们将在这一层实现订单实体(Order)、订单项实体(OrderItem)、订单状态枚举(OrderStatus)以及订单仓储接口(IOrderRepository)。

1. 订单实体(Order)

订单实体(Order)是一个聚合根,负责管理订单的各个方面,比如订单项的添加和订单状态的变更。

namespace ECommerceApp.Domain
{
    public class Order
    {
        public int Id { get; private set; }
        public string CustomerName { get; private set; }
        public OrderStatus Status { get; private set; }
        public List<OrderItem> OrderItems { get; private set; }

        // 构造函数:订单一旦创建,不能更改订单项的数量
        public Order(string customerName)
        {
            CustomerName = customerName;
            Status = OrderStatus.Pending;
            OrderItems = new List<OrderItem>();
        }

        // 添加订单项:确保订单项的数量大于0
        public void AddOrderItem(string productName, decimal price, int quantity)
        {
            if (quantity <= 0) throw new InvalidOperationException("Order item quantity must be greater than zero.");
            OrderItems.Add(new OrderItem(productName, price, quantity));
        }

        // 改变订单状态
        public void ChangeStatus(OrderStatus newStatus)
        {
            Status = newStatus;
        }
    }
}

2. 订单项实体(OrderItem)

订单项(OrderItem)是订单聚合内的一个实体,表示一个具体的商品项,包括商品名称、价格和数量。

namespace ECommerceApp.Domain
{
    public class OrderItem
    {
        public string ProductName { get; private set; }
        public decimal Price { get; private set; }
        public int Quantity { get; private set; }

        public OrderItem(string productName, decimal price, int quantity)
        {
            ProductName = productName;
            Price = price;
            Quantity = quantity;
        }
    }
}

3. 订单状态(OrderStatus)

订单状态(OrderStatus)是一个枚举,表示订单的不同生命周期状态。

namespace ECommerceApp.Domain
{
    public enum OrderStatus
    {
        Pending,
        Paid,
        Shipped,
        Delivered
    }
}

4. 订单仓储接口(IOrderRepository)

仓储接口(IOrderRepository)用于从数据存储中加载和保存订单对象。

namespace ECommerceApp.Domain
{
    public interface IOrderRepository
    {
        Task<Order> GetOrderByIdAsync(int orderId);
        Task AddAsync(Order order);
        Task SaveAsync();
    }
}

三、应用层(Application)

应用层负责协调领域模型和外部系统的交互。它通常包含一些业务逻辑服务,在此层中不会包含复杂的领域逻辑。

订单服务(OrderService)

namespace ECommerceApp.Application
{
    public class OrderService
    {
        private readonly IOrderRepository _orderRepository;

        public OrderService(IOrderRepository orderRepository)
        {
            _orderRepository = orderRepository;
        }

        // 创建订单并添加订单项
        public async Task CreateOrderAsync(string customerName, List<(string productName, decimal price, int quantity)> orderItems)
        {
            var order = new Order(customerName);

            foreach (var item in orderItems)
            {
                order.AddOrderItem(item.productName, item.price, item.quantity);
            }

            await _orderRepository.AddAsync(order);
            await _orderRepository.SaveAsync();
        }

        // 改变订单状态
        public async Task ChangeOrderStatusAsync(int orderId, OrderStatus newStatus)
        {
            var order = await _orderRepository.GetOrderByIdAsync(orderId);
            if (order == null) throw new Exception("Order not found.");
            order.ChangeStatus(newStatus);

            await _orderRepository.SaveAsync();
        }
    }
}

四、基础设施层(Infrastructure)

基础设施层提供具体的实现,例如数据存储操作、第三方API集成等。在这里,我们实现了订单仓储的内存模拟版本。

订单仓储实现(OrderRepository)

namespace ECommerceApp.Infrastructure
{
    public class OrderRepository : IOrderRepository
    {
        private readonly List<Order> _orders = new List<Order>();

        public async Task<Order> GetOrderByIdAsync(int orderId)
        {
            return await Task.FromResult(_orders.FirstOrDefault(o => o.Id == orderId));
        }

        public async Task AddAsync(Order order)
        {
            order = new Order(order.CustomerName); // Simulate creating an ID or other operations
            _orders.Add(order);
            await Task.CompletedTask;
        }

        public async Task SaveAsync()
        {
            // In a real application, you would persist changes to a database here
            await Task.CompletedTask;
        }
    }
}

五、Web层(Web)

在ASP.NET Core的Web层中,我们通过控制器暴露API接口,允许外部调用应用程序服务。

订单控制器(OrderController)

using Microsoft.AspNetCore.Mvc;
using ECommerceApp.Application;

namespace ECommerceApp.Web.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class OrderController : ControllerBase
    {
        private readonly OrderService _orderService;

        public OrderController(OrderService orderService)
        {
            _orderService = orderService;
        }

        // 创建订单
        [HttpPost]
        public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
        {
            await _orderService.CreateOrderAsync(request.CustomerName, request.OrderItems);
            return Ok();
        }

        // 修改订单状态
        [HttpPut("{orderId}/status")]
        public async Task<IActionResult> ChangeStatus(int orderId, [FromBody] ChangeStatusRequest request)
        {
            await _orderService.ChangeOrderStatusAsync(orderId, request.NewStatus);
            return Ok();
        }
    }

    public class CreateOrderRequest
    {
        public string CustomerName { get; set; }
        public List<(string productName, decimal price, int quantity)> OrderItems { get; set; }
    }

    public class ChangeStatusRequest
    {
        public OrderStatus NewStatus { get; set; }
    }
}

六、总结

通过本示例,我们展示了如何在.NET Core中实现一个电商系统的订单管理部分,并采用DDD的设计理念。具体包括:

  1. 领域层:实现了订单(Order)、订单项(OrderItem)、订单状态(OrderStatus)等领域对象和业务规则。
  2. 应用层:通过OrderService提供业务逻辑,协调领域模型与外部资源的交互。
  3. 基础设施层:通过OrderRepository实现数据存储操作(在本示例中模拟数据库)。
  4. Web层:通过OrderController暴露RESTful API端点,供外部系统调用。

这种分层结构不仅使代码更加模块化、易于扩展,而且也使得系统的业务逻辑更加清晰,业务需求的变化可以灵活地反映到领域模型中,从而提高系统的可维护性和可扩展性。

posted @   努力,努力再努力  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示