单一责任原则
(“每个班级应该只有一个责任;换句话说,每个班级应该只有一个,并且只有一个改变的理由”)
我不同意。我认为一个方法只应该有一个改变的理由,并且一个类中的所有方法应该彼此之间具有逻辑关系,但是该类本身实际上可以做几件事(相关的事情)。
以我的经验,这个原则常常过于热心地应用,并且您最终会遇到许多微小的单方法类。我工作过的两家敏捷商店都做到了。
想象一下,如果.Net API的创建者具有这种思维方式: 我们将拥有ListSorter,ListReverser和ListSearcher类,而不是List.Sort(),List.Reverse(),List.Find()等!
我不再分享SRP (从理论上讲它并不可怕),而是分享一些我漫长的轶事经历:
在我工作的地方,我写了一个非常简单的最大流量求解器,它由五个类组成:一个节点,一个图,一个图创建器,一个图求解器,以及一个使用图创建器/求解器来求解一个类的类。实际问题。没有一个特别复杂或很长(求解器最长的〜150行)。但是,确定类具有太多的“职责”,所以我的同事着手重构代码。完成后,我的5个班级已扩展到25个班级,它们的总代码行是原来的三倍多。代码的流程不再明显,新的单元测试的目的也不再明显。我现在很难弄清楚自己的代码做了什么。
在同一地方,几乎每个类都只有一个方法(它只有“责任”)。遵循程序中的流程几乎是不可能的,并且大多数单元测试包括测试该类从另一个类中调用代码,这两个目的对我来说都是一个谜。从字面上讲,有数百个班级应该只有几十个班级。每个类仅执行一个“操作”,但是即使使用“ AdminUserCreationAttemptorFactory”之类的命名约定,也很难分辨出类之间的关系。
在另一个地方(也具有类应该只有一种方法的心态),我们正在尝试优化一种方法,该方法在特定操作中会占用95%的时间。经过(有点愚蠢的)优化之后,我将注意力转向了为什么它被称为“ bajillion次”。它在一个类的循环中被调用...其方法在另一个类的循环中被调用..该方法也在一个循环中被调用..
总而言之,有五个级别的循环(严重地分布在13个类中)。仅仅通过查看它就无法确定任何一个类实际上正在执行的操作-您必须绘制一个心理图,说明它调用了什么方法以及那些方法调用了什么方法,依此类推。如果将所有方法都归纳为一种方法,那么问题方法将嵌套在五个显而易见的循环级别中,那么大约只有70行。
我要求将这13个类重构为一个类的请求被拒绝。