是否有不止一种方法违反单一责任原则?

问题描述 投票:2回答:2

我对单一责任原则非常困惑。 《原则》指出,改变班级只有一个原因。

我面临的问题是,对方法的任何更改或在执行操作中的任何逻辑更改都会更改类。例如,考虑以下类:

class Person{
    public void eat(){ };
    public void walk(){ };
    public void breathe(){ };
    public void run(){ };
    public void driveCar(Car car){ };
}

Bob叔叔将其描述为只有一个人/演员负责更改。我有以下两个问题:

  1. 对于上述阶层,谁是负责改变的演员/人?
  2. 饮食,呼吸或走路的逻辑上的任何改变都不会改变班级的人吗?难道这并不意味着每种方法都是改变的理由,因为做事的逻辑可能会改变?
java oop design-patterns solid-principles single-responsibility-principle
2个回答
1
投票

有趣的问题。 “鲍勃叔叔”马丁的quote是:

一个班级应该只有一个改变理由。

一个人可能会这样解释,即您的Person类具有五个更改原因:您可能想更改eat方法,或更改walk方法,breathe方法或[C0 ]方法或run方法。但这太狭窄了,并没有真正体现出马丁所说的“改变的理由”。]]。

更改类的原因意味着人类程序员更改类的动机。您不会仅仅因为有动力改变driveTheCar方法就改变了eat方法;您可以对其进行更改,以实现有关程序所需行为的一些目标。

如果eat类为某人建模以进行某种模拟,那么您进行更改的动机将是您希望[[“更改在模拟中对人的行为进行建模的方式”]

Every您对类所做的更改都是出于这个原因,无论您更改了一种方法还是多种方法都可以;因此Person类只有一个“理由”可以更改,可以满足SRP。如果Person类还具有其他方法,例如在屏幕上绘制人物,那么您可能还希望

“更改模拟人物的图形外观”]]。这与改变模拟人的行为的方式的动机是完全不同的动机,因此班级将承担两个责任,违反了SRP。


更改理由是什么

    对于上述阶层,谁是负责改变的演员/人?

  • Person是:用户(包括客户,利益相关者,组织的开发人员)或外部系统。

    我们可以争论人是否是系统,但无论是那里还是那里。

    另请参见:Actor

      饮食,呼吸或走路的逻辑上的任何改变都不会改变班级的人吗?难道这并不意味着每种方法都是改变的理由,因为做事的逻辑可能会改变?
  • 不,方法不是改变的理由。方法可以改变……但是为什么会改变呢?是什么会触发开发人员进行更改?


    那么,什么是责任?

    一个责任是一个人,这不是代码要做的事情,它是一个想要更改代码的人。-罗伯特·马丁(Robert C Martin)


    单一责任原则的一部分是,代码最多应与一个外部系统进行交互。

    [请记住,并非所有参与者都是外部系统,但有一些是外部系统。

    我认为大多数人会发现SRP的这一部分易于理解,因为我们可以在代码中看到与外部系统的交互。
    但是,这还不够。例如,如果您的代码必须计算税金,则可以在代码中对税率进行硬编码。这样,它就不会与任何外部系统进行交互(它只是使用一个常量)。但是,后来进行了一项税制改革,政府成为更改您的代码的原因。


    您应该能够做的是互换外部系统(也许需要额外的编码工作)。例如,从一个数据库引擎更改为另一个。但是,我们不希望这些更改之一转换为完全重写代码。更改不应传播,更改也不应破坏其他内容。为了确保这一点,我们希望隔离所有与数据库引擎相关的代码(在此示例中)。

    由于相同原因而发生变化的事物应归为一类,由于不同原因而发生变化的事物应分开。-罗伯特·马丁(Robert C Martin)

    我们可以对上面的政府示例进行类似的操作。我们可能不希望软件读取会议记录,而可以让它读取配置文件。现在,外部系统是文件系统,并且将存在与之交互的代码,并且该代码不应与其他任何交互。


    我们如何确定那些改变的原因?

    您的代码由一组要求定义。有些功能正常,有些则无法。如果这些要求中的任何一项发生更改,则您的代码必须更改。更改需求的原因是更改代码的原因。

    注:可能没有记录所有需求,但是仍然有未记录的需求。

    然后,您需要知道这些要求来自何处。谁或什么可以改变他们?这些就是您改变的原因。可能是公司政策的变化,可能是我们添加的功能,可能是新法律,可能是我们正在迁移到其他数据库引擎或操作系统,并转换为另一种语言,适应其他国家等

    其中有些是您的代码与之交互的外部系统(例如,数据库引擎),有些则不是(公司的政策)。


    如何处理责任

    您想隔离它们。因此,您将拥有与数据库交互的代码,仅此而已。您将拥有实现业务规则的代码,仅此而已。依此类推。

    意识到,即使代码的每个部分的实现都将取决于外部因素,它们的接口也不一定必须如此。因此,定义接口并注入依赖项,以便您可以更改每个部分的实现而不必更改其他部分……也就是说,代码部分的实现不应成为更改代码其他部分的实现的理由。

    :您的代码的任何部分都不应该承担多重责任。让代码的一部分负责每个职责,让代码的一部分负责将其他部分放在一起。同样,如果您的代码的一部分不承担任何责任,则没有理由保留它。因此,您的代码的每一部分都应该完全负责。

    对于您的代码,问自己,Use case类的要求是什么。他们完成了吗?它们来自哪里?他们为什么会改变?


    推荐观看

    有关单一责任原则的更权威解释,请参阅2015年挪威开发者大会上的Person(51分钟8秒,英语)。


  • 0
    投票

    更改理由是什么
    © www.soinside.com 2019 - 2024. All rights reserved.