一个对象的类型太多

本文关键字:太多 类型 一个对象 | 更新日期: 2023-09-27 18:00:36

我意识到这个问题并不完全是一成不变的,但通常情况下,你如何知道一个对象的类型太多?

我目前正在支持一个项目,在这个项目中,我不熟悉基线,但我的任务是基本上进行错误修复,以减少SPR数据库中的项目数量。我不断遇到扩展许多不同接口的类,包括一个这样的类,它总共扩展了12个接口。许多其他延伸7或8。

现在我知道依赖接口而不是具体实现是一种很好的设计实践,但这是否太过分了?这是一种实际的代码气味,可能是糟糕设计的迹象,还是我只是反应过度,根据具体情况,一个类扩展七个、八个甚至十二个不同的接口是正常的?试图追踪实现12个接口的对象的实际具体类型是很累的。

一个对象的类型太多

为了能够证明代码的气味,你必须回答(用括号表示正确答案):

  • 所讨论的物体是否用于实现十二种不同的目的?是
  • 这些目的是否过于密切相关?否
  • 那个物体有没有从未使用过的海豚?否
  • 该对象是否有很少使用的目的,可以作为更通用目的的一部分?否
  • 是否存在根本不是目的而只是运行时使用的标记的目的?否

可能还有更多问题需要回答,请随时添加评论。

正如您所说,这不是一成不变的,但它绝对值得一看。我认为回答您的问题的最佳方法是用另一个问题:"每个类都有明确定义的目的和职责吗?"如果答案是肯定的,那么可能是设计很好,或者最坏的情况是,接口太细。

为了帮助解决搜索问题,有没有一个IDE可以加载代码来帮助可视化和导航继承树?

尽管细粒度的接口定义可能很难维护,但在我看来,我并不认为这是糟糕设计的标志。

通常,这种事情是动态、敏捷系统的一个特征。也就是说,它的功能是随着时间的推移而演变的。

此外,我认为这是一个标志,表明设计师正在以良好的OO方式进行思考。

这并不是说代码不能重构,一些接口定义不能合并,事实上,由于所有的接口定义,这项任务现在变得容易多了。想象一下,尝试以其他方式重构对象!

一个类可以扩展12个接口,但如果这12个契约表示行为的交集,使得对象仍然只有一个责任,那就是A-OK。一次又一次,在大型企业项目中,最难维护的部分是那些试图做太多不同事情的类。这里有一个例子:

一个为急救人员(警察、消防等)提供路线和建议的应用程序有一个类Mapping,它可以:

  • 地理编码和反向地理编码(将lat&long转换为地址,反之亦然)
  • 将地图图像绘制到屏幕上,并突出显示交通和路线
  • 查找不同位置之间的路线
  • 分析第三方数据源提供的流量模式

系统的最初设计者一定认为"好吧,这些都是与地图和位置相关的任务,所以是的,这应该是一个类"。不幸的是,这使得以后不可能更改其中一个功能,因为所有东西都是紧密耦合的。

在应用程序中的各种组件提供的功能中查找接缝。将这些接缝分离成组件之间的内聚契约(接口),每个单元都能够向其消费者提供有价值的"服务"(而不是Web服务意义上的服务)。回到我之前的例子,我们最终将Mapping类(Project Yoko)分解为:

  • Geocoder
  • 地图渲染器
  • RouteRenderer
  • RouteBuilder
  • TrafficRenderer(继承自RouteRenderer)
  • TrafficDatasource

单个组件具有运行时解析的依赖关系,这使我们能够引入单元和系统测试,在预先存在的路由逻辑中发现几个错误,此外还提供了许多其他好处。一般来说,如果你能在一个类中看到责任的逻辑分离,你可能应该将其分离

看看中的一些类。Net的System.Collections.Generic命名空间-其中许多支持7+接口。(从设计的角度来看)这不是什么值得担心的事情。类应该实现它想要实现的任何和所有接口。

因此,类应该实现的接口数量没有数字限制。唯一的问题是这些接口对类是否有意义。

正如Eric所指出的,最坏的情况是接口过于细粒度。听起来确实如此。从纯粹的设计角度来看,IMO与数据库过度规范化是一个问题。如果您能够设法整合许多接口,即使有些东西是冗余的,并且如果您能够在不损失可管理性的情况下这样做,那么您应该这样做。

我认为这在很大程度上取决于这些接口所涵盖的服务范围有多广。接口分离原则鼓励将大型接口拆分为较小的、高度内聚的接口,这些接口可能支持非常小的服务集。如果您正在处理的代码库中的接口是这种情况,并且这些接口在组合时创建了服务的逻辑分组,那么这可能不是什么大不了的事。如果接口很大,或者在分组时看起来不同,那么您正在处理潜在的有缺陷的设计。