作者:京东物流 赵勇萍

之后的日子里,我可能会陆陆续续写一写跟编程技术感悟相干的文章,一来能够梳理一下对技术和工作的思考,二来也能够记录一下技术成长的的过程。

换个叫法的话,就叫做程序员日记吧。

电饼铛

明天就从电饼铛说起。

上周,我家的电饼铛坏了,起因可能是荡涤过后线路短路导致的。那个老式电饼铛的确用了好些年,且性能繁多,基本上除了开要害,再也没有什么能够按钮的中央了,不过老妈却始终用的很棘手。

而对我来说,这的确个好消息,终于能够换一个好电饼铛了。于是在网上买了一个七百多的苏泊尔的电饼铛,这一下子感觉高大上了许多,很多内置模式,能够反对煎蛋,煎饼,炸鸡翅等多种模式,对温控的把握也非常精准。

不过,对于我老妈来说,她并没有显得多兴奋,我将应用阐明一一教给她用,但老妈最终只抉择一种用法:关上开关,抉择自定义模式,所有都靠教训去判断电饼铛的温度和对食材的感觉,其余所有的内置模式,对她老人家来说,如同的确是多余的。

对此,我有点陷入深思,总感觉有一种似曾相识的感觉。 认真思考,其实这种状况在编程过程中不足为奇。其实这不就是咱们微服务架构中常常会遇到的一种状况么....

好的,接下来,如果把我和我老妈的上述行为形象为代码,能够写成如下:

老妈做煎蛋:

/** *老妈做煎鸡蛋 */public class MainApplicaiton{    /**     *电饼铛     */    @Resource    private DianBingCheng dianBingCheng;    /**     *老妈的判断服务类     */    @Resource    private MotherCheckService matherCheckService;    /**     * 老妈的行为服务      */    private MotherBehaviorService MotherBehaviorService;    public void execute() {        //关上电饼铛        MotherBehaviorService.Open(dianBingCheng);        //查看温度        matherCheckService.CheckTemperature(dianBingChengAggregate);        //开始煎鸡蛋        MotherBehaviorService.fryEggs();        //查看是否熟了        matherCheckService.CheckRipe();        //实现,关机盛盘        matherService.complete();    }}

我做煎蛋:

public class MainApplicaiton {    /**     * 电饼铛聚合根     */     @Resource     private DianBingChengAggregateRoot dianBingChengAggregate;     public void execute() {        //开机        dianBingChengAggregate.open();        //煎蛋模式        dianBingChengAggregate.fryEggs();        //实现,关机盛盘        dianBingChengAggregate.complete();     }}

大家能够看出这两者的实现区别,咱们有时候须要思考一下,我不就是解决一个日常特地简略的事件,肯定要引入那么多的服务类么?

贫血模型和充血模型

可能大家感觉进去了,这两种实现,就是畛域驱动设计中典型的贫血模式和充血模式。这里不得不先说一下贫血模型和充血模型。

贫血模型是事务脚本模式。对于程序员来说,脚本呢必定是要比写设计说明书要快的多了。比方,咱们要设计一个订单流程,包含下单,勾销,售后,拆单等状况下的订单流转,那么咱们就就会任选一个Service类,写一个办法就能搞定,而这时,原来的那个order类中,就会十分十分的“清新”,外面全是GET办法和Set办法,没有任何行为。而很多人喜爱给这个order类一个定义,叫OrderDomain,订单畛域模型。当然我更喜爱叫这种模型为DB模型,是面向数据库的,而不是面向畛域业务的。

而充血模型是才是典型的畛域模型模式。他实现起来绝对简单,但这种简单也是绝对的,还是下面的例子,咱们会在Order这个对象中放入响应的动作行为的办法,例如咱们更新订单状态不会用setStatus()这种办法,而会封装相似orderCancel(),orderComplete()的这种业务行为办法,当然这种形式会让这个类略显“简单”。

总结一句话,真正的畛域模型会把数据和行为聚合在一起,造成聚合根,对外提供基于行为的办法,而非脚本化的增删改查。只有这样才可能更好的对微服务进行拆分。

如果仅是贫血模型其实不是对系统架构危害最大的,想咱们曾经很相熟的MVC,通过贫血模型也能够写出简单的高效快捷的零碎。

然而,有一种危害就会很大了:

就像好多同学用这面向对象的语言,写着面向过程的代码一样,很多同学喜爱用冠以畛域驱动设计的噱头,却写着MVC式的“面向数据库编程”, 它最大的问题是你引入了畛域模型设计的所有老本,但却没有带来任何一丝的收益

只有当你充沛应用了面向对象设计来组织简单业务逻辑之后,能力对消这种老本。如果将所有行为都写入一个一个的Service类,畛域是被割裂的,那最终你会失去一组事务处理脚本,从而错过了畛域模型带来的益处,而且当业务足够简单时,你将会失去一堆爆炸的事务处理脚本。

此外,你还会发现,

原本属于一个畛域的能力,却被散落在了工程的各个角落。这样一来,根本无法造成一个可复用的能力。

当然有同学也会提出疑难:“_我的业务场景中畛域之间其实关系比拟严密,我会常常遇到会触发同时跟不同畛域行为相干的业务,在这种状况下,我就通过一个个的Service扩大,这就是一种不言而喻的解决方案呀~~_ ”

其实有这种想法的同学,次要是对畛域驱动设计了解不粗浅的,同时又对传统的MVC框架开发积重难返。

其实畛域驱动设计早已给出它的最佳实际,那就是畛域事件。而面向事件的编程思维对于后端来说,是一种十分高效和优良的思维。通过畛域事件,咱们能够实现畛域之间的解耦,同时也保护了畛域模型的独立性和数据一致性。而对于畛域事件又是一个很大的话题,当前有机会再聊。

思考

在咱们每个人的大脑里,对于一件事,如果没有概念和了解的话,咱们会无意识的规避那件事,或者用本人相熟的概念去套用。微服务,DDD,中台这些词汇,恰好是这样的概念。这是有了这些概念,才让咱们一直的致力去学习它,思考他,钻研他。

在微服务和DDD这波浪潮里,很多同学都想用这些概念来包装本人,就像我面试过的很多候选者,他们中的很多都在简历中写了精通畛域驱动设计,同时也能说出一些聚合根,实体,值对象等概念,然而理论落地就变成了贫血模式的代码。

所以,对于程序员来说,最外围的能力并不是你会几种语言,会几个架构或者几个名词概念,而是了解那些概念并转化成本人的编程思维。

同时,

勇于创新和敢于颠覆本人的已有认知,也是一名程序员是否有始终后退的能源的前提