代码能用即可,重构不是万能药

开发 前端
写烂代码很容易,但是就算写成一坨屎,能用即可, 你同意这种观点吗?

写烂代码很容易,但是就算写成一坨屎,能用即可, 你同意这种观点吗?

程序员刚入行经常听到一些观点

你要把精力放在需求文档/功能设计/架构设计/理解原理 (ABCD )上,写代码只是把想法翻译成编程语言而已,是一个没什么技术含量的事情。

当时的我在听到这种观点时会有一种近似于高冷的不屑: 你们就是一群傻子,根本不懂代码质量的重要性,这么下去迟早有一天会踩坑。

可是几个月之后,他们似乎也没怎么踩坑。而随着编程技术一直在不断发展,带来了更多的我以前认为是傻子的人加入到程序员这个行业中来。

语言越来越高级、封装越来越完善,各种技术都在帮助程序员提高生产代码的效率,依靠层层封装,程序员真的不需要了解一丁点技术细节,只要把需求里的内容逐行翻译出来就可以了。

很多程序员不知道要怎么组织代码、怎么提升运行效率、底层是基于什么原理,他们写出来的是在我心目中烂成一坨屎一样的代码。 但是那一坨屎一样代码竟然能正常工作。

[[434507]]

即使我认为他们写的代码是坨屎,但是从不接触代码的人的视角来看(比如说你的boss),代码编译过了,测试过了,上线运行了一个月都没出问题,你还想要奢求什么?

所以,即使不情愿,也必须承认,别人写的代码能正常运行,且不出错,那就是牛x。

烂代码终究是烂代码

但是偶尔有那么几次,写烂代码的人离职了之后,事情似乎又变得不一样了。

[[434508]]

想要修改功能时却发现程序里充斥着各种无法理解的逻辑、改完之后莫名其妙的bug一个接一个,接手这个项目的人开始漫无目的的加班,并且原本一个挺乐观开朗的人渐渐的开始喜欢问候别人祖宗了。

总结几类经常被骂娘的烂代码:

ி 意义不明

能力差的程序员容易写出意义不明的代码,他们不知道自己究竟在做什么。

就像这样:

  1. void Save(void
  2.   int x; 
  3.   for(x=0; x<100; x++) 
  4.   { 
  5.     //防止保存失败,保存100次 
  6.     Flash_Write(); 
  7.   } 

对于这类程序员,我一般建议他们转行。

ி 不说人话

不说人话是新手最经常出现的问题,直接的表现就是写了一段很简单的代码,其他人却看不懂。

比如下面这段:

很多程序员喜欢简单的东西: 简单的函数名、简单的变量名,代码里翻来覆去只用那么几个单词命名;能缩写就缩写、能省略就省略、能合并就合并。

这类人写出来的代码里充斥着各种g/s/gos/of/mss之类的全世界没人懂的缩写,或者一长串不知道在做什么的连续调用。

还有很多程序员喜欢复杂,各种宏定义、位运算之类写的天花乱坠,生怕代码让别人一下子看懂了会显得自己水平不够。

简单的说,他们的代码是写给机器的,不是给人看的。

ி 不恰当的组织

不恰当的组织是高级一些的烂代码,程序员在写过一些代码之后,有了基本的代码风格,但是对于规模大一些的工程的掌控能力不够,不知道代码应该如何解耦、分层和组织。

这种反模式的现象是经常会看到一段代码在工程里拷来拷去;某个文件里放了一大坨堆砌起来的代码;一个函数堆了几百上千行;或者一个简单的功能七拐八绕的调了几十个函数,在某个难以发现的猥琐的小角落里默默的调用了某些关键逻辑。

这类代码大多复杂度高,难以修改,经常一改就崩;而另一方面,创造了这些代码的人倾向于修改代码,畏惧创造代码,他们宁愿让原本复杂的代码一步步变得更复杂,也不愿意重新组织代码。当你面对一个几千行的类,问为什么不把某某逻辑提取出来的时候,他们会说:

“但是,那样就多了一个类了呀。”

ி 假设和缺少抽象

相对于前面的例子,假设这种反模式出现的场景更频繁,花样更多,始作俑者也更难以自己意识到问题。比如:

文件路径变更的时候,会把代码改成这样:

需要加载的内容更丰富的时候,会再变成这样:

之后可能会再变成这样:

这类程序员往往是项目组里开发效率比较高的人,但是大量的业务开发工作导致他们不会做多余的思考,他们的口头禅是:“我每天要做XX个需求”或者“先做完需求再考虑其他的吧”。

这种反模式表现出来的后果往往是代码很难复用,面对deadline的时候,程序员迫切的想要把需求落实成代码,而这往往也会是个循环:写代码的时候来不及考虑复用,代码难复用导致之后的需求还要继续写大量的代码。

一点点积累起来的大量的代码又带来了组织和风格一致性等问题,最后形成了一个新功能基本靠拷的遗留系统。

ி 还有吗?

烂代码还有很多种类型,沿着功能-性能-可读-可测试-可扩展这条路线走下去,还能看到很多匪夷所思的例子。

那么什么是烂代码?个人认为,烂代码包含了几个层次:

▶ 如果只是一个人维护的代码,满足功能和性能要求倒也足够了。

▶ 如果在一个团队里工作,那就必须易于理解和测试,让其它人员有能力修改各自的代码。

同时,越是处于系统底层的代码,扩展性也越重要。

所以,当一个团队里的底层代码难以阅读、耦合了上层的逻辑导致难以测试、或者对使用场景做了过多的假设导致难以复用时,虽然完成了功能,它依然是坨屎一样的代码。

ி 够用的代码

而相对的,如果一个工程的代码难以阅读,能不能说这个是烂代码?很难下定义,可能算不上好,但是能说它烂吗?如果这个工程自始至终只有一个人维护,那个人也维护的很好,那它似乎就成了“够用的代码”。

很多工程刚开始可能只是一个人负责的小项目,大家关心的重点只是代码能不能顺利的实现功能、按时完工。

过上一段时间,其他人参与时才发现代码写的有问题,看不懂,不敢动。需求方又开始催着上线了,怎么办?只好小心翼翼的只改逻辑而不动结构,然后在注释里写上这么实现很ugly,以后明白内部逻辑了再重构。

再过上一段时间,有个相似的需求,想要复用里面的逻辑,这时才意识到代码里做了各种特定场景的专用逻辑,复用非常麻烦。为了赶进度只好拷代码然后改一改。问题解决了,问题也加倍了。

几乎所有的烂代码都是从“够用的代码”演化来的,代码没变,使用代码的场景发生变了,原本够用的代码不符合新的场景,那么它就成了烂代码。

重构不是万能药

程序员最喜欢跟程序员说的谎话之一就是: 现在进度比较紧,等X个月之后项目进度宽松一些再去做重构。

不能否认在某些(极其有限的)场景下重构是解决问题的手段之一,但是写了不少代码之后发现,重构往往是程序开发过程中最复杂的工作。花一个月写的烂代码,要花更长的时间、更高的风险去重构。

曾经经历过几次忍无可忍的大规模重构,每一次重构之前都是找齐了组里的高手,开了无数次分析会,把组内需求全部暂停之后才敢开工,而重构过程中往往哀嚎遍野,几乎每天都会出上很多意料之外的问题,上线时也几乎必然会出几个问题。

从技术上来说,重构复杂代码时,要做三件事: 理解旧代码、分解旧代码、构建新代码 。而待重构的旧代码往往难以理解;模块之间过度耦合导致牵一发而动全身,不易控制影响范围;旧代码不易测试导致无法保证新代码的正确性。

重构之后能提升多少效率?能降低多少风险?很难答上来,烂代码本身就不是一个可以简单的标准化的东西。

总结

不写代码的人认为应该重构,重构很简单,无论新人还是老人都有责任做重构。

写代码老手认为应该迟早应该重构,重构很难,现在凑合用,这事别落在我头上。

写代码的新手认为不出bug就谢天谢地了,我也不知道怎么重构。

✉ 写好代码很难

与写出烂代码不同的是,想写出好代码有很多前提:

✔ 理解要开发的功能需求。

✔ 了解程序的运行原理。

✔ 做出合理的抽象。

✔ 组织复杂的逻辑。

✔ 对自己开发效率的正确估算。

✔ 持续不断的练习。

写出好代码的方法论很多,但我认为写出好代码的核心反而是听起来非常low的“持续不断的练习”。

很多程序员在写了几年代码之后并没有什么长进,代码仍然烂的让人不忍直视,原因有两个主要方面:

1、环境是很重要的因素之一,在烂代码的熏陶下很难理解什么是好代码,知道的人大部分也会选择随波逐流。

2、还有个人性格之类的说不清道不明的主观因素,写出烂代码的程序员反而都是一些很好相处的人,他们往往热爱公司团结同事平易近人工作任劳任怨–只是代码很烂而已。

而工作几年之后的人很难再说服他们去提高代码质量,你只会反复不断的听到:“那又有什么用呢?”或者“以前就是这么做的啊?”之类的说法。

那么从源头入手,提高招人时对代码的质量的要求怎么样?

前一阵面试的时候发现了一个现象:

一个人工作了几年、做过很多项目、带过团队、发了一些文章,不一定能代表他代码写的好;反之,一个人代码写的好,其它方面的能力一般不会太差。

悲观的结语

说了那么多,结论其实只有两条,作为程序员:

⊱ 不要奢望其他人会写出高质量的代码

⊱ 不要以为自己写出来的是高质量的代码

责任编辑:张燕妮 来源: strongerHuang
相关推荐

2009-06-22 09:16:00

无线网络加密网络安全

2013-06-09 09:51:27

亚马逊Web服务灾难恢复AWS灾难恢复

2012-02-28 10:06:34

虚拟化容灾灾备

2022-11-30 13:13:41

节能减碳PUE

2014-02-17 10:56:21

Hadoop

2021-09-04 00:11:32

大数据Hadoop工具

2020-10-18 12:36:06

Python开发函数

2016-11-24 12:07:42

Android万能圆角ImageView

2009-03-19 09:02:44

2017-09-07 14:15:28

2022-06-23 18:10:15

多云

2009-02-27 13:48:00

Mdaemon邮件服务器

2022-11-21 09:57:18

网关系统

2020-06-16 08:32:00

人工智能技术机器学习

2024-03-06 11:16:10

2023-08-04 13:35:00

DeepMind模型

2017-10-24 14:13:56

Java正则表达式

2009-12-03 18:13:36

PHP万能密码

2021-08-17 14:25:11

人脸识别人工智能身份识别

2011-06-16 15:57:25

Android
点赞
收藏

51CTO技术栈公众号