编程感悟:为什么要重写代码?

码农的绝大部分工作精力是在维护代码上,至少在我所工作的部门是这样的。由此观点出发,码农界形成了如下共识:

代码首先是写给人看的。

这就要求码农们在编码时,可读性/可维护性要放在重要的位置进行考量,使用简单的设计,通用的方法,统一的风格。

每个码农心目中都有一个代码的伊甸园,在那里,代码的设计良好,实现优雅,赏心悦目。代码所要表达的意思很明晰,注释恰到好处,无需猜测就能理解编写者的意图。即使有Bug出现,通过检查代码就能容易找到错误处,无需复杂的调试过程。不再惧怕需求的增加和变化,因为代码有很好的可扩展性。

但实际上,绝大部分码农维护的代码,却是两外一番景象:代码质量惨不忍睹,错误百出,码农面对蜂拥而至的Bug和新需求,加班加点,疲于奔命。不得不承认,码农是追求完美的一个群体,码农们怀着激动的心情,按捺不住重写的冲动,在码农心中,重新实现一套系统,将极大的提高代码质量,消灭Bug。需求变更时,也不再惧怕,因为轻而易举就可修改和扩展,做到了拥抱变化。码农时不时的幻想,系统如果重写过,以后的维护工作是多么的幸福和美好。实际上,每一个码农都有、或至少有过这样的冲动,我们不得不深入思考一下其原因,重写真的能带来想象中的美好结局吗?

1,客观原因

经过前辈开发者们前仆后继呕心沥血的堆砌,摆在我们面前的代码库,就如同瓦力在末日世界执着搭建的垃圾大厦,表面上看非常整齐,仔细看去,就是一块块垃圾拼凑而成,代码库中充斥着烂代码。

代码质量

好的代码大致相同,烂的代码各式各样。随便举一些例子:

  • 设计复杂,或者干脆没有设计,无法理解
  • 耦合严重,各个模块、功能间相互交织,无法分离
  • 代码重复,逻辑重复严重的代码,遍地Ctrl+C、Ctrl+V的代码
  • 风格杂乱,前辈码农前仆后继,都留下自己独有的代码性格和印记
  • 废弃代码,有用,或者没用,代码就在那里,只增不减
  • 注释失效,过时的注释不是好注释,误导码农的注释是流氓注释

一般认为,代码质量差,是产品Bug频发的罪魁祸首。任何代码,无论质量高低,都隐藏着Bug,质量低的代码,尤为严重。

一旦出现Bug,码农的一般反应是:这不是我写的代码,这是老代码,一直就有问题。即使Bug是自己新引入的,也可以轻而易举的找出理由:“老代码太烂了,谁改都会出错”。没错,在码农眼中,代码库中的代码是如此之烂,以至于所有的问题,都可以归罪于老代码。

敏捷传说

需求是在不断变化的,码农们为此疲于奔命。有一种传说,叫做敏捷,据说可以解决这个问题。值得一提的是,目前我司的敏捷事业取得了可喜的成果。敏捷了,就不再惧怕Bug,因为有完备的测试,把Bug消灭在萌芽状态;敏捷了,就不再惧需求的变化,因为我们拥抱变化;敏捷了,就不再惧怕开发人员的变动,因为敏捷要求每个人都是全才,要掌握;敏捷了,我们不再惧怕烂代码,因为我们掌握了重构代码的神技。

敏捷是鼓励进行代码重构,提高代码质量的。敏捷倡导,代码应该拥抱变化,为了适应新的需求和变化,应不断的重构代码。敏捷认为:好的代码质量带来好的产品质量。这就鼓励码农进行代码测试和重构,代码测试给了码农信心,重构不用再担心和犹豫。

既然提到敏捷,多说点题外话。毫无疑问,敏捷实践是软件开发的最佳实践,但是把敏捷引入到管理流程中时,一定要万分小心。敏捷不是银弹,需要认清其本质,才能利用敏捷,提高开发效率,提高产品质量。而不是为敏捷所用,反而使得团队变得“不敏捷”。

2,主观原因

重写代码是码农内心萌生的欲望,是码农对优美代码的追求的正面体现。重写代码可能的动机有哪些呢?

  • 代码洁癖,代码整洁很重要,但是过犹不及
  • 优雅强迫症,设计要优雅,要抽象,为了适应未来的变化,可是未来在哪里?
  • 眼高手低,认为可以轻而易举的重写代码,把既有代码替换掉
  • 先苦后甜的心里预期,认为在一番努力之后,后续的维护工作将更加轻松
  • 内心泛滥的对后代码农的责任心,希望留下优秀的代码遗产,和一段传说

每个码农都有自己的代码审美观,爱美之心,人皆有之,码农希望能写出优雅的代码,维护优雅的代码,无可厚非,而且是应当鼓励的。

3,重写代码的阻力

但是代码重写这件事,至少在使用时间相对长的系统中,却鲜有发生。

(1)外部原因

领导的三个终极问题

领导和码农的相同点是,都关注代码的质量,不同点是,领导关注Bug的数量和严重程度等KPI指标,码农关心代码的好坏和优雅程度。码农认为愈优雅的代码,就带来愈高质量的产品,码农每每向领导游说,既有代码如何如何烂,重写之后如何如何能提高代码、产品的质量。领导总是很淡定,然后抛出三个终极问题:

  1. 会不会引入新问题?
  2. 对哪些功能有影响?有多大的影响?
  3. 工程上有多大的风险?

重写当然会引入新问题,当然会对现有功能有影响,影响有多大,码农深思许久,依然没有把握,只好郁郁而归。

这个原因,是绝大部分码农经常提起的,也是最为码农们愤慨的,仿佛没有了这个阻力,将是一片广阔的天空,可以尽情施展自己的才华。

玄机暗藏

那些年,前辈码农和Bug们决战光明顶,为了改好Bug,使出了浑身解数。在烂代码上改Bug,用更烂的方式去修改,是一种快速讨巧,深受领导喜爱的方式。因为,方法虽烂,但是很好的解决了当前问题。事实证明,使用烂上加烂的方式,解决了Bug,而没有引入新问题,没有影响到既有的功能,将工程的风险控制到最小,圆满的回答领导的三个终极问题。

每个改过无数Bug的码农,都素有谦卑之心,深藏功与名,不着痕迹,以至于后代码农看到一段让人惊讶无比的代码,却不知这里暗藏玄机,封印了系统的大Bug。代码也成了一个宝藏,富含前辈码农积累下来的宝贵财富,可是隐藏的太深,无数的淘金者都失败而归。这些隐藏的知识宝藏,逐渐的成为历史,慢慢的,历史成为传说,传说成为神话。

在冒冒失失乱改一通,载了跟头,被领导臭骂之后,我们这些后世码农,在审视和修改代码时,始终怀着敬畏之心。时常用身临其境的代入感,去感受前辈码农内心的纠结和矛盾,体会他们审时度势,不得不忍痛写出如此令人不解的代码时的复杂心情。于是我们处处谨慎,不敢随意改动,总是左思右想,谨防唤醒沉睡中的Bug Boss。

(2)内部原因

1984

工程风险、领导的要求,担心改出Bug,码农被重重包围,工作中每一步都慎之又慎,不敢越雷池半步。注意!老大哥一直在盯着你!

烂代码不但带来糟糕的产品质量,也带来大的代码变更成本,修改一句代码往往都意味着工程风险,领导的责骂,自身的惶恐。更严重的是,烂代码将一步步浸染开发者追求“美”的初心。为了熟悉业务,不得不顺着既有代码的思路;为了新增功能,不得不堆砌更多的烂代码;为了解决Bug,不得不浸泡在烂代码中,无法自拔。潜移默化是最厉害、最彻底的变化方式,不知不觉间,开发者找到了成本最低的工作方法:以烂代码的思考方式解决问题,堆砌更多的烂代码。

失去了“初心”的码农,一边在挣扎,一边继续沉沦,沉沦于“舒适区”。码农已经完全忘却了曾经拥有的“初心”,没有了挣扎,并在彻夜未眠终于解决一个故障后露出了欣慰的笑容。终于,码农没有了抱怨,他在享受。

代码江湖

代码就是江湖。码农是江湖中行走的剑客,剑客们心怀天下,行侠仗义、快意恩仇,梦想着有朝一日一统江湖。可是,江湖险恶,危机暗藏。初入江湖的新手剑客,学艺不精,却心比天高,不畏艰险。浪迹江湖多年的老道剑客,往往知道水深而不敢涉险,因为他们已渐渐读懂江湖。

新手剑客,让其路见不平,拔刀相助是一件很容易的事情;但是让其谦虚谨慎,静待时机却非易事。仗剑江湖比读懂江湖要来的容易,这是一个知难行易的典型例子,我们也喜欢这样的故事。码农何尝不是?新手码农路见Bug,便想祭出重写之剑,可是却不愿意去读懂既有代码。

可是,重写代码真的比读懂代码容易吗?新手剑客是否已经剑术精湛,内功深厚,认清了江湖,才能仗剑江湖。新手码农是否夯实了技能,深入理解了要解决的问题,无法驾驭既有代码,便不可能重写出理想的代码。

江湖老鸟老罗,在其Rom发布会开头的发问:“大家准备好了吗?”,我们要时常问自己:对于彻底革新整个系统或者模块,真的准备好了吗?

4,总结

面对阻力时,我们的注意力往往集中在外因上,码农经常抱怨的也是,如果领导同意,代码早已经重写,而不会造成现在的这样一个烂摊子。却往往忽视了自身的原因,码农往往宁愿躲在“舒适区”内哭泣,也不愿意折腾之后满足的笑。

重写代码的冲动是应当珍视的,没有推翻陈旧的勇气和行为,就没有大的进步。可是,我们是否就可以大胆的对代码进行重写呢?对系统/模块是否真正掌握了?如何获取隐藏的知识?敏捷是不是万能的良药?测试能带来多大程度的保证?

带着这些问题,我们还需要做进一步的思考。

posted @ 2013-05-06 22:04  风中散发  阅读(926)  评论(0编辑  收藏  举报