专栏首页DDD耦合必然性

耦合必然性

最近学到一个词“耦合创伤应激障碍”,讲的是程序员对耦合条件反射式恐惧,对于这个新词,我再重新理解一篇

对于一名程序员,从入行开始,就听到前辈们对“高内聚低耦合”的谆谆教诲,所以对于低耦合的意识深入骨髓。知行合一,看看是怎么践行的,打开任何一个项目工程,可以看到,每一个service都有一个interface和impl,代码看起来整整齐齐,所有变化点都考虑到了,但其实没有降低问题复杂度,只是自己看着舒服

在《SOLID总结》[1]中提到过面向接口编程中接口到底是什么含义,并不是所有实现类都得需要一个接口,才是面向接口编程

而现在实践中对实现依赖心理恐惧,成了一种行业通病,见不得对实现的依赖,这是典型的耦合创伤应激障碍,像“猴子实验”

五只猴子被关进笼子里,笼子一角挂着一串香蕉,如果有猴子试图摘取香蕉,就会被开水泼到。猴子们吃了几次苦头之后,就再也不想摘香蕉了。此时用一只新猴子替换老猴子,新猴子看到有香蕉刚想去摘,就被老猴子们拉住一顿暴打。新猴子挨了几次打之后,也不再去摘香蕉了。此时再换进一只新猴子,它也看到香蕉想去摘,也被老猴子们一顿暴打,下手最狠的恰恰是那一只没被开水烫到过的。最后老猴子们都被换干净了,仍然没有猴子去碰那串香蕉,因为它们知道——碰香蕉意味着被打,而为什么会被打,没有猴子知道。

当参与一个新项目,不再创建interface时,肯定会变成那只被打的“猴子”

然而现实并不是这样的,真的加个interface就减少耦合了吗?耦合少得了吗?比如,需要使用支付宝或微信支付,那么这就是业务需求,与支付宝和微信就必然会耦合,才能达到业务要求。不管怎么组织代码结构,是明显直接调用,还是隐晦地抛出支付事件,终将需要调用支付宝微信的支付接口;再比如现在很多应用需要推送消息,短信、邮件亦或微信,那么与支付类似,不管如何,必将调用第三方接口才能实现这些功能,这也就是耦合的必然性

代码大致是这样的:

先来一个接口:

package com.zhuxingsheng.infrastructure.port

public interface AlipayService {

    public PayResult pay(AliInfo aliInfo,decimal payAmount);
}

再来对接口的具体实现,调用支付宝SDK

package com.zhuxingsheng.infrastructure.apapter
public class AlipayServiceImpl implements AlipayService {

    public PayResult pay(AliInfo aliInfo,decimal payAmount) {
        AlipaySdk.pay();
        return result;
    }
}

微信支付代码结构类似,对于这些代码味道是不是相当熟悉,有service必有interface和impl,但看看接口的意义在哪儿?

机智的你,肯定发现这样不对,我们需要的应该是在线支付能力,而支付宝支付或微信支付只是具体的实现而已,也就是与支付宝和微信耦合其实不是必然的,必然的是在线支付能力

这儿其实有两种演变过程:

第一种:先实现了支付宝支付功能,当再实现微信支付时,此时发现要抽象出在线支付接口,策略模式

第二种:从业务需求用户故事:作为用户需要完成订单线上支付,完成订单的全流程

第一种从技术入手,而第二种从最原始的业务入手,这两种演变虽然第二种方是大道,可技术人却喜欢第一种,这也就回到篇首所说,代码看起来整整齐齐,却没有简化问题,甚至只因为技术风格的强统一,带来了业务语义的更加隐晦

技术其实是解决业务的工具,需要从业务本源着手,挖掘业务背后隐藏的业务能力,构建出对应的技术模型,达到模型即代码的统一,也就知道了必然性耦合,怎么降低耦合

所以再看上面的接口,package com.zhuxingsheng.infrastructure.port,是在基础设施层,只是技术上单纯的一个接口,在《DDD》[2]专栏中,提到过的接口在领域层,实现在基础设施层,因为maven模块循环依赖或者DIP的需要,所以必须要把接口放在领域层,从业务角度分析,线上支付能力是构建模型的必要能力,是领域模型必不可少的部分,需要在线支付能力,也是业务必然性耦合的体现,应该在领域层

可从代码形式上看,你是不是觉得不管是对业务的深刻理解,还是单纯技术抽象,不都是一个接口吗?无非是叫接口还是叫业务能力而已吗?

再看一个接口

package com.zhuxingsheng.infrastructure.port

public interface UserService {

    public User getUser(long userId);
}

从命名就知道,获取用户信息,不管是业务系统自身处理用户信息,还是从用户中心式外部服务获取用户信息,这是整个系统的基本能力,而不会再需要去抽象一个深奥的业务能力,当业务需求故事阐述用户下订单业务行为时,业务方已然抽象了整个用户体系,只有研究用户上下文子域问题时,才去深入用户领域模型,但从当前业务上下文看,业务系统与这些基础服务是深度绑定,并在系统架构初始已经确定了整体架构

因此在业务系统中去定义一个userservice接口,是没啥意义的,除非系统大动,否则是不会变动的

延伸一下,此时领域层如何依赖基础设施层呢?怎么DIP呢?有没有丝毫感受到分层有问题呢。对此下回分解

总结一下,我们需要正确看待耦合必然性,不是从技术实现的角度去硬生抽象,而需要从业务角度,挖掘出业务真正耦合的能力,坦然接受这样的耦合,清晰化表达业务语义

References

[1] 《SOLID总结》: http://www.zhuxingsheng.com/blog/solid-summary.html [2] 《DDD》: http://www.zhuxingsheng.com/tags/DDD/

本文分享自微信公众号 - 码农戏码(coder-game),作者:朱先生

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-08-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Customer Report这个Fiori应用必须和CRM耦合在一起么

    CRM Is needed for “customer reports” application.

    Jerry Wang
  • 耦合非线性振荡器的拓扑同步(NS ASS)

    耦合振荡器的同步是自然界普遍存在的现象。 它的鲁棒实现对于我们理解各种非线性系统至关重要,从生物功能到电气工程。 另一方面,在凝聚态物理中,拓扑被用来实现拓扑边...

    栾博舒
  • 云计算与ERP结合未来已成必然趋势

      云计算的概念是在原有技术概念的基础上经过修饰发展而来的,是当前技术模式更为形象的代名词,它作为一种新的计算形态,直接对应的是传统的桌面计算。传统的桌面计算通...

    明象ERP
  • 语义耦合(Semantic Coupling)

    发布于 2018-02-05 10:38 更新于 2018-06...

    walterlv
  • 线性混合模型系列三:似然函数

    这部分主要是介绍如何写出似然函数,通过正态分布,线性回归为例子,并通过R语言编程实现。希望大家可以有所收获。

    邓飞
  • 变化驱动:正交设计

    一个出发点 当谈起软件设计的目的时,能够获得所有人认同的答案只有一个:功能实现。 因为这是一个软件存在的根本原因。 而在计算机软件发展的初期,这一点也正是所有...

    张逸
  • 变化驱动:正交设计|洞见

    本文首发于InfoQ: http://www.infoq.com/cn/articles/change-driven-orthogonal-design 一个...

    ThoughtWorks
  • 软件设计原则之内聚、耦合类型剖析与内聚度、耦合度比较

    高内聚、低耦合是我们在软件设计过程中必须遵循的一个重要原则,在整个软件工程中占有很大的比重。而对于内聚和耦合你还是仅仅局限于“高内聚,低耦合”的模糊概念吗?那你...

    白鹿第一帅
  • 运河交汇处浅水方程耦合条件下的角度依赖性(CS)

    在本文中,我们在一维浅水渠网络的交界处提出了一种数值黎曼问题求解器。连接条件考虑了通道相交的角度,并包括了具有不同截面的运河的可能性。该解算器通过数个数值试验进...

    Alfred_Yip
  • MECP简介(5)——Theory - What can we do beyond MECP?

    以环丁二烯的异构化为例,按照前线轨道理论,这一反应也是对称性禁阻的,原因是反应前后的HOMO对称性并不相同。

    用户7592569
  • 快速学习-IoC 的概念和作用

    耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是...

    cwl_java
  • 高类聚、低耦合真的就好么?

    最近在看《翻转式学习》,作者在里面吐槽了说真正的教育根本就不应该分学科和科目。(我感觉这个想法太高深了,没敢往下想)

    老钱
  • 应对变化

    这些原则是前辈们经过无数实践提炼出来的,百炼成刚,那是不是成了放之四海皆准的道理呢?某种程度上讲,还真就是准的,常被人耳提面命写的代码要遵守这些原则,想想cod...

    码农戏码
  • Transformer是巧合还是必然?搜索推荐领域的新潮流

    BERT等Transformer模型在自然语言处理领域大放异彩之后,将Transformer应用在各个领域变成了一种潮流,包括之前文章中介绍的 Image ...

    炼丹笔记
  • 悬臂式光栅耦合器(suspended grating coupler)

    这篇笔记介绍一篇OFC2019的研究进展“Efficient Optical I/O in Standard SiPh Process”。美国贝尔实验室通过一种...

    光学小豆芽
  • 之于5G——浅谈SDN和NFV

    在我刚开始了解5G核心网架构的时候,我注意到软件定义网络(SDN)和网络功能虚拟化(NFV)作为两种新兴技术被多次提及。然而,对于SDN和NFV技术在5G中扮演...

    SDNLAB
  • Python-面向对象

    和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

    PayneWu
  • 如何避免微服务设计中的耦合问题

    译自:How to Avoid Coupling in Microservices Design

    charlieroro
  • 【SLAM】开源 | MULTICOL-SLAM适用于任意的,刚性耦合的多摄像机系统!

    论文地址: http://arxiv.org/pdf/1610.07336v1.pdf

    CNNer

扫码关注云+社区

领取腾讯云代金券