d78307b1d4 | ||
---|---|---|
.. | ||
config | ||
grpc | ||
logger | ||
.drone.yml | ||
.gitlab-ci.yml | ||
Dockerfile | ||
README.md | ||
auth.go | ||
go.mod | ||
go.sum | ||
mem_cache.go |
README.md
ddd 代码脚手架
基于Golang的DDD实践
一、项目代码结构生成
操作步骤:
1、从git拉取脚手架到本地:git clone https://mop-middleware-auth.git;
2、将脚手架拷贝到目标路径:cp -a mop-middleware-auth 目标路径;
3、将目标路径改为服务名称(例如:mop-license-mamanger);
4、使用代码编辑工具,查找并替换,将代码或者文件中所有的mop-middleware-auth批量替换为服务名称(mop-license-mamanger);
5、并在目标路径下(例如:mop-license-mamanger)开发业务代码;
二、一些概念
DDD经典分层:
分层架构的一个重要原则是:每层只能与位于其下方的层发生耦合。严格分层架构,某层只能与直接位于其下方的层发生耦合;松散分层架构,则允许任意上方层与任意下方层发生耦合。大原则如此,我一般都是采用松散分层,严格的太夸张,在团队里推广起来挺难的。
CQRS:
命令查询职责分离,是由Betrand Meyer(Eiffel语言之父,OCP提出者)提出来的。命令(Command):不返回任何结果(void),但会改变对象的状态。查询(Query):返回结果,但是不会改变对象的状态,对系统没有副作用。
ES事件溯源:
在CQRS中,每一个确定的命令操作,不论成功还是失败,只要执行之后就产生相应的事件(Event)。这样只需要把所有系统运行的Event,以及其产生时的数据记录起来,这就是系统的历史记录了,并且能够方便的回滚到某一历史状态。Event Sourcing就是用来进行存储和管理事件的。
粗略的知道了这几个概念之后,基本上就可以用来理解和构建最基础的领域驱动架构了。
三、一般实践
总体分层结构如下:
1.presentation 表现层。Web框架选择了gin,gin是基于MVC的。我将V和C层都放在了表现层。路由设置这些统在一起都算是表现层的。领域驱动设计,更多关注的是业务,以及其变更时能够比较好的扩展与维护。表现层逻辑也很简单,主要是承接gin框架转发过来的请求。
2.application应用层。DDD里应用层是很薄的一层,只作为计算机领域到业务领域的过渡层。比如计算机能够识别和传输的肯定是2进制字节流,这一层可以充当翻译,把这些晦涩难懂的机器“语言”,转化为领域业务人员建模出来的语言。或者说是高级计算机编程语言,这里一般会有专门的ViewMode来承接所需的参数数据。这一层直接消费领域层,并且开始记录一些系统型功能,比如日志、事件溯源。
3. domain领域层。领域驱动设计里最核心的部分了,可以细拆分为聚合根、实体,领域服务等一大堆其他概念。这里不展开详细说明了,简单的理解下聚合根,负责整个聚合业务的所有功能就行了。
4. infrastructure基础架构层。这一层一般主要将所有公共功能抽象整理出来,作为独立的对外输出一些帮助类等。这一层也是讲求和业务逻辑无关,只重点提供通用的功能。
四、一些支持
领域驱动很友好的适配了业务,本身建模时就根据业务规则、界限做了很好的细化,区分。很容易顺延以下,就能够用于微服务的构建。 支持RPC方式启动,作为服务间的通讯。 各种服务支持,其实都是表现层以不同的方式对外表现而已,从应用层起必须是一样的。这也正是DDD的精髓所在。
五、一点感悟
对DDD的理解和应用其实还很不成熟,只是对过去的一点总结。
确实很Go的面向对象设计,没有继承,而是采用组合的方式来实现OO里的“继承”。尽可能的使用组合而不是继承,也算是面向对象设计的一个原则,Golang天然就直接遵循了。“封装”也很有意思,直接通过首字母是否大小写,“多态”还没怎么了解透彻就不可描述了。再使用Golang实现DDD的时候,也发现了如果有“泛型”就好了的感概。这个时候更能深刻的理解和体会,泛型的好处。不得不佩服下C#的设计者,很早就有了泛型。
简单的构造出来了一个DDD的实现,不成熟的地方还有很多,但是迭代是个好东西,慢慢的理解和完善。