Sua*_*ere 13
你问:如果没有,他们有什么不同?
抛出你认为这个原则意味着什么.
Robert C. Martin正式将此原则定义为:
一个班级应该只有一个改变的理由
定义SRP的大多数人都是不正确的.SRP通常被误解为:
"这个Employee班不应该,UpdateDemographics()并且SendMessage(),这算作两个责任......放入SendMessage()一个Message类!!"
^^错了
vv对
罗伯特C.马丁说
"责任不是代码所做的事情".(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并不意味着永远不会重复.正如我所提到的:很多时候你可能会有重复的代码,因为业务规则在不同的问题中是相似的,并且有不同的改变原因.