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