程序员之拍案惊奇:为什么我会一天到晚的想说FUCK!
经常有人找我给他们的软件项目做修改或维护,我对这些项目毫不了解,而他们只告诉一些很少的项目相关信息。必然的,需要在项目中增加一些新的功能,但在动手之前,我通常需要耗费大量的功夫来大幅度的重构它们。
JavaScript (Photo credit: Johannes_wl)
大概一个月前,一个公司老板给我来信“嗨,我有一个软件,需要做一些个性化的改动,有个大客户愿意花一大笔钱来买它,正等着呢,可我现在都没办法让它跑起来,最初的开发人员都找不到了。你能帮我搞定它吗?”
最初的程序员的逃离已经是亮起了红灯,但这个项目的技术架构正和我的胃口:node.js,mongodb,大量的事实数据流,以及 UI 上更新的速度要求。这个等待使用这个软件的用户的名字也让我精神一振。
我操!能坏到哪去?
你会忍不住的想骂街
能坏到不能再坏。
项目的一部分是用 Java 写成的。这很好,根据项目的现状,选用静态类型的语言是明智的选择。
而其余部分是用 Javascript 写的。Java 和服务器端 JavaScript 和前端 Javascript 通信的机制是…..哇塞,这有个限制,参数名长度不能超过 3 个字符。
好吧,节省带宽,不是吗?我们现在说的这个项目具有巨大的数据流量,所以就尽量让 json 对象保持最小体积吧。
这就是让事情变得棘手的地方。
因为核心传输协议里只让各种变量名长 3 个字符,所以数据库设计也遵照这个原则。因为数据库里的各种表名、字段名、视图名等等都是这个模样,你猜怎么着?没错!所有的程序代码都沿袭了变量名不超过 3 个字符的特征。
这个风俗的渗透超出了变量名进而感染了数据。
为什么在应该写成label地方偏要写成lbl呢?以及诸如此类,等等等等…..在差不多两个月的研究这个项目后,我仍然不知道大部分的变量名的真实含义。我只是把它们当作是拉丁语,用来描述一种模糊的概念。我开始对这个项目是如何运转的有了一些理解。
情况慢慢清晰起来。
如何让一个布尔值符合这种命名机制?这样做:
function fix (boolean_value) { return boolean_value ? 'tru' : 'fls'; }
这样能节省空间。把一个 1bit 的值编码成一个 24bit 的字符串!服了!
好吧,但愿事情到此为止,但我发现了另外一个有趣的东西…这个东西在很多代码里反复出现,我不敢动它们,我怕会发生什么不可思议的事,会让有些程序跑不起来。
我有没有跟你们说过这个项目是没有单元测试代码的?当发现需要给它们写单元测试时你知道我有多受打击吗?但是,好在这个项目看起来最终不需要通过一个安全测试….哦,等一下,程序里有安全检查代码。
if (!thing || thing === 'null') ...
好可爱,不是吗?肯定是因为 null 被编码成了字符串。你还能有其它办法吗?
起初我一直在宽慰自己说他们这样做一定有必要的原因。
不管怎样,我全忍受了,有些东西从某种角度看似乎是合理的,有些可能是过度优化造成的。很糟糕,但有些我还是可以忍受的。
下面的这个是让我真正抓狂的东西:
function getPurple (cake) { cake.color = global_color_setting; return cake; }
我甚至不知道如何入手去重构它,让它变得有实际作用…完全就是…什么玩意?谁干的!?
然而,这最糟糕的事情,最最糟糕的事情是,这个项目不知从何时起由传统的 jQuery 转向了 Backbone。这没任何的问题,迁移的很好,我喜欢 Backbone!
但他们忘了进行彻底的迁移。很多时候 Backbone 只是一个很薄的皮,包着旧的东西。大部分的代码甚至根本没有使用 Backbone,仍然使用大量的$.ajax,随处可见。
在这样一种弱类型化的语言、没有单元测试代码的情况下,我根本不可能说“嗨,我修改名称X,请把相关的所有引用都改一下”…用 grep 命令搜索,也只能这样了,我的这段日子过的太充实了。
不知道系统什么时候就会突然崩溃,因为我也忘了去测试…