当前位置: 首页 > news >正文

烂代码传奇

现在你们管叫我烂代码, 实在是委屈我了,想当年我年轻的时候,那可真是人见人爱,花见花开,气质高贵,身段优雅,无数程序员对我着迷。 那个时候你们叫我什么来着?  好像是优雅代码、漂亮代码吧。

 

但是请注意,虽然被你们称为烂代码,我可是一直在生产环境上运行的代码啊,支持起成千上万的并发访问和计算,所以准确点儿说,我叫遗留代码

 

我为什么会变成这样, 你们程序员负有不可推卸的责任,如果你看看我的版本管理历史,对,就是2010年以前, 还能看到年轻而漂亮的我。但也是从那个时候开始, 多变的需求、进度的压力、人员的素质、混乱的管理, 让我慢慢走向了这条不归路。

 

我清楚的记得那一天,一个叫小董的程序员奉命开发一个新功能, 要对我这一块代码进行改动, 当时有两个方案,一个是对我重构,继续保持优雅的身段,但是工作量比较大。

 

另外一个是就地修改,只需要寥寥几行代码即可,代价是需要加上我极为讨厌的类似 if(p instanceof XXX) {......}这样的代码, 在进度的压力下, 小董为了少加班, 没有顶住魔鬼的诱惑,不假思索地选择了后一种方案。

 

我本来想抗议一下, 但是看着他睡眼惺忪的眼睛, 想到他昨晚加班到凌晨3点才睡, 心就软了。

 

体谅一下码农,忍了吧, 不就多了一个看起来非常丑陋的if 分支吗?

 

小董的代码被传到了组长那里做Code Review,  曾经要求非常严格的组长这时候忙得四脚朝天,根本没时间细看,这段丑陋的代码作为漏网之鱼,轻松进入了版本管理系统的代码仓库。

 

心太软的后果很严重, 这个丑陋的if 分支如同我漂亮面孔上的一道伤疤, 开了一个恶劣的先例,时刻在诱惑着程序员们: 大家都不用有心理负担了, 以后想怎么改就怎么改,反正已经开始腐化掉了!

 

三天以后, 张大胖毫不留情的在这里补了一刀,又是一个丑陋的特殊判断! 不过张大胖还算良心,写了“长达”10个字的注释,努力地辩解代码的意图,实际上我内心非常清楚,这10个字完全词不达意,把人带沟里的可能是99%。

 

一周以后,项目进度依然落后, 经理招了一大批新人入职, 终极“杀人王”小李出现了! 

 

小李是个典型地使用面向对象语言写面向过程代码的年轻人, 刚进团队的时候,他还纳闷说这个项目的代码怎么和自己见到的、自己写的不一样呢?  这里的代码读起来怎么这么难理解 ?

 

其实他不知道,面向对象的代码由于是针对接口编程,  每当你去找接口实现的时候是比较费劲的, 比起直接的面向过程代码, 读起来是个不小的阻碍。

 

然后小李便发现了被改得面目全非的我, 熟悉的配方,熟悉的味道, 他欣喜若狂, 举着一把杀猪刀, 在我这里大砍大杀, 我疼得昏倒在地,在被编译器唤醒以后,看到这数不清的伤疤,我吐血三升,再次晕倒。

 

拖着伤痕累累的身体,我和伙伴们又进入编译器, 让它把我们编译成二进制代码,这些二进制代码长得都差不多,也无法看出曾经的丑陋伤疤, 他们乐呵呵的奔向生产系统。

 

编译器看到我们的疑惑,解释说: “你们这些源代码主要是给人看的,所以很在乎自己的外表, 但是二进制代码是让机器执行的,都是指令而已,根本不关心长得如何, 能执行就行。”

 

我心里一阵羡慕:二进制代码的生活真好,单纯而快乐。

 

一年以后,这个系统的源代码已经变得凌乱不堪,极难维护了。 有一回高层领导震怒了:  为什么新加一个小小的功能,你们这里都得改一个月?   客户可等不及啊, 加班!

 

可是加班也不行, 代码太难懂了,这简直就是一片黑暗丛林, 程序员通常是有去无回。

 

领导又说了,你们的瀑布开发流程有问题, 现在敏捷软件开发很有效,赶紧转型敏捷。

 

于是敏捷教练来了,看到我们这些烂代码,不由的露出了得意的笑容: “看看, 和我之前估计的一模一样吧,这么烂的代码你们还想迅速响应市场变化? 一定得重构啊 ”

 

可是没有人敢重构我们这些遗留代码,张大胖说:“不是不想重构,是不敢啊, 这代码牵一发而动全身, 万一该改错了怎么办?”

 

教练说: “想重构必须得有测试, 你们得先写测试用例!”

 

那就写吧, 在教练的指导下,开始轰轰烈烈的单元测试运动, 可是刚推进没多久就被迫停止了,因为我们这些遗留代码很难写测试, 我们经常依赖数据库,网络,文件系统的数据,按照单元测试的做法,需要把他们用Mock技术给模拟出来, 但是想Mock的话代码中也得有“接缝”才行。

 

(码农翻身注: 接缝的概念来自于《修改代码的艺术》, 指的是是指程序中的一些特殊的点,在这些点上你无需做任何修改就可以达到改动程序行为的目的, Mock 代码通常可以在这里安插)

 

但是我们这些“烂代码”中哪里有“接缝”?   为了提供接缝,就必须在没有测试保护的情况下对遗留代码进行修改, 这就回到了原始的问题, 张大胖他们不敢改啊。

 

敏捷教练说张大胖你们得有勇气做啊,张大胖说你真是站着说话不腰疼,万一改错了你又不承担责任都是我们的锅我们必须来背你拍拍屁股就走了.....

 

教练无语,真的走了。 有人提议重新写, 但是也被否决, 原因是业务这么复杂,重写怎么能考虑到这么多细节, 重写出来的代码Bug 会更多!

 

于是只好保持现状,三年过去了, 开发人员都换了一茬,能够透彻理解系统的人几乎没有了。

 

经历了这么多事,我也就破罐子破摔了,完全不再在意自己的相貌。

 

有些时候,程序员为了理解代码逻辑, 翻起了代码的早期版本,惊叹于当时的优雅代码,我也就有机会跟着自我陶醉一下,仅此而已了。 

 

你看到的只是冰山一角, 更多精彩文章,请移步《码农翻身文章精华》

 

有心得想和大家分享? 欢迎投稿 ! 我的联系方式:微信:liuxinlehan  QQ: 3340792577

 

 

 

码农翻身

用故事讲述技术本质

微信号:coderising

相关文章:

  • Docker的安装和测试
  • React-Native - 收藏集 - 掘金
  • java基础-数组的折半查找原理
  • Ubuntu设置屏幕分辨率
  • Python 入门学习 -----变量及基础类型(元组,列表,字典,集合)
  • PowerDesigner16的使用
  • linux 下的动态库制作 以及在python 中如何调用 c 函数库
  • Asp.Net 用户验证(自定义IPrincipal和IIdentity)
  • mybatis标签之——trim
  • 【laravel5.4】 Composer移除依赖
  • IP-MAC绑定后,能禁止私接路由和随身WIFI吗?
  • c:关于 #include
  • 关于oraclize使用最好的一篇文章
  • BGP的各种属性
  • java基础
  • (三)从jvm层面了解线程的启动和停止
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • github指令
  • JavaScript设计模式系列一:工厂模式
  • java概述
  • Just for fun——迅速写完快速排序
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • TypeScript实现数据结构(一)栈,队列,链表
  • XForms - 更强大的Form
  • yii2中session跨域名的问题
  • 半理解系列--Promise的进化史
  • 将回调地狱按在地上摩擦的Promise
  • 前端面试之闭包
  • 微信小程序实战练习(仿五洲到家微信版)
  • 新版博客前端前瞻
  • zabbix3.2监控linux磁盘IO
  • 积累各种好的链接
  • 整理一些计算机基础知识!
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #1014 : Trie树
  • $.proxy和$.extend
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (编译到47%失败)to be deleted
  • (层次遍历)104. 二叉树的最大深度
  • (第27天)Oracle 数据泵转换分区表
  • (二)PySpark3:SparkSQL编程
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (四) Graphivz 颜色选择
  • (一) storm的集群安装与配置
  • .htaccess配置重写url引擎
  • .Net - 类的介绍
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .Net IOC框架入门之一 Unity
  • .NET MVC之AOP
  • .Net面试题4
  • .NET与 java通用的3DES加密解密方法
  • [Firefly-Linux] RK3568 pca9555芯片驱动详解
  • [hive] 窗口函数 ROW_NUMBER()