根据Microsoft文档,有关Wikipedia SOLID原则的文章或大多数IT架构师,我们必须确保每个班级仅负一个责任。我想知道为什么,因为如果每个人似乎都同意这条规则,那么似乎没人会同意这条规则的原因。
一些人引用了更好的维护,有人说它提供了简单的测试,或者使类更加健壮或安全。什么是正确的,实际上是什么意思?为什么它可以使维护更好,测试更容易或代码更健壮?
根据Microsoft文档,有关Wikipedia SOLID原则的文章或大多数IT架构师,我们必须确保每个班级仅负一个责任。我想知道为什么,因为如果每个人似乎都同意这条规则,那么似乎没人会同意这条规则的原因。
一些人引用了更好的维护,有人说它提供了简单的测试,或者使类更加健壮或安全。什么是正确的,实际上是什么意思?为什么它可以使维护更好,测试更容易或代码更健壮?
Answers:
模块化。任何体面的语言都会为您提供将代码段粘合在一起的方法,但是没有程序员在源头上不做手术的一般方法,就无法解开大段代码。通过将许多任务卡在一个代码结构中,您会失去自己和其他人机会,以其他方式组合其各个部分,并引入不必要的依赖关系,这些不必要的依赖关系可能导致对一个部分的更改影响其他部分。
SRP适用于函数,也适用于类,但是主流的OOP语言在将函数粘合在一起方面相对较差。
更好的维护,轻松的测试,更快的错误修复是(非常愉快)应用SRP的结果。主要原因(如Robert C. Matin所说)是:
一堂课应该只有一个改变的理由。
换句话说,SRP提出了变更地点。
SRP还促进DRY代码。只要我们的班级只负责一项工作,我们就可以选择在需要的任何地方使用它们。如果我们的班级有两个职责,但我们只需要其中一个职责,而第二个职责就是干预,那么我们有两个选择:
创建代码来解决特定问题很容易。创建更正该问题的代码,同时允许以后进行安全更改的代码更加复杂。SOLID提供了一组使代码更好的实践。
关于哪一个是正确的:全部三个。这些都是使用单一职责的好处,也是您应该使用它的原因。
关于它们的含义:
请尝试遵循该原理一段时间来创建代码,然后稍后重新访问该代码以进行一些更改。您将看到它提供的巨大优势。
您对每个班级都做同样的事情,最后得到更多班级,所有班级都符合SRP。从连接的角度来看,它使结构更加复杂,但是每个类的简单性证明了这一点。
我认为,以下论点支持“单一责任原则”是一种良好做法的主张。我还提供了指向更多文献的链接,在这些文献中您可以阅读甚至更详细的论据-并且比我的论断更雄辩:
更好的维护:理想情况下,每当必须更改系统功能时,都将只有一个类需要更改。类和职责之间的明确映射意味着项目中涉及的任何开发人员都可以识别出这是哪个类。(如@MaciejChałapuk所指出的,请参见Robert C. Martin,“清洁代码”。)
更简单的测试:理想情况下,类应具有尽可能少的公共接口,并且测试应仅针对该公共接口。如果由于类的许多部分是私有的而无法进行清晰的测试,则这明确表明您的类承担了太多的责任,因此您应该将其拆分为较小的子类。请注意,这也适用于没有“公共”或“私人”班级成员的语言;具有小的公共接口意味着对于客户端代码而言,很清楚应该使用该类的哪一部分。(有关更多详细信息,请参见Kent Beck,“测试驱动开发”。)
健壮的代码:您的代码不会因为编写得当而经常失败。但是,作为所有代码,其最终目标不是与机器通信,而是与其他开发人员通信(请参见Kent Beck,“实现模式”,第1章。)清晰的代码库更易于推论,因此将引入更少的错误。 ,在发现错误和修复错误之间将花费更少的时间。
原因有很多,但是我喜欢的一个原因是许多早期UNIX程序使用的方法:做好一件事。一件事情很难做到,而尝试做更多的事情就变得越来越困难。
另一个原因是限制和控制副作用。我喜欢组合式咖啡壶开门器。不幸的是,当我有访客时,咖啡通常会溢出。前几天煮咖啡后,我忘了关门,有人偷了。
从心理角度来看,您一次只能跟踪几件事。一般估计是七个正负两个。如果一个班级做了很多事情,您需要一次跟踪所有这些。这会降低您跟踪自己正在做的事情的能力。如果一个班级要做三件事,而您只想要其中的三件事,那么您可能会在实际对班级做任何事情之前就用尽能力来跟踪事情。
进行多项操作会增加代码的复杂性。除了最简单的代码,复杂性的增加还增加了发生错误的可能性。从这个角度出发,您希望类尽可能简单。
测试一个做一件事的类要简单得多。您不必验证每次测试该类所做的第二件事是否发生。您也不必修复损坏的条件并在其中一项测试失败时重新测试。
我遵循以下想法:1 Class = 1 Job
。
使用生理学类比:运动(神经系统),呼吸(肺),消化(胃),嗅觉(观察)等。这些控制器中的每一个都有一个子集,但无论它们是否要管理,它们都只有一个职责它们各自子系统的工作方式或它们是否是端点子系统并且仅执行一项任务,例如抬起手指或生长毛囊。
不要混淆它可能充当经理而不是工人的事实。当一些工人执行的工作变得过于复杂以至于一个流程无法自行处理时,他们最终会被提升为经理。
我经历过的最复杂的部分是,知道何时指定一个班级为操作员,主管或经理程序。无论如何,您需要观察并表示其功能以承担1种责任(操作员,主管或经理)。
当一个类/对象执行多个上述类型角色时,您会发现整个过程将开始出现性能问题或过程瓶颈。
Lung
类来处理,我也会假设Person
仍然应该有一个实例Breathe
,因此Person
该类应包含足够的逻辑以至少委派与该方法相关的责任。我进一步建议,与具有多个独立访问点的林相比,只有通过共同所有者才能访问的互连实体林通常更容易推理。
Person
类的职责是委派与一个极其复杂的“现实世界”实体相关的所有功能,包括其各个部分的关联。让一个实体执行500件事是很丑陋的,但是如果这是要模拟的现实世界系统的工作方式,那么拥有一个可以委派500个功能同时保留一个身份的类可能比必须处理所有不相交的部分要好。
Person
但仍会在成功/失败方面报告整个过程,但不一定会影响其他过程。500种功能(尽管以示例为例,但会有些过时且不被支持),我试图保持这种类型的功能派生和模块化。
Fred.vision.lookAt(George)
是有道理的,但是允许代码说起来someEyes = Fred.vision; someTubes = Fred.digestion
似乎很棘手,因为它掩盖了someEyes
和之间的关系someTubes
。)
我个人尤其希望采用“单一责任”这一重要原则,而人们采纳这一原则有很多原因。
其中一些原因可能是:
另请注意,SRP附带了SOLID原理包。遵守SRP而忽略其余部分与不进行SRP一样糟糕。因此,您不应单独评估SRP,而应在所有SOLID原则的背景下进行评估。
... test is not affected by other responsibilities the class has
,请您详细说明一下吗?
理解这些原则的重要性的最好方法是有需要。
当我还是一名新手程序员时,我并没有对设计进行太多思考,实际上,我什至不知道设计模式是否存在。随着我的程序的发展,改变一件事意味着改变许多其他事情。很难发现错误,代码庞大且重复。没有太多的对象层次结构,到处都是东西。 添加新的东西或删除旧的东西会在程序的其他部分带来错误。去搞清楚。
在小型项目中,这可能并不重要,但是在大型项目中,情况可能会非常糟糕。后来,当我遇到设计模式的概念时,我对自己说:“哦,是的,这样做会使事情变得容易得多”。
在需求出现之前,您真的无法理解设计模式的重要性。我尊重这些模式,因为根据经验我可以说它们使代码维护变得容易并且代码健壮。
但是,就像您一样,我仍然对“简单测试”不确定,因为我还不需要进行单元测试。