高凝聚力 是 单一责任原则的同义词吗? 如果没有,它们有何不同?
答案 0 :(得分:10)
您问:如果没有,它们有何不同?
扔出你认为这个原则意味着什么。
Robert C. Martin正式将此原则定义为:
一个班级应该有一个改变的理由
定义SRP的大多数人都不正确。 SRP通常被误解为:
" Employee
课程不应该UpdateDemographics()
和SendMessage()
,这要算作两个责任......将SendMessage()
放入Message类! !"
^^错误
vv正确
Robert C. Martin说
"责任不是代码所做的事情'"。 (NDC 2012)
Robert C. Martin将SRP定义为:
"任何模块都应该只对一个人 - [角色]负责。" (NDC 2012)
当利益相关方要求更改视图中的数据排序时,管理层不应该担心并且担心算法会中断。因为在View上处理Sorting的模块只对利益相关者负责,而处理总计算算法的模块只对业务分析师负责。所以当业务分析师要求对算法进行更改,我们不应该担心View会发生变化。
因此,模块(单数)只应因以下原因而改变:此模块所服务的单人 - 角色已请求更改。
将其作为SRP定义的新基础,您现在可以应用之前思考 SRP的内容,并使定义更加精细。没有人会说将所有前端代码放入一个模块,将所有后端代码放入一个模块中。
想象一下,您有方法decimal CalculatePayFor(Employee)
和另一种方法void Pay(Employee)
这些属于一起吗?可能有一个服务可以执行所有类型的计算,并且可能有一个服务只能包装人力资源支付SOAP。也许Pay(Employee)
会调用CalculatePayFor(Employee)
,但仅仅因为他们中有Pay
这个词并不意味着他们属于一起!
如何创造凝聚力? - 你不是。凝聚力是你观察到的。你所做的是不要撕掉属于你的东西。
可以为您想要的每个公共方法创建一个类。每个类现在都有一个公共方法,一切都是明确的混乱。你有一个名为PayrollClass1
和PayrollClass2
的类,因为一个是单向计算,另一个是双向计算。
有些语言甚至可以从完全缺少类中获益,并且方法可以自由运行。没有方法分组,方法只是您可以随时调用的方法。他们几乎都是静止的。
然而,您可以观察 CalculatePayFor(Employee)
和Pay(Employee)
实际上非常绑定。他们就像一对当选夫妇,他们看起来很棒。当方法明显属于一起时,你不想将它们分开。观察它们的自然状态并建立一个野生动物保护区。这是保持高凝聚力。你没有创造它,你观察它。
这真正有用的是正确的代码重复。例如,PayrollService.CalculatePayFor(Employee)
与ReportService.CalculatePayFor(Employee)
具有完全相同的代码。这不好吗?当然不是。如果高级管理层要求为报告而更改员工薪酬的计算,则该责任与人力资源部门要求您为实际付款方式的税务目的进行变更时的责任不同。
"等等,他只是混淆了SRP和Cohesion?"不,但我很高兴你认识到混乱。如果ReportService进入PayrollService'类和使用它的方法?然后,当它为合法付款目的而改变时,报告全部改变......但管理层并不想要这样!因此,由于Cohesion强制方法保留在自己的类中,并且SRP强制模块在应用程序中保持自己,因此ReportService被强制从PayrollService类复制/粘贴方法。现在他们可以彼此独立地改变。
"但如果那不是你想要的怎么办?"好吧,代码中有很多地方可以排除重复。但算法最常见的是坚持自己,并且独立于依赖性而改变。即使这意味着重复。这取决于需要什么。但是,关注点分离,单一责任,凝聚力和干燥(不要重复自己)都是不同的想法。
侧注:DRY并不意味着永远不会重复。正如我所提到的:很多时候你可能会有重复的代码,因为业务规则在不同的问题中是相似的,并且有不同的原因需要改变。
答案 1 :(得分:6)
这不是一回事。
你可以拥有一个高度凝聚力的课程,而不仅仅有一个责任。
答案 2 :(得分:3)
答案 3 :(得分:0)
在罗伯特·马丁(Robert Martin)的own words中,
如果考虑[SRP],您会意识到这只是定义内聚和耦合的另一种方式。我们希望增加由于相同原因而改变的事物之间的凝聚力,并且我们希望减少因不同原因而改变的事物之间的耦合。
另请参阅:Difference between Single Responsibility Principle and Separation of Concerns。