10

你懂SOLID原则吗?

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MjM5MjY3OTgwMA%3D%3D&%3Bmid=2652471524&%3Bidx=1&%3Bsn=1868dce922be34e2d9c7728cd678d99f
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

虽然SOLID原则不能时刻有效指导编码落地,理解这些原则背后的设计理念,让你迈出了第一步,接下来,你需要做的是在前进的路上,不断地进行编码实践、思考总结,将其内化。

做了这么多年的面向对象编程还是写出违背SOLID原则的代码,一看都懂、一做就被怼,敏感度不够,如何是好?

  • 难道SOLID原则本身就有错?

  • 难道我不应该涉水OOD?

  • ……

请先屏住呼吸,我们来看看SOLID叫什么:

  • S ingle Responsibility Principle,单一职责原则

  • O pen Close Principle,开闭原则

  • L iskov Substitution Principle,里氏替换原则

  • I nterface Segregation Principle,接口隔离原则

  • D ependency Inversion Principle,依赖倒置原则

原则通常较为抽象,别说刚接触OO的程序员,有一定经验的人也不一定吃得透。要想提高对OO原则的敏感度,第一步,我们要清楚SOLID到底在讲什么?本文,袁Sir的SOLID创业故事将为你揭开一层面纱。

设计小而精美的工具箱,提高顾客体验

袁Sir创业初期经营了一家五金器具共享租用店,遇到两类顾客,A顾客需要剪刀、锤子、扳手、电锯,B顾客需要锤子、扳手、水果刀、梅花刀。袁Sir为了图省事,把这个六把工具同时装在一个工具箱里,每次都把装有6把工具的工具箱给A或B租用。

经过几次借还,袁Sir收到顾客的抱怨,为什么呢?因为袁Sir这么做增加了A和B的负担,首先多了两把工具,扛来抗去的累得多。其次,他们拿回去之后会发现:”咦,这两个是啥,我没要这个呀?莫非是增值服务?但我要用来做啥呢?” 结果A从未用过水果刀和梅花刀,但A还要保管好这两工具,增加了保管的成本。同理,B顾客也会面临同样的问题。为了提高顾客的体验,袁Sir把这两类顾客的工具单独用两个更小的工具箱装好,分别提供给A和B,并得到了两类顾客的一致好评。

袁Sir从一开始图一时的方便,塞给顾客他本不需要的东西,经过反思后,从顾客需求出发,只提供顾客想要的东西。 投其所好 ,是他创业悟出的第一个处世之道。

在软件设计中,ISP 提倡不要将一个大而全的接口扔给使用者,而是将每个使用者关注的接口进行隔离。

iE3yEf3.png!mobile

让客户坚信徒弟能代替师傅干活

袁Sir勤勤恳恳经营的五金租用店2年,挣了一大把辛苦钱,正好赶上房地产兴起的年头,家装市场跟着兴起,他果断买下一家知名的家具厂,并跟一家私人工匠所展开了合作。

SJ是工匠所的一名木匠学徒,从师3年有余,书架、衣柜、餐桌,门、窗这些家具已经能够到跟他的师傅如出一辙了。

袁Sir每次合作都是直接跟SJ的师傅对接,而在实际执行过程中,师傅有时候因体力跟不上,就交给SJ去做,好在每次生产出来的家具都能够让袁Sir满意。几次合作下来,袁Sir便相信:徒弟继承了师傅的手艺,师傅能做的这些家具,徒弟也一定能做得一模一样。

2017年,房地产彻底疯了,袁Sir一次性采购订单多出了以往2倍。为了如期交付,SJ的师弟小Y也参与进来。不幸的是,个性十足的小Y打造衣柜和门窗的方式跟师傅的风格差别很大,设计出来的家具让袁Sir一脸懵逼,始料不及的三丈大火烧尽后,袁Sir果断地中断了跟这家工匠会所的合作…

[LSP解读]  小Y将其师傅的手艺继承后,但自己又擅自修改了设计风格,结果打造的家具跟袁Sir的期望不一致,这就好比子类替换了父类,产生了不一致的行为,软件不能正常运行,这种继承设计存在潜在的问题。

在软件设计中,LSP 重点强调:对使用者来说,能够使用父类的地方,一定可以使用其子类,并且预期结果是一致的。

简而言之,子类不应该去修改父类已有的功能(在Java中,体现为子类重写了父类中非抽象的方法)。如果你的继承体系中出现了这种替换后不一致的现象,需要警惕你的继承是否合理了。

关于代码示例,请在文末参考阅读文章《让里氏替换原则为你效力》。

QFvMjiA.png!mobile

清晰良好的合作协议,让彼此更加信任

经过上一次不愉快的合作,袁Sir虽然少挣了一笔钱,还生了一肚子气。但台风来,猪想飞你也挡不住。在房地产彻底疯了的这几年里,袁Sir又捞了好几大桶金。有了钱能做什么呢?当然把公司做大,再挣更多的钱呀。

袁Sir秉着 ‘麻雀虽小,五脏不能不全’ 的原则,成立了财务部、法务部、行政部、人事部、市场部、销售部,由于期初业务量没有大到招架不住,各部门都是光杆司令,而且人事、行政、财务、法务四个部门由小蔡独管(袁Sir流露出了资本家的面貌)。

袁Sir要核对一个报销单,就直接找财务部的小蔡办了,要举办一场年会还得找小蔡,想了解上个月的销售业绩,他去找了销售部的老肖,当然找的最多的还是市场部老史。

经过大半年的快速发展,各部门从光杆司令变成了群狼作战。袁Sir仍然按照之前的方式办事,但遇到了烦恼 – 前天报销单还是小蔡在处理,昨天变成了小吴,今天又换成了小任。当然,其他部门也产生了相同的现象。苦思冥想,袁Sir出了一招:部门的负责人制定一个固定的服务列表,比如财务部小蔡提供服务列表:

  1. 核对报销单

  2. 处理报销

  3. 发工资

  4. 招聘新同事

  5. 评审绩效

  6. 举办年会

  7. 审核营业执照

袁Sir此时要处理报销、发工资,只用找小蔡沟通就好,至于具体谁去执行,袁Sir压根不需要知道。当然其他部门跟财务部合作也轻松了很多。此后袁Sir对所有部门都进行了整改。

此时袁Sir终于才体会到当老板的一丁点美好了。下班合上电脑前,他敲下了一句话: 部门之间得通过约定好的协议来合作,而不用关心对方内部由谁做协议所规定的事项

[DIP解读]  一开始,袁Sir直接找部门中某个具体执行的人去沟通工作,此时袁Sir依赖的是具体实现细节,每次执行的人发生变化会增加袁Sir的沟通成本。他让小蔡提供了一个服务清单,小蔡充当了一个抽象/接口,此后他只用找小蔡沟通即可,袁Sir从依赖具体实现细节转变到依赖抽象。

在软件设计中,DIP 提倡使用者依赖一个抽象的服务接口,而不是去依赖一个具体的服务执行者,从依赖具体实现转向到依赖抽象接口,倒置过来。

nE73yuv.png!mobile

各司其职,工作效率会大大提升

袁Sir起初让小蔡统管了人事、行政、财务、法务四个部门,业务扩张后也只是给小蔡多招了10来个人。小蔡大脑里就不得不绷紧四根弦,他要给部门各个同事合理分配任务,确保公司能够正常开展日常活动、人员考核培养、工资发放等工作,当然还有一些诸如工商督查、账务审核、信息安全审核等敏感的活动。

暂且不说小蔡有多累,关键是有一次捅了个篓子,差点没葬送公司前程。

一天,工商局来了几个人审核公司的营业资质,就在小蔡跟工商局负责人交涉的过程中,其他管理账目的两位同事因为一项没法对齐的数据起了点小争执,全然忘记还有工商局调查人员在,口角中抖了一些账目相关的敏感信息,好在小蔡反应快,及时进行了制止,当然也做了一些额外的安抚工作,把这事给糊弄过去。

这事传到袁Sir耳中,加上小蔡多次跟袁Sir反馈业务太杂,不但累且容易出篓子,袁Sir这才把几个部门进行了拆分,人事部交给了小任,行政部交给了小邢,法务由老发掌管。

经过几个月的验证,让袁Sir欣喜的是,运营成本不但没有增加,员工的工作状态也比之前大有改善。

从此,财务部门小蔡提供的服务列表:

  1. 核对报销单

  2. 处理报销

  3. 发工资

人事部门小任提供的服务列表:

  1. 招聘新员工

  2. 员工绩效考核

  3. 员工培养

行政部小邢提供的服务列表是:

  1. 举办年会

  2. 接待来宾

法务部提供的服务列表是:

  1. 审核营业执照

  2. 审核信息安全

周五晚上10点,袁Sir走出办公室大门,哼着小曲自言自语道:还得专门的人干专门的事呀,勿贪多,贪多必失…

袁Sir睡前打开电脑,在备忘录写下: 分离关注点(专注)是做好一件事的有效途径,如果同时需要兼顾多项不太相关的工作,注意力就必须在不同的上下文切换,会大大降低工作效率,更糟糕的是可能会出现一些意外的灾难 。敲完欣慰睡去。

在软件设计中,SRP 提倡让一个类只处理一组相关的事情,控制了它的变化方向,后期也能更好的定位。如果引发变化的因素很多,会导致类的职责过多,难以维护,常见的上帝类就是这么形。

FNjU3a6.png!mobile

引入中间人读书大使,解放自己

经过几年的发展,袁Sir的公司俨然已经步入正轨,他开始思考公司文化建设方面的事情。

袁Sir一直对读书非常重视,他想在公司把读书运动搞起来,每周搞一次分享大会。起初他提议由行政部和人事部来牵头搞,两个部门轮流来,自己直接分别跟两个部门负责此事的负责人对接。

两个月过去了,公司的读书氛围得到大大提升,书架遍布公司各个角落,水果时间也从八卦转向了读书心得的分享。

欣慰之余,袁Sir也感觉有点力不从心。经常出现这种现象:有时候去他找人事部的小史商量工作,却被告知这周轮到行政部的小郑了,而去找小郑的时候,被告知市场部也是组织者之一,本周轮到市场部了。

袁Sir因为业务繁忙,加上翻来覆去的对接工作,搞得心累,但他又很重视这件事情。琢磨良久,他决定给自己招一个读书会大使(有钱了可以稍微任性一下下),每周要开展读书运动大会前,他直接跟读书大使对接,大使后续再去协调对应的部门开展工作。

经过这么一整改,袁Sir得到了解放,再也不用关心这周该由哪个部门组织,下次会有什么新的部门加入进来。

看着读书运动在公司里遍地开花,袁Sir心想着年底了要给读书最多,分享最多的同事多发12个月的年终奖…

[OCP解读]  在一开始,袁Sir支持某个部门举办的读书会,后续只要有新的部门要负责举办时(好比功能上的扩展),袁Sir都要改变自己的沟通方式,这意味着他自身做出修改才能支持新的需求,此时,袁Sir对修改是开放的。引入读书大使后,相当于做了一个抽象,袁Sir只需要依赖这个抽象,再有新的部门举办读书会时,他就不需要在改变沟通方式了,此时,袁Sir对修改是关闭的,对扩展是开放的。

在软件设计中,OCP 提倡对修改关闭,对扩展开放。建议为你的服务调用者提供一个他需要的抽象、高层次的行为接口,后期你的服务有新的种类,你只需要新增一个实现该抽象、高层次接口具体服务,而不需要修改调用者的使用方式

Bbyaiyy.png!mobile

创业故事回顾

从袁Sir的故事中可以看出来,袁Sir在不同阶段之所以面临各种不同的痛点,主要原因有两点:

  1. 关注的事情太多

  2. 关注事情的细节

创业初期,袁Sir这么做问题不大,公司在不断地发展壮大(如同软件的演变),袁Sir就需要琢磨出新的方案,而这些方案的核心观念无非两个:

  1. 分离关注点

  2. 引入中间人

在面向对象软件设计中,关注点分离,其实体现的就是软件设计的精髓 – 高内聚,低耦合,引入一个中间人 则跟 面向抽象编程 有异曲同工之处。

写在最后

SOLID原则,它其实是在帮助指导我们设计出高内聚,低耦合 的软件,降低软件后期的维护成本。虽然原则不能时刻有效指导编码落地,理解这些原则背后的设计理念,让你迈出了第一步,接下来,你需要做的是在前进的路上,不断地进行编码实践、思考总结,将其内化。

最后,我想跟技术人员共享一个关键词汇 – 用户视角/业务视角:

我们学到了的很多技巧(设计原则、设计模式、重构手法等),如果忘记初衷,失去目标,代码写得再炫酷、再健壮,也很难体现出应有的价值。从业务需求出发,以用户视角看问题,致力编写出简洁可用的代码即可

参考阅读

让里氏替换原则为你效力

解析简单设计原则

聊聊面向对象设计中的Is-A

写了这么多年代码,你真的了解SOLID吗?

- 相关阅读 -

超越培训——比培训多做一点点

使用DDD指导业务设计的一点思考

fyIreev.jpg!mobile

点击【阅读原文】可至洞见网站查看原文 &绿色字体 部分的相关链接。

本文版权属ThoughtWorks公司所有,如需转载请在后台留言联系。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK