文章
问答
冒泡
Golang领域驱动实战:序章

之前写过一篇python的领域驱动相关开发的文章,收到同事的称赞,但有些人说我是翻译抄袭的,顺便冷嘲热讽一下。刚好最近公司一些新项目都在往go里面迁移。但收到之前python/PHP影响颇深,思维固化。依然按照原先脚本语言的方式继续往上糊。但是又不知道怎么写好。刚好我负责了一个新的项目。实践一遍DDD。所以写几篇文章分享出来。

我们做错了什么?

但凡讲DDD的时候,我们会被很多概念吓唬住,比如什么实体值对象CQRS 等等,听起来十分高端,十分上档次。但从来没有人说我们为什么这样做。为什么要弄出这么多概念来?存粹为了装逼吗?要搞懂为什么要理解以上概念,我认为更多应该理解我们错在什么地方了,或者我们遇到什么问题了才能从解决问题的角度去理解他并且驾驭它。不会人云亦云。被人牵着鼻子走。

演化

首先我们看下传统的MVC,这是我们最熟悉的方式了。

传统的MVC中,View 层代表渲染层一般意义上我们负责构建和渲染HTML,Control控制层负责处理请求和拉取数据并把数据给View层渲染,Model层负责定义我们流转在系统中的各种数据。这么看貌似没什么问题。一般情况下我们一直也是这么做的。但是随着时代的发展,前后端开始分离。也就是说,View层从此不由我们后端负责了。View层交给了我们的前端去做了。于是就形成了这样的结构

后端不再处理如何渲染了,后端实际上只有了,Control和Model,专注于业务逻辑。但现在有问题吗?确实没什么问题。但是对于简单的项目来说,确实够用了。毕竟我们就是从数据库里查查数据,改改数据,然后组织成json之类数据格式返回给前端。类似这样

但往往我们的业务并没有那么简单,自从分离后,Control太重了。我们这里经常会做很多事请,除了查询数据库,我们还有验证表单,参数,验证业务逻辑,等等,混乱开始在Control滋生。怎么办?所谓没有什么事情是加一层不能解决的,如果有那就再加一层于是,我们把Control拆分成Action/Service层

Action层主要负责验证入参及输出,Service负责封装业务逻辑,解决一部分Control膨胀的问题。但问题解决了吗?其实并没有,随着业务发展,service也会越来越膨胀复杂。Service不仅仅控制了数据库的查询,事务,修改,还有整合了各种外部服务,比如RPC,其他业务的Restful API,各类云服务,缓存,消息队列,日志记录,ES搜索引擎等

没错,Service开始膨胀,开始不堪重负,他处理了太多细节,复杂度开始失控。随着越来越多的人加入,因为Service包含了部分查询,你团队的有些人开始为了快速开发,Service开始调Service,互相依赖Service]

3uwZSs.png

没错,你的项目慢慢开始出现循环引用,但你没有什么好的办法解决,为了拆掉循环引用,你把部分相同的查询和其他业务基础设施重复实现。一旦发生需求变动,开始形成了多米乐骨牌效应。此时项目质量开是下降,牵一发动全身。每一次需求变动就会导致各种连锁反应。项目经理开始骂街,产品经理开始抱怨。你开始想通过单元测试来勉强维护项目质量。但其实你根本推行不下去。因为你的发现,单元测试要把这些该死的外部服务全部mock掉,但你根本mock不掉。

查看源图像

怎么办

知道问题就可以着手解决问题,其实解决此方法的问题,其实很简单,我们只需要遵守两个原则

  1. 单一职责
  2. 依赖倒置

听起来很简单,但是怎么实践是个困难的问题。此时我们就需要使用DDD的规范和理论指导去构建我们的应用程序。DDD的概念非常广,我们这里只讨论代码技术层面的问题。不去讨论战略战术的问题。我将会使用buffalo 来做例子

为啥用Buffalo?Gin不香吗?Gorm不香吗?

在Go语言中,框架不像其他语言那样无所不阔,大多数是对net/http包进行封装。在后续的文章中,你会发现,我们所要解决的问题也跟框架无关,用Buffalo的原因是因为我懒。代码我将会在github上供参考。

连接


关于作者

雷米Remy
获得点赞
文章被阅读