The Single Responsibility Principle(译)

来源:8th light
作者:Robert Martin


在1972年, David L. Parnas出版了一篇名为On the Criteria To Be Used in Decomposing Systems into Modules经典文章。出现在当年十二月ACM社区论坛第15页中编号为12的位置。

在这篇文章中,Parnas比较了两种不同的用于分解一个单一算法逻辑的策略。这篇文章十分吸引人,我强烈建议你们去研究它。他在文章中得出部分结论如下所示:

“我们尝试用这些例子来证明,仅仅基于流程图而将一个系统分解为各个模块的做法常常是不正确的。作为替代,我们建议先准备一个清单,上面列出复杂的设计方案,或者是有可能会改变的设计方案。每一个模块用于存放这样的方案以便与别的部分隔离”

我立刻就在最后一段话上加了强调符。Parnas的结论是这些模块应该基于,至少部分基于,它们可能会改变的方式而被分离出来。

两年后,Edsger Dijkstra写了另外一篇经典文章,名为On the role of scientific thought, 在文章中他介绍了他的主张 : The Separation of Concerns.

二十世纪七,八时年代是软件架构(sofewarre architecture)原则的丰产时期。结构化编程与设计(Structured Programming and Design) 十分流行。就在那段时间,耦合与内聚(Coupling and Cohesion) 的概念被Larry Constantine提出, 并被Tom DeMarco, Meilir Page-Jones以及其它许多人丰富。

在二十世纪九十年代后期,我打算将这些概念巩固并称为一个原则,我把它命名为单一功能原则(The Single Responsibility Principle) (我有一种模糊的感觉:我这个原则的名字是从Bertrand Meyer那里偷窃过来的,但是我还没有能够去确认)。

单一功能原则(The Single Responsibility Principle,SRP)规定:每一个软件模块应该有且仅有一个理由被改变(each software module should have one and only one reason to change)。这听起来很好,而且看起来符合Parnas所提出的模式。但是它回避了一个问题:改变的理由应该如何定义(What defines a reason to change)?

一些人疑惑修复错误(bug-fix)是否能作为改变的理由。另一些人疑惑重构是否能作为改变的理由。这些问题可以这样解决:指出术语“改变的理由” 和 “功能” 之间的耦合度(These questions can be answered by pointing out the coupling between the term “reason to change” and “responsibility”.)

(ps:这段话翻译时有点蒙,尤其是最后一句)

诚然程序的功能并不是去解决错误或者重构。这些事情是编写程序者需要承担的,而不是程序本身。那么如果上句话成立,那么程序的功能是什么呢?哦,可能一个更好的说法: 程序需要对负责( who is the program responsible to), 改进一下:设计程序的方案必须对负责( who must the design of the program respond to)

想象一个典型的公司组织形式。CEO在最顶层,首席级别的官员对他负责:CFO,COO,CTO。CFO的职责是掌控公司的财政,COO的职责是管理公司的运作。CTO的职责是对公司的技术进行构建与开发。

现在来看一段java代码

    public class Employee{
        public Money calculatePay();
        public void save();
        public String reportHours();
    }
  • calculatePay 方法基于诸如劳务合同,职位,工作时长等因素决定一个员工的工资高低。
  • save 方法将 Employee 对象所存储的数据存入公司数据库
  • reportHours 方法返回一个字符串,附于一个报告上,用于审计师来确认员工工作了恰当的时长,并且被支付的对应的工资。

现在,哪一个向CEO报告的首席官员需要承担规定calculatePay 方法责任?又是哪一个首席官员需要对这个方法灾难般的错误执行负责?十分清楚,是CFO。规定员工工资是一项经济类职责。如果每一个员工在一年中由于CFO所领导的团队错误规定了计算工资的规定而都被付了双倍工资,CFO很有可能被解雇。

一个不同的首席官员对规定 reportHours 方法所返回的字符串的形式与内容负责。这位官员管理着审计师与审稿人, 而且这是运营类职责。所以如果在这里出现灾难般错误,那么COO将会被开除。

最后, save 方法出现灾难般的错误话哪一个首席官员将被清退是很清楚的。如果公司数据库由于这个错误而崩溃,CTO很有可能被开除。

所以,如果当 calculatePay 方法内部算法改变时,改变算法的人应该是来自CFO所领导的团队。同样的,应该由COO团队的人来修改 reportHours 方法,由CTO团队的人来修改 save 方法。

这就到达了单一功能原则(The Single Responsibility Principle) 的症结所在:这个原则是关于人的(This principle is about people)

当你编写一个程序模块时,你需要确保当发起改变请求时,这个请求只能来源于一个人,或者,代表着一个单一商业职责的一组人(a single tightly coupled group of people representing a single narrowly defined business function)。你需要将你的模块从复杂的整体中独立出来,将你的系统设计成每一个模块仅仅承担一个商业职责的形式。

为什么?因为我们不希望COO由于CTO的修改行为而被解雇。没有什么比让顾客和经理发现一个这个程序出现这样的故障而让他们吃惊的了,在他们的角度,与他们的要求毫不相关。如果你修改了 calculatePay 方法而不可避免地损坏了 reportHours 方法, 那么接下来COO就会开始要求你永远都不要再改变 calculatePay 方法了

想象一下你将你的汽车交给一个机械师去维修损坏的电动车窗。第二天他打电话给你说完全修好了。当你去取车时,你发现车窗修好了,但是汽车无法发动起来了。似乎你不会再去请那个机械师维修了因为他就是一个白痴。

这就是当顾客和经理发现我们损坏了他们关心的,而且并没有要求我们改变的东西时的心情。

这就是我们不会在JSPs中书写SQL,不会在计算结果的模块中书写HTML,商业规则中没有数据库模式的原因。这就是我们分散需求(separate concern)的原因

单一需求原则(The Single Responsibility Principle)的另一种解释为:

将由于相同原因而改变的部分聚集在一起。将由于不同原因而改变的部分分散开来

如果你对上述语句进行思考,你会发现这就是对耦合与内聚(Coupling and Cohesion) 的另一种定义形式。我们希望增加因为相同原因给改变的部分之间的耦合度,减少由于不同原因而改变的部分之间的聚合度。

但是,正如现在你对这个原则的思考一样,记住,产生改变理由的是人。是由人来提出改变。因为不同的人产生关心的原因并不相同,你不希望让别人,或者你自己,由于因此而产生的混乱的代码而感到困惑。(However, as you think about this principle, remember that the reasons for change are people. It is people who request changes. And you don’t want to confuse those people, or yourself, by mixing together the code that many different people care about for different reasons.)

(ps:最后一段也没太理解)


ps: 最后来一段摘自维基百科的解释

The single responsibility principle states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、资源1项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值