编辑导语:聊起系统架构时,架构师们总是喜欢提及“高内聚”和“低耦合”,这在系统设计中是十分重要的概念,也是产品经理需要进行学习和思考以推动业务更好开展的必备技能点。作者用生动的故事作为案例,分享了他对于高内聚和低耦合的理解,一起来看。

在和架构师们讨论系统设计时,总是能处处听到“高内聚”和“低耦合”的声音,仿佛这就是技术和产品之间的一道墙,初级和高级之间的一条沟。但如果了解了它们的原理,也就不那么神奇了,要知道,这两个词并不是研发专用。作为产品经理,我们对这两个词的理解甚至可以比架构师们更宽广,拽起概念来可以比他们更酷。

本文木笔用一个故事开始,再用一个故事结束,和你聊聊我眼里的高内聚和低耦合,往下看!

聊起系统架构时,架构师们总是喜欢把“高内聚”和“低耦合”挂在嘴边,一副拽拽不可一世的姿态,让不懂的人听的一愣一愣的,仿佛这就是技术和产品之间的一道墙,初级和高级之间的一条沟。那到底什么是高内聚和低耦合,对系统设计又有什么影响?其实,了解它们的原理以后,也就不过如此。

今天,木笔从一个美好的北漂故事说起,聊聊我自己对这两个词儿的理解,相信你看完本文以后,也能和这些架构师互拽一下了,而且,产品经理眼中的高内聚和低耦合不应该局限在系统设计本身,还应该向更源头的业务方向思考,从业务层面做内聚和解耦。

在和架构师互拽时,我就一个要求,要拽得酷一点,气势上一定不能输,即便脸被打肿,也要保持迷人的微笑和傲人的姿态,不要给咱产品经理丢脸。

一、从北京爱情故事说起

故事是这样开始的:

老陈、老张、老李三人是大学同学,大学毕业后相约一起到北京闯荡,由于初入社会工资比较低,为了省房租,3个人便一起合租,在一个房间里摆了两张上下铺,延续了大学宿舍的生活方式,每天下班后就一起喝酒、吹牛、打游戏,周末时间充裕就一起唱歌打球吃火锅,北漂虽然穷苦,但日子过的好不快活。

这样快意江湖的日子持续了三年,三条单身狗各自交了女朋友,偶尔某一位的女朋友过来,其它两位就要出去避一避风头,很不方便,于是三人一合计,租了一个大的三居室,每个人一间,这样既能解决女朋友过来小聚的问题,三人也能继续一起逍遥。随着住宿条件的提升,以及小情侣们感情的升温,为了克服相思之苦,也为了最大化节省国家资源,小情侣们想方设法克服重重阻碍同居到一起了,这样原本3个人的房子里住起了6个人。

自从3个人变成3家6口人以后,原本的快活日子开始慢慢起了微妙变化,起因在于房间的隔音效果不怎么好,而火爆脾气的老陈和女朋友总是吵架,而且经常闹到大半夜,严重影响了隔壁的老李和老张,时间一长,两家小媳妇儿就有意见了。加上三家也经常因为厨房和卫生间的使用发生冲突,小媳妇儿们之间的事情,处理起来再也不像以前3个大老爷们那么简单粗暴了,一旦处理不好,后果大家都懂……

半年以后,为了避免女友之间的矛盾进一步加大变得不可开交,老张、老李和老陈最终决定不再续租,三人各自带女友出去租单间了,周末有空才到一起聚会。这样一来,虽然老陈还是经常和女友吵架,依旧睡的晚,但三家合租时候遇到的所有的问题都就此化解了,没有了冲突,三位女友见面以后反倒比之前合租时更加亲切了……

故事讲完了,如果你也曾有过几位类似的室友和经历,那么你无疑是幸运的,因为那些恰同学少年一起合租的日子就像昙花,美妙而短暂,那些一起为梦想穷开心的日子终将成为人生旅途中最珍贵的一段回忆,而它也终将随时光一去不返。

不过本文的重点不是为缅怀青春,而是想从故事中提炼出我们需要的主干:高内聚和低耦合。我们从资源分配角度来分析为何最早3个人合租的时候关系很好,变3家合租以后,就会出现矛盾,而后来各自分开住以后,关系又变好了呢?先思考3秒钟….

二、什么是高内聚和低耦合

把故事暂放一边,我们先理解一下什么是内聚和耦合。

所谓内聚,指某一个事物内部各要素之间的紧密联系程度。如果相同的要素越集中,说明内聚越高,反之则越低。比如人身体里的五脏六腑,彼此之间从出生就相互协作,如果换成其他人的器官,就会出现排斥现象,这就是高内聚。

所谓耦合,指不同事物之间的依赖性。如果彼此的依赖性越强,说明耦合性越高,反之则越低。还拿人体举例,心脏负责供血,肺负责呼吸,肝脏负责代谢,彼此之间分工明确,各司其职,即便某一部位生病了,只需要针对性治疗,不影响其它部位,这就是低耦合。

了解完概念以后,我们再回来分析一下故事的结局:为何最早3个人合租的时候关系很好,变3家合租以后,就会出现矛盾,而后来各自分开住以后,关系又变好了呢?

答案揭晓:最初3个人合租时,省钱最重要,人少感情铁,事情简单,所以不会有大的矛盾。而变成3家以后就成了3个不同的家庭,每个家庭的计划和诉求不一样,省钱已经不是第一诉求了,同在一个屋檐下,老陈和女朋友的家事免不了会影响到老张和老李两家,加上大家平时共用厨房、卫生间等公共资源,只要一家在使用,其它两家就会受到影响,而老陈、老张、老李的女朋友之间并不像他们三人之前一样生活单一且有着深厚的感情基础,久而久之,自然就出现矛盾了。

最后随着三家分开以后,自己过自己的生活,再也不会影响到其它两家,矛盾自然就没有了,随着偶尔的联络聚会,还会增进彼此的感情。

▲老陈、老张和老王的合租

这就是高内聚和低耦合的原理。最初三人合租时,人少、有感情基础,省钱第一,不存在内聚和耦合问题;三家6人合租时,彼此之间依赖太多,任何一家的举动都会影响到其它两家,耦合性太高,所以容易出问题;分开以后,每家独自负责自己的生活,不再依赖别人,内聚性变高了,同时只有周末才会相互联络,耦合性降低了,所以关系更亲近了。

看看,是不是和我们的系统设计一样一样的?当系统很小时,为节约资源,大家在一起共用一套资源,这样效率最高,而随着系统和团队的复杂度逐渐提升,彼此之间的依赖越来越高,就会经常出现资源问题和发展瓶颈,到最后,为了解决耦合性高的问题,只能对系统和团队进行拆分,各司其职,最终演变成了标准的高内聚和低耦合模型。

三、如何实现高内聚和低耦合

从定义上,我们应该清楚了高内聚和低耦合其实说的是两件事,一件事对内(高内聚),一件事对外(低耦合)。站在产品的视角,高内聚和低耦合不应该只局限于系统设计层面,那样就显得比较狭隘了,正确的解读应该立为业务和系统两个层面。

▲高内聚与低耦合示例

1. 业务层面

无论是业务部门的责任分工、流程的规划和设计,还是作业现场的管理,都需要遵循高内聚和低耦合,我们应该尽量将相同的职能、流程和运营工作尽量集中式管理,而不同职能、流程和运营之间责任和边界清晰,沟通协作顺畅且不相互影响,具体体现为:

(1)各部门和岗位分工明确,各司其职。例如采购、仓储和配送,虽然交集很多,但在定人定岗时,就应该是不同的岗位角色,即便有的公司很小,可以一人身兼数职,但也要清楚,只是一个人做了多个岗位的事,而不是多个职能融合成了一个岗位。

(2)各项流程清晰,职责单一。在设计业务流程时,应该考虑单一职能原则,每套流程解决一个核心业务场景,虽然很多时候人和功能可以复用,但在流程和规则层面还是要分开设计,不要混在一起。例如销售出库和退供应商出库,虽然都是出库,系统功能和操作人都可以复用,但出库的对象不同,应该视为两种业务流程。

(3)现场管理规章明确,流向清晰。在仓储中心、物流中心的现场管理时,需要按照不同岗位、不同商品和不同业务形态规划库区、动线流向,制订规章制度,例如收发货区域管理、整件和散件区域管理、大件区和中小件区域管理等,让每个流程对应不同的规则,每个区域负责不同的存储形态,每个岗位操作不同的业务单据,彼此之间能无缝衔接却又不相互干扰。

2. 系统层面

在做系统设计时,需要保证相同的系统和功能模块尽量内聚,系统和功能模块之间尽量解耦,体现为:

  • 系统和模块职能单一,边界清晰。在规划系统时,应该做到每个系统,以及每个系统下的每个功能模块都有很清晰的职责,核心职责只有一个,并且和其它模块之间有比较清晰的边界,避免模棱两可。例如库存模块负责处理所有库存相关事宜,入库模块负责处理入库业务流程,二者的边界在入库上架时对库存的处理,由入库模块触发,库存模块做执行。
  • 数据和逻辑统一,唯一主责方。每个数据和逻辑的操作应该只有一个主责方,当其它模块需要操作此数据时,应该由此模块授权并通过接口服务的方式互通,如此可以最大化的保证数据和功能的完整和安全。例如入库和出库都需要操作库存,但库存的逻辑统一由库存模块来处理,出入库操作库存需要通过库存模块提供的接口来交互,千万不要把库存的处理直接交给入库和出库模块来各自处理。
  • 与尽量少的系统交互,降低系统之间的复杂性。参考软件设计原则里的迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers),尽量避免多个系统之间相互交互,形成了笛卡尔积和网状结构。比如上方有3个ERP,都需要要与下方的3个WMS系统做交互,这个时候就应该考虑通过一个中间的系统来对上承接3个ERP,对下对接3个WMS系统,不要让每个ERP分别与每个WMS形成笛卡尔积。

当然,高内聚和低耦合的设计虽然看起来更合理,但在实现时还是要因时制宜,因为高内聚和低耦合的实现一定会带来人力成本和系统实现成本的增加,就像北漂故事中一样,老陈老张和老李三家分开以后,确实实现了高内聚和低耦合,但每个人都需要自己租单间,还需要置配生活用品和厨房用具,总成本一定比合租时要高,比起最初三人合租一间房时就更高得多了。

在设计流程和系统时,我们应该根据实际情况来定夺,没必要照本宣科过度设计,在此,木笔提供几个思考建议:

  • 系统设计来源于业务,做系统的内聚和耦合之前,先从业务层面进行梳理,让业务先做好高内聚和低耦合,很多时候问题不是出在系统上,而是业务侧没有做好内聚和解耦。
  • 当业务发展初期,流程和系统相对简单且未来尚不清晰时,需要快速试错,可以不用太考虑内聚和耦合(适当兼顾就行),先以成本最低的方式支持业务,等业务慢慢清晰以后再继续调整也不迟,千万不要过度设计,用10万单的规模架构太承接1000单的业务,实打实的浪费。
  • 如果业务相对稳定,长期不变,适当耦合会更合理,比如商品的基本属性、订单的关键信息、地址库信息等,没必要为了低耦合,每次都做接口交互,这样比较浪费性能。
  • 当业务体量和团队规模都很小时,适合合租模式,一套系统中考虑按模块做高内聚和低耦合最合理;而当业务规模较大时,适合分开自住模式,分成多套系统,各系统内部高内聚,系统间低耦合更合理。

四、小Q的故事分享

最后,我们分享一个小Q的故事来加强对高内聚和低耦合的理解。

小Q最近有点烦,事情经过是这样的:

上个月自己刚入职了Z公司负责仓储系统的产品工作,刚入职就遇到前任产品经理离职,两人在交接的过程中才知道这套WMS系统是前不久才开发上线的,但因为系统问题较多,导致系统库存记录的严重不准,才1个月就产生了1000多万的账实差异,而且差异越来越大,已经严重影响了公司的销售,每天被销售部门、仓储部门和财务部门多方逼着解决,前任实在顶不住压力了,所以才提了离职,后来公司才招了小Q入职……原来如此。如果要评出职场上最坑的事,这种入职即背锅一定能排进前三。

小Q刚开始还没意识到问题的严重性,直到被仓储业务方在邮件里将盘点差异直接抄送CEO,并点名要求技术部门为库存差异负责并责令修复系统问题,限期1个月。为了不惹火上身,小Q当即提出离职,被领导好说歹说挽留下来,并为其增加了绩效奖金,因为目前最专业的人只有小Q了,只能死马当作活马医。重赏之下,两人商定以1个月为限,领导答应给小Q协调足够的资源来解决此问题。

小Q拉上研发经理和测试经理成立了专项组,先从业务的差异数据开始着手,从差异最大的业务开始排查,不多久便根据自己的经验发现了问题的根本:新的WMS系统研发团队都没有库存处理相关经验,在做库存处理设计时,都是在各个业务模块中自行处理,各自模块负责自己模块的库存加减,直接操作库存表,这样看起来各业务之间互不干预,似乎很解耦很合理。

但大家都忽略了一个现实:业务是并行的,在入库的时还可能在做出库、盘点等业务,虽然每个业务都是各自开展,但一旦针对某一个SKU同时操作多个业务时,库存的处理就会相互牵制,往往上一个业务还没处理完库存,下个业务又对库存操作了变更,这就产生了库存的操作错乱,所以产生了库存差异。看起来解耦的设计,实际上是各种业务和库存的处理高度耦合导致的问题。

▲Z公司的库存处理现状

这么严重的问题,测试时为什么没有发现呢?因为测试时样本太少,根本没有测到这种业务并发的情况。

找到问题根本以后,小Q稍微松了一口气,根据经验很快出具了一个库存解决方案:将库存的处理单独抽出来做成公共服务,整个系统只能基于此服务操作库存表,保证前一个业务加减完成后再执行下一个业务操作,并记录详细的库存变更流水日志。

对外则提供公共的库存的加减公共服务,这样各仓储业务环节只需要处理业务逻辑,在需要变更库存时再调用库存服务完成对库存的处理,不用再关注库存的底层逻辑了,如此才是真正的各业务内部高内聚(每个业务只关注处理自己的业务逻辑),业务和库存之间低耦合(通过唯一接口交互)。

▲小Q改造后的库存处理方案

方案出具以后,技术团队用1周时间完成了库存的重构,并按照差异大小排序,将各业务逐一往新的库存服务中迁移,虽然业务仍然在天天紧逼,但看着库存差异在一天天缩小,小Q知道自己的新方案凑效了,如此下去,不到1个月,库存问题就能得到彻底根治了…

案例也分享完了,以上就是我个人对高内聚和低耦合的一些见解了,最后想说的是,高内聚和低耦合的设计只是最终的实现形式,而它们更多的价值体现在我们梳理过程中的一种结构化思维方式,这是一种放诸四海都有用的方法。在做内聚时,我们要学会归纳、抽象,让相同的业务和功能尽量紧凑,在做耦合时,我们要学会将联系比较密切的流程、逻辑和功能拆分、剥离再重组和内聚,切忌藕断丝连。

我的文章分享完了,观点如上,够不够出去拽一下,就看你的了。

#专栏作者#

木笔,产品一俗生,深耕于供应链领域,微信公众号:供应链产品笔记

本文原创发布于人人都是产品经理。未经许可,禁止转载

题图来自Unsplash,基于CC0协议