如何维护混乱的代码
让你自己的生活变得更好,就像你之后的所有人一样
今天是星期一早上,你又坐回了你的办公桌前。摆在你面前的是系统的意大利面条代码,你没有建立,但被要求从现在开始维护。
最初的代码是由受训者写的,在当时打算离开的人的半指导下,他不再特别投入--否则,这东西就不会通过代码审查。
有重复的代码,不必要的注释,以及写好了但从未使用的类。变量的命名方式算是遵循了内部的编码准则。虽然我承认,这些准则可能是后来写的,直接参考了这个项目的缺陷。
由于今天是星期一早上,你可以有一定程度的身份危机,迅速陷入抑郁,然后喝上一杯急需的咖啡。然后,是时候离开这个系统了,比你找到它时更好,日复一日。
登录就像在一个寒冷的日子里洗一个热水澡
在你面前的系统大部分时间都在做它的事情,但它喜欢把它的底牌藏在胸前。它做了你要求的事情吗?它失败了吗?甚至成功了吗?谁他妈知道呢。
日志输出将极大地改善你与系统的交互方式,只需几行简单的console.WriteLine()--甚至在我们现在生活的未来世界中,也可以进行实际的日志记录。突然间,你得到了自动警报和监控,看到了运行时的统计数据,并且可以看到哪些函数花费了异常的时间--很可能是所有的函数。
根据逻辑的复杂性,你将能够更好地理解内部运作,可以立即看到在哪一点上数据被丢弃,出现错误,以及哪些步骤以可重复的模式不断失败。
与一个让你完全蒙在鼓里的系统相比,你只需知道在哪里为下一次运行设置断点,就可以节省几个小时的时间。
增量提交就像热天里的冷水澡
每当你与遗留软件打交道时,很有可能它们最初的设计是为有经验的焊工建立管道的工作。
这意味着如果进展顺利的话,每月都要发布一次。值得记住的是,最初的开发者有一半的时间都花在了合并变化、推出代码和修复错误的配置文件等的开销上。我的年纪大了,记得很清楚。
在我的第一家公司引入适当的DevOps工作流程和工具之前,我就已经是一名学徒了--我不能夸张地说,这为我们这些地面上的士兵节省了大量的时间。
毫不夸张地说,光是让工作代码在任何系统或服务器上运行就花了每个人百分之三十的时间,还有许多针对生产运行测试案例的近乎死亡的经历,或者让用户对测试数据库进行生产修改。我甚至不能说哪种情况更糟糕,可能只是后者。
所以,每当你和一个这样设计的系统一起工作时,你很有可能不得不回滚你自己的改动,仅仅是因为你认为你理解的代码毕竟是不同的。
通过渐进式的改变,你可以把曾经做得更差的事情做得更好,而且你会在第一时间感谢自己,因为这5分钟的开销为你节省了一两个小时和额外的白头发。
无情的重构就像洗澡的时间
你是否曾经在浴缸里蒸了一个小时,而显然半个小时就够了?冒着泡沫的肥皂水所能达到的任何清洁效果,在最初的几分钟内就能做到。最糟糕的是:在清洁方面,淋浴也能达到同样的效果。然而,这几乎感觉不到是在浪费时间。
让我这样说吧。我几乎不洗澡,但我不会搬进一个没有浴缸的房子。
当你花时间进行适当的重构和深度清洁时,遗留的代码也会有同样的感觉。
如果你在C#中工作并使用ReSharper,你常常可以在几分钟内将一个类的复杂性降低一半。但即使不这样做,你也可以通过以下方式来改善代码。
- 将复杂的嵌套for循环分解成更简洁的LINQ语句。这只是C#,但在LINQ之前,曾经有过一段时期,那是一个黑暗的时期。很多时候,你甚至无法判断一个嵌套循环的目的,然后你会意识到它本可以成为一个单行的。
- 扔掉所有的注释。它们是绿色的、丑陋的,而且时代已经发展到不需要写注释了。
- 把那些长长的单功能类,以及较小部分的方法提取到它们自己的、命名的函数中。这可能是我在ReSharper中最喜欢的函数,因为它让这一切变得如此简单,只需按下一个按钮,就能带来参数和其他东西。很抱歉听起来像个广告,这个函数为我节省了很多时间。
- 修复所有变量名称没有遵循合理的命名模式的情况,循环变量只是x和y,以及类似的小事情。这些都会对以后的工作产生巨大的影响,而且不需要花费太多的时间来解决。
在一行中重写过去需要50年的内容,就像拿出高压清洗机一样。
我现在正搬进一个老旧的房子,第一块石头是在1910年建成的。它很美,也很古怪,但甚至要经过大量的高压清洗才能让你看到所有东西的样子。我发现这张花园棚子的照片很适合遗留代码的样子。
这就是当有人懒得敲几下钉子,而决定把沉重的轮子拖到屋顶上是劳动强度较低的选择时发生的事情。
你可以进入并立即将这一代码的复杂性减少一半,只是通过扔掉那些甚至不需要存在的东西。作为一个局外人,这很容易看到,但我确信这家伙做出这个特殊的选择是有道理的。
我之前已经提到了LINQ语句,但是还有像.Contains()之类的东西,通常可以取代复杂的字符拆分-数组-循环--是的,这些可恶的东西非常存在。
利用包管理器可以极大地提高可读性和可维护性
总是值得记住的是,就在十年前,包管理器还是一种新奇的概念。虽然不是到处都有,但在很多地方,很多工作流程在很小的时间范围内发生了相当大的变化。
如果你看到一长串的代码看起来很可疑,那么NuGet/Pip/NPM很可能为你准备了一些东西。
有一个潜在的缺点,就是你放弃了对你的代码的一些控制--但很多时候,这是很值得的。有人花了大量的时间来找出创建二维码或其他东西的最有效的方法--他们的结果可能是你在相同时间内所希望的两倍。这个或那个软件包有十万次下载是有原因的。
我曾经看过一个特定的系统,当其中大约百分之三十的部分看起来可以替换时,我挠了挠头。当然它不可能......是的,它可以。我们生活在一个伟大的时代,以导入语句为代价减少代码的复杂性,所以在适当的时候使用它。
经验之谈。混乱的代码最具有改进的潜力
你可以说我是个简单的人,但我喜欢大数字。如果有人告诉我他们把某个函数的运行时间提高了40%,我就会很兴奋。
也许这又和我搬进的房子一致,我对它的状态太兴奋了。我在花园里使用的第一个工具是我的电池电锯,没有其他方法可以穿过藤蔓。
现在,大部分重活都完成了,只剩下无聊的美容修复,我非常接近于对它感到厌烦,因为与早期阶段相比,改进很小。我昨天修复了一扇刮到地板的门,我还写了一行代码,替换了另外两扇门。