什么时候课程太大或太小?

时间:2010-07-21 20:19:04

标签: oop

我最近在公司的一位高级开发人员审核了我的代码。他批评我的设计使用了太多的课程。我很想听听你的反应。

我的任务是创建一个服务,该服务生成一个xml文件,因为它操作了3个其他xml文件。我们将这些 aaa.xml bbb.xml ccc.xml 命名为。该服务分两个阶段进行。在第一阶段,它会针对 bbb.xml 清除 aaa.xml 。在第二阶段,它将第一阶段的产品与 ccc.xml 合并,以产生最终结果。

我选择了一个包含三个类的设计:一个XmlService类,它使用了另外两个类,一个scrubber类和一个merger类。我保持擦洗和合并类是分开的,因为这两个类都很大并且具有不同的逻辑。

我认为我的方法很好,因为它让我的课程变得小而有凝聚力。我的方法也有助于控制我的测试类的大小。

高级开发人员声称,清理和合并类只能由XmlService类使用,因此应该是它的一部分。他觉得这会使XMLService具有凝聚力,这就是他所说的具有凝聚力的意思。他还认为以这种方式分手,会使他们松散凝聚力。

具有讽刺意味的是,我试图打破这些课程以达到凝聚力。你怎么看?谁对或错?我们都对吗?谢谢你的建议。

6 个答案:

答案 0 :(得分:13)

如果您按照single responsibility principle(根据问题的基调,我认为您确实遵循它),那么答案很明确:

  1. 当一个班级做不止一件事时,它太大了;和
  2. 当一个课程无法达到目的时,它就太小了。
  3. 这是非常广泛而且确实是主观的 - 因此与你的同事的斗争。在你这边,你可以争辩说:

    • 创建其他类绝对没有问题 - 这是一个非问题,编译方式和运行时方式。
    • 该服务的当前实现可能会建议这些类“属于”它,但可能会发生变化。
    • 您可以单独测试每个功能。
    • 您可以应用依赖注入。
    • 您可以减轻理解服务内部工作的认知负担,因为它的代码更小,组织更好。

    此外,我认为你的老板对凝聚力有误解。将其视为焦点:程序的焦点越窄,凝聚力越高。如果卫星类中的代码在服务类中合并,则后者变得不那么集中(不那么有凝聚力)。人们普遍认为,较高的内聚力优于较低的内聚力。试着启发他/她对此的看法。

答案 1 :(得分:8)

Cohesion衡量代码体内功能的相关程度。也就是说,如果合并和擦洗没有很强的相关性,包括它们在同一个类中都会降低凝聚力。

Single Responsibility Principle在这里也值得一提。创建一个仅用于擦洗的类,另一个用于合并的目的遵循这个原则。

我说你的方法比两者更好。

答案 2 :(得分:2)

你会把这些课命名为什么? ScrubXmlMergeXml是很好的名字。 ProcessXMLScrubAndMergeXml不是,第一个太笼统,第二个有连词。只要没有一个类完全依赖于一个或另一个的内部(即低耦合),那么你就有了很好的设计。

名称在确定凝聚力方面非常有用。一个有凝聚力的模块做一件事,因此有一个简单的特定名称。一个不止一件事的模块缺乏凝聚力,需要更通用或更复杂的名称。

如果X仅使用Y,则将X中的功能合并到Y中的一个问题是还原广告:如果您的调用图是非循环的,那么您将在一个类中完成所有功能。

答案 3 :(得分:2)

作为一个从GodClass建筑节目中退回多年的人,现在正努力避免将来的错误;使用单个类制作6000到10000行单源单元的错误,超过250种方法,200个数据字段,以及超过100行的一些方法,单一责任原则看起来像是值得防范未开明的主管的偏好。

但是,如果您的主管和您在2000行代码属于一个类别还是三个类别的问题上存在分歧,那么我认为您比我更接近理智。也许这是规模和观点的问题。一些面向对象的编程爱好者喜欢每个类别的某个“独立系数”,直接违反了关于如何提高内聚力和最小化耦合的普遍理解的想法。

一组能够很好地协同工作的3个类,客观上是一个面向对象的系统,而不是单个类做同样的事情。有人可能会争辩说,如果你只使用一个类来编写应用程序,那么应用程序根本不是面向对象的。

答案 4 :(得分:1)

如果擦除器和合并在主类的上下文之外没有意义,那么我同意您的审阅者,特别是如果您必须公开任何实现细节以允许这种分离。如果您使用的语言支持嵌套的私有类或类似的东西,那么这可能是维护逻辑分离的合理替代方法,而不会将实现细节暴露给主类的外部使用者。

答案 5 :(得分:0)

这是一个非常主观的领域,根据编码和样式指南以及批准您的代码的人而有所不同。

那就是说,如果你的设计辩护没有成功,而你的高级团队成员仍然坚持要合并你的课程,那么你必须妥协:

你已经把逻辑分开了。编写一个服务类并保持方法与其他好的设计分开,然后编写一个粘合方法。在每个方法上方添加一些注释,说明如果将来需要,可以轻松地将它们分区为多个类。