DDD实战进阶第一波(四):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架三)
上一篇文章我们讲了经典DDD架构对比传统三层架构的优势,以及经典DDD架构每一层的职责后,本篇文章将介绍基础结构层中支持DDD的轻量级框架的主要代码。
这里需要说明的是,DDD轻量级框架能够体现DDD的思想即可,没必要做得很重,你也可以根据理解,自己实现支持DDD的框架。
1.实体、聚合根与值对象的顶层体现
实体顶层定义:
public interface IEntity
{
string Code { get; set; }
Guid Id { get; set; }
}
Id是一个未来存储到数据库表中的技术主键,Code是领域对象的唯一业务标识符。你也可以扩展这个接口,定义两个实体比较接口(未来实现就是比较两个实体如果Code一致,则代表两个实体相等)。
聚合根顶层定义:
public interface IAggregationRoot:IEntity
{ }
聚合根接口就是从实体接口继承,只是未来的用法可以在仓储中定义持久化时的领域对象必须从这个接口或继承了这个接口的抽象类继承下来的。
值对象顶层定义:
public interface IValueObject
{
Guid Id { get; set; }
}
值对象接口只需要保留一个技术主键即可,它没有业务标识符。在数据库中,值对象可能作为单独表存储,也可以作为实体的一部分存储。你也可以扩展这个接口,定义两个值对象比较接口(未来实现
就是比较两个值对象如果所有属性值一致,则代表两个值对象相等)。
工作单元顶层定义:
public interface IUnitOfWork
{
void Commit();
}
工作单元接口就定义了一个提交方法,在具体实现时,其实就是对应的EF Core的整个聚合的事务提交方法。
仓储接口顶层定义:
public interface IRepository:IUnitOfWork,IDisposable
{
}
仓储接口从工作单元接口与资源释放接口继承,为未来的数据访问框架和可替换性提供顶层约束。
EF Core顶层仓储持久化实现:
public class EFCoreRepository : IRepository
{
private readonly DbContext context;
public EFCoreRepository(DbContext context)
{
this.context = context;
}
public void Commit()
{
try
{
context.SaveChanges();
}
catch(Exception error)
{
throw error;
}
} public void Dispose()
{
context.Dispose();
}
}
从上述代码中可以看到,主要实现了仓储接口的Commit方法,其实就是使用了EF Core的DbContext数据访问上下文类的SaveChanges()事务提交方法,应用服务层的用例就可以获取到某个聚合根的当前状态,然后调用仓储接口的Commit方法,实现了整个聚合所有对象的一次性事务提交。
2.常用工具类的实现
我们还应该定义另一个项目,这个项目是整个系统都需要使用到的工具,其中至少应该包括Asp.net Core Json配置文件的读,Json序列化与反序列化,加密,依赖注入,返回给前端的对象格式定义等,这里
先列出几个需要的,其他的在后面具体案例中在补充。
Asp.net Core Json配置文件读取:
Json配置文件会存储我们的一些配置信息,比如数据库连接字符串,微信AppId与AppSecure等,所以需要有功能支持Json配置文件的Key到Value的读取
public class AppSetting
{
private static IConfigurationSection appsections = null;
public static void SetAppSetting(IConfigurationSection section)
{
appsections = section;
}
public static string GetAppSetting(string key)
{
string str = "";
if (appsections.GetSection(key) != null)
{
str = appsections.GetSection(key).Value;
}
return str;
}
}
返回前端的对象格式定义:
我们的应用服务层将返回WebApi接口一定的数据格式,WebApi接口也会将这个数据返回给前端,前端拿到后就会做相应的处理。
public class ResultEntity<T>
{
public bool IsSuccess { get; set; }
public string Msg { get; set; }
public T Data { get; set; }
public int ErrorCode { get; set; }
public int Count { get; set; }
}
public class BaseAppSrv
{
protected ResultEntity<T> GetResultEntity<T>(T vobj,string msg="未成功获取到对象",int errorcode = )
{
var ueresult = new ResultEntity<T>();
var issuccess = true;
if(vobj is int && Convert.ToInt32(vobj) <= )
{
issuccess = false;
}
else if(vobj is bool && !Convert.ToBoolean(vobj))
{
issuccess = false;
}
else if(vobj is string && string.IsNullOrEmpty(Convert.ToString(vobj)))
{
issuccess = false;
}
if (!issuccess)
{
ueresult.Msg = msg;
ueresult.ErrorCode = ;
}
ueresult.IsSuccess = issuccess;
ueresult.Data = vobj;
return ueresult;
}
}
未来所有的用例都将从BaseAppSrv继承,最终返回的格式都是ResultEntity<T>。
好了,基本的框架搭建好了,下一章就可以直接进入案例,看案例中如何通过DDD思想进行设计,并通过经典DDD架构与DDD轻量级框架进行实际业务系统的代码编写。
QQ讨论群:309287205
DDD实战进阶视频请关注微信公众号:
DDD实战进阶第一波(四):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架三)的更多相关文章
- DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述)
本系列文章 DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述) DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一) 近年来,关于如何开发基于 ...
- DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一)
要实现软件设计.软件开发在一个统一的思想.统一的节奏下进行,就应该有一个轻量级的框架对开发过程与代码编写做一定的约束. 虽然DDD是一个软件开发的方法,而不是具体的技术或框架,但拥有一个轻量级的框架仍 ...
- DDD实战进阶第一波(八):开发一般业务的大健康行业直销系统(业务逻辑条件判断最佳实践)
这篇文章其实是大健康行业直销系统的番外篇,主要给大家讲讲如何在领域逻辑中,有效的处理业务逻辑条件判断的最佳实践问题. 大家都知道,聚合根.实体和值对象这些领域对象都自身处理自己的业务逻辑.在业务处理过 ...
- DDD实战进阶第一波(三):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架二)
了解了DDD的好处与基本的核心组件后,我们先不急着进入支持DDD思想的轻量级框架开发,也不急于直销系统需求分析和具体代码实现,我们还少一块, 那就是经典DDD的架构,只有了解了经典DDD的架构,你才能 ...
- DDD实战进阶第一波(十四):开发一般业务的大健康行业直销系统(订单上下文应用服务用例与接口)
上一篇文章我们主要讲了订单上下文的领域逻辑,在领域逻辑中完成了订单项的计算逻辑.订单的计算逻辑以及如何生成相应的实体code,这篇文章我们通过 在应用服务中实现一个下单的用例,来将这些领域逻辑以及仓储 ...
- DDD实战进阶第一波(五):开发一般业务的大健康行业直销系统(实现产品上下文领域层)
从这篇文章开始,我们根据前面的DDD理论与DDD框架的约束,正式进入直销系统案例的开发. 本篇文章主要讲产品上下文中的领域层的主要实现,先简单讲下业务方面的需求:产品SPU与产品SKU,产品SPU主要 ...
- DDD实战进阶第一波(十五):开发一般业务的大健康行业直销系统(总结篇)
前面我们花了14篇的文章来给大家介绍经典DDD的概念.架构和实践.这篇文章我们来做一个完整的总结,另外生成一个Api接口文档. 一.DDD解决传统的开发的几大问题: 没有描述需求的设计模型:而是直接通 ...
- DDD实战进阶第一波(六):开发一般业务的大健康行业直销系统(实现产品上下文仓储与应用服务层)
前一篇文章我们完成了产品上下文的领域层,我们已经有了关于产品方面的简单领域逻辑,我们接着来实现产品上下文关于仓储持久化与应用层的用例如何来协调 领域逻辑与仓储持久化. 首先大家需要明确的是,产品上下文 ...
- DDD实战进阶第一波(十二):开发一般业务的大健康行业直销系统(订单上下文POCO模型)
在本系列前面的文章中,我们主要讨论了产品上下文与经销商上下文相关的实现,大家对DDD的方法与架构已经有了初步的了解. 但是在这两个界限上下文中,业务逻辑很简单,也没有用到更多的值对象的内容.从这篇文章 ...
随机推荐
- 大数据学习笔记1-大数据处理架构Hadoop
Hadoop:一个开源的.可运行于大规模集群上的分布式计算平台.实现了MapReduce计算模型和分布式文件系统HDFS等功能,方便用户轻松编写分布式并行程序. Hadoop生态系统: HDFS:Ha ...
- http://ctf.bugku.com/challenges#Mountain%20climbing:bugku--Mountain-Climbing
分析这道题,爽,能够结合IDA和ollydbg分析代码,美滋滋.但如果以后能直接根据汇编容易地看懂逻辑那就更好了. 参考链接: https://blog.csdn.net/cossack9989/ ...
- [leetcode]53. Maximum Subarray最大子数组和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- spring整合kafka(配置文件方式 生产者)
Kafka官方文档有 https://docs.spring.io/spring-kafka/reference/htmlsingle/ 这里是配置文件实现的方式 先引入依赖 <depend ...
- node.js中path路径模块的使用
path模块是node.js中处理路径的核心模块.可以很方便的处理关于文件路径的问题. join() 将多个参数值合并成一个路径 const path = require('path'); conso ...
- vue组件之时间组件
效果图 主要有两个注意点,前面时分,通过定时器,1秒钟取一次,只要数据变了立刻让他展示,当然也可以1分钟取一次,我看了下定时器和真正的时间 其实有一定的偏差的,大约要1分多才会改变,所以我用了1秒取一 ...
- MySQL优化(五) SQL 语句的优化 索引、explain
一.索引 1.分类 (1)主键索引:当一张表的某个字段设置为主键时,该字段就是主键索引: (2)唯一索引:索引列中的值必须是唯一的,但是允许为空值(可以存在多个null): (3)普通索引:基本索引类 ...
- osg探究补充:Node::accept(NodeVisitor& nv)及NodeVisitor简介
前言 在前几节中,我自己觉得讲的比较粗糙,因为实在是时间上不是很充足,今天我想弥补一下,希望不是亡羊补牢.我们在osgViewer::Viewer::eventTraversal()函数中经常看到这么 ...
- 201621123002《Java程序设计》第七周学习总结
1. 本周学习总结 1.1 思维导图:Java图形界面总结 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 事件源,事件处理方法,事件监听器 事件源(Event ...
- 为docker配置HTTP代理服务器
背景: node1不能访问外网, node2可以访问外网,node1通过node2的代理服务来访问外网. 1. node1不能访问外网 vim /etc/resolv.conf 注释掉DNS配置文件 ...