当前位置: 首页 > 后端技术 > Node.js

【译文】单一职责原则

时间:2023-04-03 16:51:12 Node.js

简介我在很多地方都看过或者听说过单一职责原则。看完这篇《The Single Responsibility Principle》,我又有了新的认识。让我翻译记录一下。原文有些链接失效了,找了资源重新改了下。原文翻译:TheSingleResponsibilityPrinciple出处我的GitHub文字1972年,DavidL.Parnas发表了一篇优秀的论文,名为《On the Criteria To Be Used in Decomposing Systems into Modules》。这篇文章发表在《Communications of the ACM》12月号,第15卷,第12期。在这篇论文中,帕纳斯在一个简单的算法中比较了两种不同的逻辑分解和分离策略。这篇论文很有趣,我强烈建议您研究它。他的部分结论如下:我们试图通过这些示例证明,根据流程图开始将系统分解为模块几乎总是不正确的。相反,我们建议从一系列困难的设计决策或可能发生变化的设计决策开始。然后,每个模块都被设计成对其他模块隐藏此类决定。我强调第二句。Parnas得出结论,模块应该按照它们可能改变的方式分开,至少部分分开。两年后,EdsgerDijkstra写了一篇题为《On the role of scientific thought》的优秀论文。在这篇文章中,他引入了一个术语:关注点分离。70年代和80年代是软件架构原则的鼎盛时期。结构化编程和设计风靡一时。在此期间,LarryConstantine引入了Coupling和Cohesion的概念,TomDeMarco、MeilirPage-Jones和其他许多人对这些概念进行了扩展。在20世纪90年代后期,我试图将这些概念整合到一个原则中,我称之为:单一职责原则。(我有一种模糊的感觉,我从BertrandMeyer那里盗用了该原则的名称,但我无法证实这一点。)单一职责原则(SRP)指出每个软件模块都应该有一个原因。这听起来不错,而且似乎符合Parnas的理念。然而,它引出了一个问题:什么定义了改变的原因?有些人想知道错误修复是否是改变的理由,其他人想知道重构是否是改变的理由。这些问题可以通过指出“改变的原因”和“责任”之间的耦合来回答。当然,代码不负责错误修复或重构。这些事情是程序员的责任,而不是程序。但如果是这样,这个程序负责什么?或者,一个更好的问题:这个项目对谁负责?更好的是:程序的设计必须响应谁?想象一个典型的商业组织,最高层有一个CEO(首席执行官),向CEO汇报的C级高管有:CFO(首席财务官)、COO(首席运营官)和CTO(首席技术官)等.CFO负责控制公司的财务。COO负责管理公司的运营。CTO负责公司内部的技术基础设施和开发。现在考虑下面这段Java代码:publicclassEmployee{publicMoneycalculatePay();公共无效保存();publicStringreportHours();}calculatePay方法实现了一些算法,这些算法根据员工的合同、职位、工作时间等因素来决定应该给员工支付多少工资。save方法存储了Employee管理的数据企业数据库中的对象。reportHours方法返回一个字符串,该字符串被添加到报告中,审计员使用这个字符串来确保员工在正确的时间工作并获得正确的报酬。现在,向CEO汇报的C级管理人员中谁负责指定calculatePay方法的行为?如果这个方法的规范出现严重错误,其中哪一个会被CEO开除?显然,答案是CFO。规范员工工资是一项财务责任。如果CFO组织中有人制定了严重错误的薪酬计算规则,所有员工将少付一年的薪水。是两倍,那么CFO很可能被解雇。另一位C级主管负责指定reportHours方法返回的字符串的格式和内容。这个执行官管理审计员和审计员,这是运营部门的职责。因此,如果报告出现灾难性错误,首席运营官将被解雇。最后,如果save方法被灾难性地错误指定,那么哪些C级高管将被解雇应该是显而易见的。如果公司数据库被如此可怕的错误指定破坏,那么CTO很可能会被解雇。因此,当算法在calculatePay方法中更改时,这些更改的请求将来自以CFO为首的组织是合理的。同样,COO的组织将要求更改reportHours方法,而CTO的组织将要求更改save方法。这是单一职责原则的关键。这个原则是关于人的。在编写软件模块时,您希望确保在请求更改时,这些更改只能来自一个人,或者更确切地说,来自代表严格定义的业务功能的紧密耦合的组。您希望将您的模块与整个组织的复杂性隔离开来,并设计您的系统,以便每个模块只负责(响应)一个业务功能的需求。为什么?因为我们不想因为CTO的变更请求而解雇COO。从他们的角度来看,对于我们的客户和经理来说,没有什么比在程序中发现与他们要求的更改完全无关的错误更可怕的了。如果您更改了calculatePay方法,并且无意中破坏了reportHours方法,COO将开始要求您永远不要再更改calculatePay方法。想象一下,您将汽车开到机械师那里修理破损的电动车窗。他第二天打电话告诉您一切都已解决。当你提车时,发现车窗工作正常,但汽车无法启动。你不太可能回到那个机械师那里,因为他显然是个混蛋。这就是当客户和经理不要求我们改变时的感觉,我们破坏了他们关心的事情。这就是我们不在jsp中使用SQL的原因。这就是为什么我们不在计算结果的模块中生成HTML。这就是为什么业务规则不应该知道数据库模型的原因。这就是我们分离关注点的原因。单一职责原则的另一种表达方式是:将因相同原因发生变化的事物集中在一起。将因不同原因而改变的事情分开。如果您考虑一下,这只是定义内聚和耦合的另一种方式。我们希望增加因相同原因而变化的事物之间的内聚性,并减少因不同原因而变化的事物之间的耦合性。无论哪种方式,当您考虑这个原则时,请记住改变的原因是人。要求改变的是人。不同的人出于不同的原因关心,您不希望将这些代码混合在一起并混淆这些人或您自己。参考资料单一职责原则