编 辑:老彭
来 源:大数据架构师
彭友们好,我是老彭。最近看了一本好书,人称“Bob大叔”的Robert C.Martin写的《整洁架构之道》。一直在数据和架构领域追寻大佬的老彭那读的是津津有味啊~~~
我在带团队的时候经常跟同事们说的一句话就是:只要你在写代码,无论用的是什么语言,做的是什么业务,一定要锻炼自己从架构师的视角思考问题。这也是老彭为啥给公众号取名“大数据架构师”的原因之一。
是否拥有架构师的视角,决定了你是否能编程水平的瓶颈。
好,话不多说,开唠今天的嗑。
01 少林无上内功心法易筋经:高内聚、低耦合老彭还在本科学习的时候就听说过“高内聚,低耦合”(High Cohesion and Low Coupling)。当时只是单纯的觉得不明觉厉,根本没明白这句话的威力有多大。
再次听到这句话是在考高项的时候,那是老彭已经是一个3、4年经验的SQL Boy了。之前基本上都沉浸在存储过程、提数sql、报表开发等繁重的工作中,全凭本能在写代码,犹如刚上少林寺天天挑水打杂的小和尚,每一个任务就像是一次新的挑水任务,基本上都得重来。
老彭愚钝,一个复杂的报表经常能突破上千行代码,一直觉得这样不对,但又不知道该怎么办。
再次听老师讲解“高内聚、低耦合”其中的奥秘,老彭觉得这简直就是上天来帮助我从繁重的体力劳动中解脱的“易筋经”,一语道破为何那时老彭的代码又臭又长的原因。
所谓内聚性,就是一个软件单位内部的关联紧密程度。
所谓耦合性,则是强调两个或多个软件单位之间的关联紧密程度。
我们要尽可能让一个软件单位内的关联更紧密,或者说把关联紧密的功能放在一个软件单位内实现,这样能避免多余的重复和交互。
同时我们还要尽量让两个或者多个软件单位之间的关联紧密程度不要那么高,减少相互依赖,这样能最大化减少一个软件单位对另一个软件单位的影响,把错误或者运维工作控制在有限范围内。
转头老彭就回去开始重构代码,把各种sql、报表中共性的部分都提炼出来,构造函数,建设基础报表,甚至回过头到数仓的整合层和汇总层重构ETL程序,优化各层的数据模型。
将数仓各层、函数、共性报表进行充分解耦,在每层、每个函数、每个共性报表中把它们需要解决的问题尽量独立完成,使之尽量内聚,之间通过定义数据标准进行交互。
这样一下如同拨开云雾见天明,开发和运维的工作量顿时瞬间降低了一个数量级别。
如果业务系统某张表的字段名字或者长度发生变化,老彭只需要在数仓的第二层进行调整就行了,由于每层做了充分解耦,后面用的字段已经统一为成标准字段、新的数据模型,所以后续代码根本无需做任何调整。
即便是有新表、新字段,由于代码已经层层抽象,数据逐层落地,因此只需要在需要调整的地方略微修改即可。
当老彭花费了不少时间调整之后,终于能按时下班了。这是老彭第一次尝到“架构思维”的甜头。
也需有人会说老彭真笨,学校都教过了,照做就行呗,还需要花这么多时间先错后改,浪费时间。但是老彭觉得,这也需就是“纸上得来终觉浅,绝知此事要躬行”吧。
从文字上来说,就短短的6个字,其中的奥妙还需自己慢慢体会。
02 无上神功太玄经:SOLID原则如果说“高内聚、低耦合” 太过于基础,那么就得请出如同金庸小说里最强的无上神功太玄经一般存在的SOLID原则:
这里不得不吐槽一下老外奇葩的取名方法,逻辑居然是首字母凑单词
Bob大叔在《整洁架构之道》里就披露了SOLID原则的由来:
“20世纪80年代后期,我在 USENET (古早版 Facebook )上和其他人就软件设计原则辩论时,便开始归纳这些原则。多年来,这些原则发生了一些变化。有些被删除,有些被合并,还新增了一些。
2000年代初,这组原则的最终版确定,只是和我的顺序有所不同。
2004年前后, Michael Feathers 给我发了封电子邮件,说如果重新排列这些原则,它们的首字母可以拼成单词 SOLID -﹣于是称为 SOLID 原则。”
SOLID够奇葩了吧?更奇葩的是每个原则的名字...
网上有很多SOLID原则的解释,这里老彭就不赘述了,只讲讲自己的一些体会。
①单一职责原则(SRP)定义为:一个模块应该对且仅对一类行为主体负责。
Bob大叔在书里也吐槽说这个名字取得不好,导致很多人误解了。其实老彭觉得叫做“需求隔离原则”,或者“用户隔离原则”可能会更好。
因为这个原则其实大有来头,是根据“康威定律”推导出来的。
康威定律:软件的最佳系统架构很大程度上取决于开发它的组织架构。也就是说,企业组织架构决定了系统架构。
从这个视角上看,单一职责原则是从需求端视角(用户、用户群等某类行为主体)进行隔离,不能将多个用户、用户群的需要放在同一个模块里,这样会导致某个用户的需求发生变化,会导致该模块的调整,进而影响其他用户的需求。
书里给了一个反例,彭友们一看就明白:
Employee类里的三个方法分别服务三个对象。一旦三个CXO中的任意一个人需求有变更,都会导致Employee类要修改,从而影响另外俩CXO的正常需要。
②开闭原则(OCP)定义为:对扩展开放,对修改封闭。
是不是同样有些拗口?其实很简单,老彭带你从面对需求变更的视角就瞬间明白了。
这个原则是为了面对需求变更而存在的。当面临需求变更时,我们尽量减少对现有程序的修改,用新增代码完成变更的需求。减少改代码,就能减少不必要的bug。
怎么实现呢?书里举了一个生成财务报表的例子:
注:>代表接口,
其设计思想是将报表生成拆分为报表数据计算和报表展示两个独立的职责,再加上必要的控制模块和数据库模块,之间都用接口进行隔离,这样就能确保相互不会受到影响。
总体上既能保证非常强的扩展性,又能很好地隔离了各个功能之间的相互影响。在本例中,interactor把核心业务处理好了,其他细枝末节交的任务给另外3个模型实现,最符合OCP原则。
这里有两个设计技巧:依赖方向的控制和信息隐藏。接口就是完成依赖方向控制的重要手段之一。接口和data mapper也是信息隐藏重要手段。
在这里个例子,一旦数据库发生变化,只需要改一下data mapper或者接口就行,interactor内部完全不受任何影响。
为了让大家更容易理解,老彭给这个原则取个外号,叫“坚决不改代码原则”,或者叫“只增不改原则”。
③里氏替换原则(LSP)定义为组件必须遵循可以相互替换的约定。是不是看不明白?
其实也非常简单,这是从设计子对象的视角上进行设计的原则。
书里给的例子也很清晰,Personal License 和Business License继承Licenes,并且在Billing调用的时候,可以直接替换Licenes,而不会出现不适当的问题。
书里同时给了一个反例,就是矩形和正方形。正方形虽然是矩形的一种,但是他们是有区别的。矩形的两个参数长宽都可以随便变,但是正方形虽然也能继承“长宽”,但是这俩必须得同时变才行。因此正方形不能成为矩形的子类型。
老彭觉得还是叫“龙生龙原则”比较符合拗口的历史替换原则比较合适。毕竟龙生龙凤生凤,老鼠的儿子会打洞。
④接口隔离原则(ISP)定义为恰当地使用接口,避免不必要的依赖。
这个就很好理解了。书里也给出了生动的例子:
当user1调用OPS类里的op1时,会强行依赖op2和op3,但是很明显,op2和op3分属user2和user3,跟user1完全没啥关系。这样就造成了不必要的依赖。
解决办法是给每个op(操作)都做一个独立的接口,把操作隔离到接口中,这样就实现了解耦。
这个原则的名字还是挺贴切的,老彭还是给它取个外号吧,就叫“人人有份,大家别抢原则”
⑤依赖反转原则(DIP)定义为源代码应该多依赖抽象类型而不是具体实现。
名字同样的拗口,定义同样的不知所云。
其实换个说法就好多了:这是从引用、继承的视角进行设计的原则。为了保证代码不必改来改去(更稳定),我们需要做到以下几点:
1.不要引用易变的具体实现类;
2.不要衍生、继承易变的具体实现类;
3.不要覆盖类中具体实现函数;
4.永远不要直接引用任何具体实现和易变类的名字。
Bob大叔建议利用抽象工厂模式设计和管理依赖。如上图所示,中间的曲线是架构边界,上面是抽象接口,下面是具体实现。
因为跨越曲线的箭头方向和实际源代码依赖的方向相反,所以该原则叫“依赖反转原则”。这取名字的水平也是没谁了。
吐槽一下,这真的不是翻译的问题,就tmd是原作者的问题。
老规矩,老彭给取个外号,叫“身份证原则”,大家对外沟通的时候,都取一个不会改的身份证号就完了。至于你的真名、网名、笔名啥的,随便取,随便改。把一个独立的个体,抽象成一个身份证号,完美解决。
03 小结Bob大叔真的是我偶像!软件领域的巨头之一。架构造诣超神,但是取名字的水平实在是令老彭无力吐槽
以上插图、案例就来自于此书,强烈建议各位购买这本书过来瞅瞅,必有收获。
以上就是关于【高阶架构师必看】架构设计的两种无上心法-易筋经和太玄经姐姐的儿子叫什么全部的内容,关注我们,带您了解更多相关内容。
特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。