在“现实世界”中使用单一责任原则

时间:2009-01-28 18:05:42

标签: oop solid-principles single-responsibility-principle

我基本上想知道在实际代码中使用单一责任原则实际做了多少人的百分比。在Podcast #38乔尔谈到这个OOP原则是如何无用的真实世界;而这进一步证明了像鲍勃叔叔这样的人可能没有写过非平凡的系统。

我个人在一些软件项目中亲自撰写或发挥了重要作用,但在我年轻的职业生涯中才刚刚遇到这种模式。我喜欢这个原则的声音,并且真的想开始使用它。我发现Joel在播客中的论点相当薄弱(如果你继续阅读博客评论here)也是如此。但是,它有什么道理吗?

社区的想法是什么?

9 个答案:

答案 0 :(得分:25)

我有一些应用SOLID原则的经验,我的经验主要是好的。我也听过播客,听起来杰夫和乔尔都没有尝试过他们谈论的任何事情,足以真正评估好处。反对的主要论点通常是“你编写更多代码”。如果我看看我做了什么,我会编写10个或多20%的代码(通常是接口定义),但因为所有内容都是高度分离的,所以它更易于维护。我的应用程序的某个部分的更改几乎没有破坏其他部分的情况。所以我必须保持20%的额外代码才能收回成本。

杰夫也错过了关于代码质量的观点。他并不认为代码质量对客户来说是一个巨大的好处。而他是对的,客户并不在乎。客户确实关心快速实现新功能以及代码质量的来源。我发现保持代码质量尽可能高的投资总能在几个月内收回成本。高品质=低维护。

我同意他们的观点,就像你必须对这些事情务实一样。如果你需要提供一些东西,那就继续快速而又脏。但事后要清理干净。

答案 1 :(得分:8)

我正在开发一个项目,在一个应该可以被其他人轻松扩展的框架中执行许多不同的,非常复杂的事情。

起初,课程很大并​​且做了很多事情。为了改变这些行为,你必须扩展这些类。这些方法都是虚拟的,并没有改变对象的状态,所以很容易做到这一点。

但是随着系统的发展,更加清晰的是框架最终将会出现一系列整体对象,每个对象都有一些looooong继承链。这也导致了意外的依赖关系 - 一个抽象的方法,它采用类X的集合来生成在基类中定义的对象Y,并指示EVERYBODY必须这样做,即使它对继承树的一半没有任何意义。这也导致大量的类需要数十次单元测试才能使代码覆盖率超过80%,并且复杂性使得您不确定是否正确覆盖了所有内容。很明显,这种设计会导致框架变得非常僵硬和不灵活。

因此,我们重新设计了SRP线路上的所有内容。你有你的接口,基类,可能还有一个或多个实现类。每个人都是组成的不同对象,它们执行整个过程的关键功能。如果您想要更改一个部分,则不会覆盖方法,您将生成另一个扩展必需的接口/基类并以不同方式执行其作业的对象。 SRP甚至被归入参数并返回类方法的值。对于需要灵活的系统部分,而不是传递用于生成Y对象的X类集合,创建了一个类来封装Y对象的生成过程。然后,系统中的组件将通过这些生产者,将它们与其他生产者(生产者的责任)结合起来,并最终使用它们来生成Y.这允许创建不同类型的生产者,所有这些生产者都可以完全处理同样,即使他们做了截然不同的事情。此举还大大减少了每个类的代码库,使其更容易测试。

我想说,作为一名新开发者,将一切都打破到这个水平是非常难的。你几乎不得不写一个大泥球,了解它是如何工作的,然后将它重新设计为几个不同的组件,每个组件都负责整体的一部分。

答案 2 :(得分:4)

我没有阅读或听过Joel的评论,所以不能对这些评论进行评论。

我认为你必须从目标而不是严格要求的角度来看待单一责任原则。与软件开发中的许多事情一样,有理想应该努力,但除非您的代码没有金钱利益或成本,否则您必须务实地满足客户的需求。

答案 3 :(得分:4)

在实践中,在OO情况下很难获得真正的SRP。考虑一个复杂系统中存在的类。它可能只有一个面向业务的职责(例如打印报告),但它在内部会有许多违反纯SRP理念的其他职责,例如日志记录和异常处理。如果您显着更改了日志记录机制,则可能需要更改打印类所进行的调用。

这就是为什么设想AOP的原因。使用它,您不必更改除日志记录类之外的任何内容以更改日志记录。

出于明显的原因,努力寻找面向业务的SRP是件好事,但对于足够复杂的系统,你永远不会在OOP中获得真正的SRP。 AOP,当然,但不是OOP。

我不知道这是不是Joel的推理,但这就是我接近这个想法的方式。

答案 4 :(得分:4)

一些大量编程理论的最大问题是,他们专注于建议代码中的良好属性,实际上是代码的良好属性。他们是对的,因为他们本质上是正确的,因此不是特别有用。

是的,代码应该写得很好,是的,事情不应该重复,是的,更改不应该导致意想不到的地方奇怪的中断。但是,在一天结束时,以简单,易于理解的方式表达解决方案的非常简单,非常一致的代码远远超过满足一些严格原则的大型复杂系统。作为一个行业,我们倾向于采取过于好的想法,在寻求“正确”解决方案时创造大量不必要的复杂性,而不是最好的解决方案。

保罗。

答案 5 :(得分:1)

我认为成为一名训练有素的OO开发人员并尽可能地遵守SRP的最大好处是易于测试和维护,所以我认为SRP是任何将要测试/维护的系统的一个很好的目标(基本上,除了一次性系统以外的任何事情。)

答案 6 :(得分:1)

我认为SOLID原则有时不符合设计类时通常应用的自然/业务逻辑。罗伯特C.马丁提出了一个Rectange和Square类的例子(Square不应该是Rectangle的后代)。

http://www.hanselminutes.com/default.aspx?showID=163

我不确定它是关于SRP的,但这个想法是一样的。 SOLID原则可能导致违反直觉的决定,并且很难通过这个障碍。

对我而言,“指南”比“原则”更合适。

答案 7 :(得分:0)

总的来说,我同意SOLID原则,但您也必须将它们纳入背景。如果您正在编写概念证明,则SOLID原则不太适用。

另一方面,如果您正在开发寿命长达数年的产品,那么您最好仔细查看SOLID原则并应用它们。否则,这将使公司在生产力方面花费大量资金。

关于乔尔和他的评论,他有一个有效的观点。有时产品需要发货或公司发生故障。就是那样子。

作为开发人员,您的工作是运送产品,但仅仅因为时间紧迫并不意味着您选择了糟糕的架构。您使用数据集或业务实体的选择是一个简单的决定,并且都有类似的实施工作,但从长远来看,两者之间的新功能开发和维护是极其重要的。

答案 8 :(得分:0)

我认为应该可以为所有类写一个简单的单行主要责任。这个单行中的“和”这个词通常不是一个好兆头。然后,单一责任通常归结为选择适当的抽象。

类附近的GUI倾向于反映GUI,并且单独负责“成为XXXX的gui”。考沃德的解决方案......