1000层死亡:Java过度抽象的危险(2017)

2020-12-14 22:00:20

Sun Microsystems的逃学人员认识到良好的面向对象代码可以更好地伸缩,因此指出Java中的任何内容都不应漫游大厅或在购物中心里闲逛,而应该封闭在教室中。方法代替了功能。字段替换了全局变量。 Java将面向对象提升为一种恋物癖。

不幸的是,Java的结构吸引了粗心的程序员过度抽象。在要求所有内容都使用一个类与在编译时强制使用所有类型之间,它鼓励您在类和接口声明中逐层放下形式主义。

您会被诱惑,甚至疲惫不堪,以为结果可口可笑,有序有序,适应能力强。每个新的抽象层都是一种资产,这是未来的枢纽,您可以在该枢纽上使用您的代码。您大概会想像,将任何一门课程变成两门课程,总有一天会以更好的可重用性或更少的错误获得回报。将您的字段常规地隐藏在getter和setter后面,将为您提供自由度,以便将来将其更改。

但是,按照这些设计原则,您会遇到麻烦。如果您从未遇到自己不喜欢的抽象,随着时间的流逝,您的逻辑将被细化成细小的类和方法的薄雾,而这些类和方法中的任何一个都不单独做任何事情。您将发现无法遵循的代码。对其进行调试甚至是通读都涉及一次又一次地上下推15个堆栈帧,试图理解逻辑,直到头晕可以克服并且忘记了为什么开始。只有经验丰富的项目专家才能真正理解所有内容如何组合在一起。

人们要求的新功能似乎从未与您的代码中的各层保持一致。

您不仅可以将这种实现换成那个实现,还必须立即更改六个不同的模块,并修补一些不幸的外部依赖项。而且,尽管您已经准备好在眨眼之间重新实现employee.getEmployeeID(),但没人会要求这样做。

您的代码库将因难以使用且不受重构而赢得声誉,因为任何给定的类都像Lulputian依赖军一样固定在Gulliver上。您和您的队友将不得不触摸它,而梦talk以求地谈论您似乎没有时间进行的“大重写”。

您今天患有千层综合症吗?还是表现出早期症状?看看你的代码。您是否通过筛选看到了2行和3行方法?保存数据但不拥有任何决策的类,例如C结构?与仅一种实现的接口?令人困惑的类名如何?如果您无法确定ParameterInfoBuilderWrapper应该做什么,或与ParameterInfoBuilder有何不同,则可能是您的疾病正在恶化。

但是不要担心。即使您的病情较重,您的病也可以治愈。

首先,忘记大重写。重写是一个冒险的秘诀,它可能花费比您想象的更长的时间,并使公司的其他部分同时成为您的人质。而且,如果当前版本增加了太多层次,那么除非您和您的团队首先掌握了更好的设计方法,否则下一个版本可能会执行相同的操作。因此,不要等到“大改写”,开始逐步改进代码和团队。

计算机先做这件事,然后再做那件事,然后再做其他事情。高级语言和面向对象的设计大张旗鼓和专心致志,从我们根本不起眼的工作中分心:选择if-then语句。

因此,过程逻辑应在代码中占据中心位置。好的Java应该类似于C。方法应该有一个清晰,平凡的工作,并且应该显示其工作。您应该能够从上至下阅读一种方法,并了解其工作原理,而无需研究其他20种方法的实现。

同样,一个班级应该有一些肉,并从事一些实际的工作。一个经过深思熟虑的类应该拥有一个有趣的决定以及做出该决定所需的数据,而不仅仅是一个或另一个。它应该易于命名,理想情况下是使用一个名词,该名词对应于具有生命周期的现实世界中的某物。如果您在努力想出一个区别于此类的名称,则可能是滚动了太多层。并且它应该具有可测试的表面。给班级一个有限的工作,独立于同级同学,并编写测试以确保做到这一点。

第三,开始锻炼程序。将食指向前方伸出,然后将其向下弯曲至Delete键,然后再将其抬起。优秀的。每次签到都要进行一次代表。将两个两行方法拼合为一个。找到一个要删除的小类。废除不必要的吸气剂和吸气剂。您不是维多利亚时代的女士,她的脚踝都遮住了她;加入那些摇摆不定的Pythonistas,让您的领域闲逛。

对每个接口和受保护的方法进行测试:“我们今天需要这种方法的多个实现吗?”如果您头脑中的声音恳求“但我们可能希望……”,请保持镇定,并用“极端编程”的歌声驱赶他们:“不需要。不需要。不需要。”通过使代码简短,清晰和经过良好测试来证明您的代码的未来,而不是赌博千里眼。

最后,招募您的同事,因为你们在一起。在代码审查中互相挑战。可以更清楚地命名此方法吗?这堂课代表什么很明显?该代码是否可用于今天的实际用例或明天的假设用例?明年夏天的实习生会立即理解这一惯例吗?

设计是一门艺术。您可以阅读本讲章中的建议,然后再读一本书,告诉您正好相反。重要的是要磨练自己的技艺。读那些书。实验。辩论。这项投资将不仅仅可以提高生产力,还可以逐步改进代码。在不知不觉中,您将拥有数千层,只有几层可以管理,您将享受不断提高的速度,并且在自豪的代码库中笑逐颜开。