如果您听其他语言社区(例如Python或Ruby),则Java开发人员似乎倾向于过度设计。
也许他们只是嫉妒我们的高级平台( wink ),也许他们有一些很小的理由相信。 我相信。 我通过进行代码审查意识到了这一点,这很有趣,尽管我可能会在编写代码时过度设计自己。 但是我正在努力。
当然,您是一个“ 简单 ”的开发人员,只有架构师才有设计能力,所以只有他们才有可能过度设计,不是吗? 恐怕并非如此:开发人员一直都在这样做。 在本文中,我将重点介绍我在评论中评论过很多的一种症状,但是可以将其扩展到许多其他症状。
在我职业生涯的早期,我就被教导要设计我的班级层次结构,使其尽可能地可扩展。 它转换为由具体类实现的父接口。 有时,它们之间甚至可能有一个抽象类。 如下图所示:
![类图](https://i-blog.csdnimg.cn/blog_migrate/69d8675010f799e62c031f1b0c1dc0a3.png)
例如,Spring框架在其整个软件包中都大量使用此设计。 一个很好的例子是ViewResolver接口,该接口具有丰富的子层次结构和许多不同的实现类, 例如 InternalResourceViewResolver
和VelocityLayoutViewResolver
等。 在框架的不同部分中还存在其他示例(bean注册表,上下文等)。
但是,请注意有关Spring的重要事实:
- 在结构化的层次结构中组织了许多不同的子类
- 这是一个框架 ,它的意思是可以扩展,但可以定义修改
回到我们当前的项目,让我们说一个常规的Web应用程序。 找到定义的接口之一。 从这一点来看,找到其子实现很容易。 在大多数情况下,只有一个,并且以Default
为前缀(或者以Impl
作为后缀)。 同样,在大多数情况下,该接口位于xyz
包中,而实现位于xyzimpl
。 人们可能会对这种完全缺乏想象力的东西感到好奇。 嗯,很难为实现提供一个相关的名称,因为它和接口之间没有语义上的区别 , 即前者没有专门化后者。 唯一可能的结论是该接口不是必需的...
一些架构师可能会争辩说,即使现在没用了,抽象也可能在以后有用。 但是, 仅由于在将来可能变得有用而添加不必要的代码, 只会降低代码库的信噪比-毫无理由地妨碍可读性。 此外,需要创建,测试和维护此额外的代码,因此增加了成本和浪费。 这也与“足够”实现目标的敏捷方法相反。 最后,如果(且仅当)需要出现时,只需更改应用程序的代码即可很容易地引入父接口。 这很容易,这要归功于任何值得称赞的IDE的重构功能。
如果有人故意设计上述方法以为假设的未来做准备,那么我将上述方法视为过度工程;而如果仅仅因为它总是这样进行,则将其视为“ 货运崇拜” 。
无用的接口只是过度工程的一个简单示例。 还有更多。 我很高兴阅读您发现的(或练习过的)那些。
翻译自: https://blog.frankel.ch/are-you-guilty-of-overengineering/