我对单一责任原则很困惑。 《原则》指出,班级变更只有一个原因。
我面临的问题是,对方法的任何更改或在执行操作中的任何逻辑更改都会更改类。例如,考虑以下类:
class Person{
public void eat(){ };
public void walk(){ };
public void breathe(){ };
public void run(){ };
public void driveCar(Car car){ };
}
鲍勃叔叔将其描述为只有一个人/演员负责更改。我有以下两个问题:
答案 0 :(得分:2)
有趣的问题。来自“鲍勃叔叔”马丁的quote是:
一个班级应该只有一个改变理由。
可以这样解释,即您的Person
类有五个更改原因:您可能想更改eat
方法,或更改walk
方法,或{{ 1}}方法或breathe
方法或run
方法。但这太狭窄了,并不能真正反映出马丁所说的“ 改变理由” 。
更改类的原因意味着人类程序员更改类的动机。您不会仅仅因为有动力改变driveTheCar
方法而改变eat
方法;而是您将对其进行更改,以实现有关程序所需行为的一些目标。
如果eat
类为某人建模以进行某种模拟,那么您进行更改的动机将是您希望“更改模拟人的行为的方式” 。您对课程进行的每次更改都是出于这个原因,无论您更改了一种方法还是多种方法都可以。因此Person
类只有一个“理由”可以更改,可以满足SRP。
如果Person
类还具有其他方法,例如在屏幕上绘制人物,则您可能还希望“更改模拟人物的图形外观” 。这与改变模拟人的行为的方式的动机是完全不同的动机,因此,班级将承担两个责任,违反了SRP。
答案 1 :(得分:1)
- 对于上述阶层,谁是负责变革的演员/人?
Actor是:用户(包括客户,利益相关者,组织的开发人员)或外部系统。 我们可以争论人是否是系统,但这不是这里也不是那里。
另请参见:Use case。
- 饮食,呼吸或走路的逻辑不会改变“人”的等级吗?难道这并不意味着每种方法都是改变的理由,因为做事的逻辑可能会改变吗?
不,方法不是改变的理由。方法可以改变……但是为什么会改变呢?是什么会触发开发人员进行更改?
单一责任原则的一部分是代码最多应与一个外部系统进行交互。 请记住,并非所有参与者都是外部系统,而是某些参与者。我认为大多数人会发现SRP的这一部分易于理解,因为我们可以在代码中看到与外部系统的交互。
但是,这还不够。例如,如果您的代码必须计算税金,则可以在代码中对税率进行硬编码。这样,它就不会与任何外部系统进行交互(它只是使用一个常量)。但是,在后来的一项税制改革中,政府已被披露为更改您的代码的原因。
您应该能够做的是互换外部系统(也许需要额外的编码工作)。例如,从一个数据库引擎更改为另一个。但是,我们不希望这些更改之一转换为完全重写代码。更改不应传播,更改也不应破坏其他内容。为了确保这一点,我们希望隔离所有与数据库引擎相关的代码(在此示例中)。
由于相同原因而发生变化的事物应归为一组,由于不同原因而发生变化的事物应分开。 -罗伯特·马丁(Robert C Martin)
我们可以用上面的政府示例做类似的事情。我们可能不希望软件读取会议记录,而可以让它读取配置文件。现在,外部系统是文件系统,并且将存在与之交互的代码,并且该代码不应与其他任何东西交互。
您的代码由一组要求定义。有些功能正常,有些则无法。如果这些要求中的任何一项发生更改,则您的代码必须更改。更改需求的原因是更改代码的原因。
注意:您可能没有记录所有需求,但是仍然有未记录的需求。
然后,您需要知道这些要求从何而来。谁或什么可以改变他们?这些就是您改变的原因。可能是公司政策的变化,可能是我们添加的功能,可能是新法律,可能是我们正在迁移到其他数据库引擎或操作系统,并转换为另一种语言,适应其他国家等
其中有些是代码与之交互的外部系统(例如数据库引擎),有些则不是(公司的政治)。
您想隔离它们。因此,您将拥有与数据库交互的代码,仅此而已。您将拥有实现业务规则的代码,仅此而已。依此类推。
意识到即使代码的每个部分的实现都将依赖于外部的东西,它们的接口也不必一定要这样做。因此,定义接口并注入依赖项,以便您可以更改每个部分的实现而不必更改其他部分……也就是说,代码部分的实现不应成为更改代码其他部分的实现的理由
注意:您的代码的任何部分都不应该承担多重责任。让代码的一部分负责每个职责,让代码的一部分负责将其他部分放在一起。同样,如果您的代码的一部分不承担任何责任,则没有理由保留它。因此,您的代码的每一部分都应该完全负责。
对于您的代码,请问自己,Person
类的要求是什么。他们完成了吗?它们来自哪里?他们为什么会改变?
有关单一责任原则的更权威解释,请参见2015年挪威开发者大会上的Robert C Martin - The Single Responsibility Principle(51分钟8秒,英语)。