zoukankan      html  css  js  c++  java
  • ABP VNext 微服务搭建入门(3)-- 业务逻辑写在哪里

    业务逻辑可以分为领域逻辑非领域逻辑。一般来说,领域逻辑包含新增修改,由领域驱动且不易变,非领域逻辑包含查询删除,由数据驱动且易变

    一、领域逻辑

    1、领域模型

    单个实体内部的领域逻辑,不进行持久化,持久化交给上层处理,如领域服务,应用服务。

    public class Product : AuditedAggregateRoot<Guid>
        {
            [NotNull]
            public string Code { get; private set; }
    
            [NotNull]
            public string Name { get; private set; }
    
            public float Price { get; private set; }
    
            public int StockCount { get; private set; }
    
            public string ImageName { get; private set; }
    
            private Product()
            {
                //Default constructor is needed for ORMs.
            }
    
            internal Product(
                Guid id,
                [NotNull] string code, 
                [NotNull] string name, 
                float price = 0.0f, 
                int stockCount = 0,
                string imageName = null)
            {
                Check.NotNullOrWhiteSpace(code, nameof(code));
    
                if (code.Length >= ProductConsts.MaxCodeLength)
                {
                    throw new ArgumentException($"Product code can not be longer than {ProductConsts.MaxCodeLength}");
                }
    
                Id = id;
                Code = code;
                SetName(Check.NotNullOrWhiteSpace(name, nameof(name)));
                SetPrice(price);
                SetImageName(imageName);
                SetStockCountInternal(stockCount, triggerEvent: false);
            }
    
            public Product SetName([NotNull] string name)
            {
                Check.NotNullOrWhiteSpace(name, nameof(name));
    
                if (name.Length >= ProductConsts.MaxNameLength)
                {
                    throw new ArgumentException($"Product name can not be longer than {ProductConsts.MaxNameLength}");
                }
    
                Name = name;
                return this;
            }
              ...
          }
    

    2、领域服务

    涉及一个或多个完整实体的领域逻辑。实现 DomainService

    public class ProductManager : DomainService
    {
        private readonly IRepository<Product, Guid> _productRepository;
    
        public ProductManager(IRepository<Product, Guid> productRepository)
        {
            _productRepository = productRepository;
        }
    
        public async Task<Product> CreateAsync(
            [NotNull] string code,
            [NotNull] string name,
            float price = 0.0f,
            int stockCount = 0)
        {
            var existingProduct = 
                await _productRepository.FirstOrDefaultAsync(p => p.Code == code);
                
            if (existingProduct != null)
            {
                throw new ProductCodeAlreadyExistsException(code);
            }
    
            return await _productRepository.InsertAsync(
                new Product(
                    GuidGenerator.Create(),
                    code,
                    name,
                    price,
                    stockCount
                )
            );
        }
    }
    
    

    3、领域事件

    通过事件的发布订阅来处理领域逻辑,对复杂的流程业务进行解耦,实现事务的最终一致性。领域事件可以分为本地事件和分布式事件。

    public class Product : AuditedAggregateRoot<Guid>
        {
            ...
    
            public Product SetStockCount(int stockCount)
            {
                return SetStockCountInternal(stockCount);
            }
    
            private Product SetStockCountInternal(int stockCount, bool triggerEvent = true)
            {
                if (StockCount < 0)
                {
                    throw new ArgumentException($"{nameof(stockCount)} can not be less than 0!");
                }
    
                if (StockCount == stockCount)
                {
                    return this;
                }
    
                if (triggerEvent)
                {
                    AddDistributedEvent(
                        new ProductStockCountChangedEto(
                            Id,
                            StockCount,
                            stockCount
                        )
                    );
                }
    
                StockCount = stockCount;
                return this;
            }
         }
    

    二、非领域逻辑

    仓储

    仓储用于保存和获取聚合对象。仓储分为两种,一种是基于集合的,一种是基于持久化的。Abp 的 IRespository 实现了常用的CRUD方法。
    如果不够用(极少情况),可以自定义仓储实现IRespository。所有不含业务逻辑的CRUD都写在这里。代码实现写在基础架构层,接口定义在Domian层。

    应用服务

    负责调用领域逻辑增改和处理非领域逻辑的查删,并持久化。实现 ApplicationService。

    [Authorize(ProductManagementPermissions.Products.Default)]
    public class ProductAppService : ApplicationService, IProductAppService
    {
    	private readonly ProductManager _productManager;
    	private readonly IRepository<Product, Guid> _productRepository;
    
    	public ProductAppService(ProductManager productManager, IRepository<Product, Guid> productRepository)
    	{
    		_productManager = productManager;
    		_productRepository = productRepository;
    	}
    
    	public async Task<PagedResultDto<ProductDto>> GetListPagedAsync(PagedAndSortedResultRequestDto input)
    	{
    		await NormalizeMaxResultCountAsync(input);
    
    		var products = await _productRepository
    			.OrderBy(input.Sorting ?? "Name")
    			.Skip(input.SkipCount)
    			.Take(input.MaxResultCount)
    			.ToListAsync();
    
    		var totalCount = await _productRepository.GetCountAsync();
    
    		var dtos = ObjectMapper.Map<List<Product>, List<ProductDto>>(products);
    
    		return new PagedResultDto<ProductDto>(totalCount, dtos);
    	}
    
    	public async Task<ListResultDto<ProductDto>> GetListAsync() //TODO: Why there are two GetList. GetListPagedAsync would be enough (rename it to GetList)!
    	{
    		var products = await _productRepository.GetListAsync();
    
    		var productList =  ObjectMapper.Map<List<Product>, List<ProductDto>>(products);
    
    		return new ListResultDto<ProductDto>(productList);
    	}
    
    	public async Task<ProductDto> GetAsync(Guid id)
    	{
    		var product = await _productRepository.GetAsync(id);
    
    		return ObjectMapper.Map<Product, ProductDto>(product);
    	}
    
    	[Authorize(ProductManagementPermissions.Products.Create)]
    	public async Task<ProductDto> CreateAsync(CreateProductDto input)
    	{
    		var product = await _productManager.CreateAsync(
    			input.Code,
    			input.Name,
    			input.Price,
    			input.StockCount,
    			input.ImageName
    		);
    
    		return ObjectMapper.Map<Product, ProductDto>(product);
    	}
    
    	[Authorize(ProductManagementPermissions.Products.Update)]
    	public async Task<ProductDto> UpdateAsync(Guid id, UpdateProductDto input)
    	{
    		var product = await _productRepository.GetAsync(id);
    
    		product.SetName(input.Name);
    		product.SetPrice(input.Price);
    		product.SetStockCount(input.StockCount);
    		product.SetImageName(input.ImageName);
    
    		return ObjectMapper.Map<Product, ProductDto>(product);
    	}
    
    	[Authorize(ProductManagementPermissions.Products.Delete)]
    	public async Task DeleteAsync(Guid id)
    	{
    		await _productRepository.DeleteAsync(id);
    	}
    
    	private async Task NormalizeMaxResultCountAsync(PagedAndSortedResultRequestDto input)
    	{
    		var maxPageSize = (await SettingProvider.GetOrNullAsync(ProductManagementSettings.MaxPageSize))?.To<int>();
    		if (maxPageSize.HasValue && input.MaxResultCount > maxPageSize.Value)
    		{
    			input.MaxResultCount = maxPageSize.Value;
    		}
    	}
    }
    
  • 相关阅读:
    Panorama和Pivot的区别
    Windows phone 全景视图
    在usercontrol里实现导航
    (App.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
    Windows phone重写返回键
    Windows Phone 8弹窗
    Kotlin 区间的一些小注意
    Kotlin 区间和循环 Loop和Range
    Kotlin when 流程判断
    Kotlin 在kotlin内使用Java的一些注意(长篇)
  • 原文地址:https://www.cnblogs.com/zk-ljc/p/14092605.html
Copyright © 2011-2022 走看看