我需要帮助来澄清我对单一责任原则(SRP)的(错误)理解。

在我从事的许多项目中,我的同事认为SRP意味着类应该实现非常有限的功能,例如计算一组对象的总计。这导致类具有一种公共方法(一种责任),例如CalculateTotals(...)。我不是DDD专家,但是从我所看到的结果来看,这会导致Anemic域模型,DTO和无休止的微服务。

采用这种方法并将DRY添加到混合中会导致在应用程序的不同部分中重复使用这些类。

我倾向于在更高的级别(需求级别)上考虑SRP。例如,需要为报告计算总计,而为税收相关计算需要计算总计。在这种情况下应用DRY可能会导致意外错误。当总计计算逻辑因报表要求的变化而需要更改时,如果我们应用了DRY并重用了该类,则我们将中断税额计算。

鉴于更改的原因仅应是需求更改的结果(我认为此处不适用重构),DRY原则应仅在单个用例范围内吗?

如果上述说法正确,是否意味着我们不必将税收计算分为一个单独的类?好吧,我们可以这样做来简化代码,但是由于SRP的原因我们不这样做吗?

我的想法错了吗?

最佳答案

单一责任原则实际上是怎么说?

The Single Responsibility Principle doesn't say that a class should implement very limited functionality, it says that there should only be one reason for a class to change.因此(至少就SRP而言),如果一个类可能仅出于一个原因发生更改,则该类具有许多方法是可以的。与所有这些原则一样,确定SRP是否适用(等效地,确定构成类别更改的一个单独原因)与品味和判断有关。

例如,在我刚刚链接到的SRP的原始描述中,我发现SRP在玩具保龄球游戏中的应用是免费的-如果更改保龄球规则,则单独的类将全部更改。另一方面,将几何计算与呈现UI分开对任何人都应该有意义。

我不知道您的代码库,但是每个方法的类对我来说都是错误的。

SRP与DRY有什么关系?

SRP的反面是,如果两个类别出于相同的原因而改变(如在保龄球比赛中一样),也许它们应该是一个类别。这本身与DRY根本无关(这是责任的分散,而不是代码的重复),但是:如果某人在编写或提取第二类时忘记了DRY,您可能会注意到在进行更改时这两个类(或者更糟的是,当您忘记更改一个类并在生产中发现)时,请记住为什么DRY很重要。

我是否应该对我负责的类进行重复数据删除(“DRY up”)?

是。相同代码的副本会导致错误。不要无理取闹;如果提取某些重复项会使您的程序难以理解,并增加了代码行数,那么您肯定会做得过多。但是请提取大量重复项,而只需测试一次,并在更改时进行一次更改。

但是,请始终清楚提取的方法与需求之间的关系。如果您需要以相同的方式对一些值求和以进行报告和税收计算,请不要调用totalForReporting方法或将其命名为total并将其放在ReportingService上,然后再从TaxService中调用它-想要更改报告和而不是税收计算不会考虑检查该方法是否在其名称不会引起您期望的上下文中使用。相反,调用类似transactionTotal之类的通用方法,或仅将其命名为total并将其放在您的GeneralLedgerService上,这将完全(知道)其作用是什么以及何时应更改或不更改。

着眼于需求的重复数据删除将增强您的域模型,因为您将始终谨慎地将代码与适当的域概念(无论是模型,服务还是其他东西)相关联。

10-07 14:56