Skip to content

四火的唠叨

一个纯正程序员的啰嗦

Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接
Menu

史上最烂的代码

Posted on 11/08/201210/08/2024 by 四火

shit 其实本没有什么代码是 “史上最烂” 的,要有也只有 “史上更烂” 的,我想随便说说这个话题,也是源自豆瓣的一个讨论。事实上,系统复杂了被骂代码烂是一件司空见惯的事情。当然,也有一些短小的代码片段,就足以看出代码作者是个不怎么样的人。

布尔类型的使用是很容易变成最烂代码的:

1
2
3
if (isTrue())
    if (isTrue())
        doSomething();
1
2
3
if(boolVal == true) {
    .....
}

有一些毫无意义的注释:

1
return 1; // 返回 1
1
2
3
//如果标志为真,就返回 true
if(flag)
    return true;

更无意义的是这样的变量命名:

1
2
public static final int ONE = 1;
public static final int TWO = 2;

也有人说,最烂的代码片段应该是这样的才对:

1
2
3
4
5
6
7
8
9
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

还有曾经被骂到遍体流脓的 12306.cn,代码节选:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var sig = 0;
if(searchwordl.indexOf("'") > -1 || searchwordl.indexOf("\"") > -1 || searchwordl.indexOf("%") > -1 || searchwordl.indexOf("#") > -1 || searchwordl.indexOf("&") > -1 || searchwordl.indexOf("*") > -1 || searchwordl.indexOf("(") > -1 || searchwordl.indexOf(")") > -1 || searchwordl.indexOf("@") > -1 || searchwordl.indexOf("`") > -1 || searchwordl.indexOf("/") > -1 || searchwordl.indexOf("\\") > -1 || searchwordl.indexOf(",") > -1 || searchwordl.indexOf(".") > -1 || searchwordl.indexOf("=") > -1 || searchwordl.indexOf("<") > -1 || searchwordl.indexOf(">") > -1)
sig = 1;
 
searchwordl=searchwordl.replace("'",""); 
//searchwordl=searchwordl.replace(" ","");
searchwordl=searchwordl.replace("%","");
searchwordl=searchwordl.replace("#","");
searchwordl=searchwordl.replace("&","");
searchwordl=searchwordl.replace("*","");
searchwordl=searchwordl.replace("(","");
searchwordl=searchwordl.replace(")","");
searchwordl=searchwordl.replace("@","");
searchwordl=searchwordl.replace("`","");
searchwordl=searchwordl.replace("/","");
searchwordl=searchwordl.replace("\\","");
searchwordl=searchwordl.replace(",","");
searchwordl=searchwordl.replace(".","");
searchwordl=searchwordl.replace("=","");
searchwordl=searchwordl.replace("<","");
searchwordl=searchwordl.replace(">","");
if(searchwordl == '请输入搜索条件'){
    alert("请输入搜索条件");
    return false;
}
if(searchwordl == ''){
    alert("请正确输入搜索条件");
    return false;
}
if(sig == 1){
    alert("请正确输入搜索条件");
    return false;
}
document.getElementById('searchword').value=searchwordl;

还有 JavaScript 的烂代码,这实在太多了,就不贴了。越灵活的语言,越难驾驭,超级烂的代码就越容易见到。

Tiago Fernandez 做过一个投票,选举最烂的 Java API:

java-api-unpleasent

公式是:score = (I can live with) + (Painful * 2) + (Crappy * 3) + (Hellish * 4)

结果,你猜到了吗?

chart

Java 的框架多、语法严格,对于限制那些要来搞破坏的程序员确实有帮助。但是真要搞破坏,要限制还是限制不住。以前我接触过一个 Portlet 扩展类,一共好几千行,当时觉得这代码已经够烂了。可是后来我看到了 5000 多行的存储过程,还有 7000 多行的 jsp 页面——我以前以为 Java 程序员的破坏力要远远小于 C/C++程序员。看来,也不尽然。

我的经历中接触到的烂代码,最常见的大概包括下面几种:

  • 一些命名的恶习,比如 “cptct” 这种缩略语缩略到几乎是密码电报的方法名,大概是受到 Basic 毒害,即便是早期的 Visual Basic 版本也在代码中强制实施了一些约束(如变量名的长度、模块中允许的变量数和模块的大小)。
  • 早些年的 web 项目(甚至包括现在的一些小公司做的 web 项目),不懂解耦、不会分层,逻辑全部揉在一起,一坨屎一样。页面模板直接访问数据库、样式代码散落在世界各地,HTML 写死在各种逻辑里。
  • 在某些程序员眼里,“复用”==“继承”,只要有可复用的属性、公共的方法,就设法用无敌霹雳继承大法来解决,也不管适不适合,一级又一级,最后一定是一棵伟岸无边的继承树。
  • 无穷无尽的工具类。这类代码比继承大法的代码好不到哪去,XXHelper、XXTools 这样的静态类满山遍地都是,但是复用的眼光倒是比只会继承多了一条路……
  • 不会用标准库函数、封装好的类库。我见过好几个这样的程序员,对于 Integer、Long、Double 这些数值对象类型的定义、方法几乎完全不了解,倒是对 String 很熟悉,所有的转换、校验,全部都转换成 String 以后完成,完成后再转回来。
  • 上帝类。本质是对类的职责单一不理解。用 Java、C++的程序员写出上帝类也就罢了,今年我居然听朋友说到一个写 Ruby 的有相当工作经验程序员写出一个巨大的上帝类来……
  • 满大街乱跑的设计模式。本质是过度设计。好好一个 “new Template()” 非要引入工厂,再搞一个策略模式、模板模式,不过瘾,最后加上注解来实现……
  • 大部分的 JavaScript、CSS。不解释。

今天有同事说,代码之所以成为烂代码,很大可能是写代码的人会遇到比后来读代码的人多得多的问题,虽然写代码的人解决了大部分的问题,但是剩下的问题还是足以让代码遗臭万年。不过我不这么看,我看到过年份比较早的 VB 代码、还有 Delphi 代码,虽然都是界面开发用的,虽然很多理念远远不及今天,代码依然清晰易懂。

有的程序员说,工期紧、项目重,领导催得我天天吐血,迫不得已我写出了烂代码。客观原因千千万万,我确实无话可说,毕竟在物质文明还非常虚弱的时候,还是不要扯精神文明的蛋。但是,优秀的程序员是有追求的,而人是会麻木的,总是把项目压力挂在嘴边的,给一个宽松的限期也不见得能如何。

还有的程序员说,唯物辩证法告诉我们,任何事物都有两面性,所以我们要学习烂代码中好的设计,并且把糟糕的设计引以为戒……我说,得了吧。烂就是烂,把屎放在冰激凌蛋筒里也还是屎,那么矫情干什么?

有很多程序员总有一种推倒重来的冲动,特别是看到烂代码的时候。我也曾经如此。其实这是危险的。况且在很多情况下你的重写未必有他原来的烂代码好。也许你能解决其中的 30 个问题,却引入了 50 个新问题。重构还是要在业务模型和流程清晰的情况下尽量小改动、划模块入手,大开大合总是危险的。

总说十五年前吃过多少多少苦的程序员我一点都不佩服,我佩服的是在十五年前那种条件和观念下,依然能够写出现在看来都让人无比舒坦代码的优秀程序员。不写烂代码就是爱惜生命、节约资源、保护地球,写好的代码就是一个程序员的素质,没有那么多理由可以讲。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

×Scan to share with WeChat

你可能也喜欢看:

  1. Function Invocation Patterns
  2. 从 DCL 的对象安全发布谈起
  3. 运行时动态增加枚举类型
  4. 同步、异步转化和任务执行
  5. 再议单例模式和静态类

8 thoughts on “史上最烂的代码”

  1. Andy says:
    11/14/2012 at 10:29 AM

    更无意义的是这样的变量命名:
    public static final int TWO = 2;

    对这个不敢苟同。。2 是 magic number, checkstyle 通不过的 - -

    Reply
    1. 四火 says:
      11/14/2012 at 10:50 AM

      通不通过又能怎样?把 2 命名成 TWO 就有意义了?

      是程序员玩工具,而不是被工具玩

      Reply
      1. 甄码农 says:
        11/20/2012 at 5:28 PM

        羡慕你没有 checkstyle 的约束呀,我们这儿 checkstyle 通不过,别想签入代码。

        Reply
        1. Haart says:
          12/12/2012 at 3:23 PM

          即使这样也不应该命名为 TWO。
          哪怕 NUMBER_OF_RECOREDS 或者 DEMOMINITOR 也行。
          至少能让别人明白你定义这个常量的目的是什么。

          Reply
    2. Anonymous says:
      04/12/2018 at 4:11 PM

      TWO = 2;这就是经典的废话。

      Reply
  2. 就是哈哈 says:
    11/09/2012 at 8:07 AM

    人生多风雨,快乐常相伴!

    Reply
  3. yutian says:
    11/08/2012 at 10:43 PM

    重构之后保证不出问题是很关键的,因为我真的不想过些时间又被质保告知回归的过程中出现了 Bug。其实有时候我觉得重构之后的验证工作应该尽量是由自动化的测试工具来完成的,而不是程序员自己(毕竟覆盖率会全一些)。

    Reply
    1. momo says:
      11/13/2012 at 11:45 AM

      所以马丁在《重构》里面一开始就强调单元测试的重要性

      Reply

Leave a Reply to momo Cancel reply

Your email address will not be published. Required fields are marked *

订阅·联系

四火,啰嗦的程序员一枚,现居西雅图

Amazon Google Groovy Hadoop Haskell Java JavaScript LeetCode Oracle Spark 互联网 亚马逊 前端 华为 历史 同步 团队 图解笔记 基础设施 工作 工作流 工具 工程师 应用系统 异步 微博 思考 技术 数据库 曼联 测试 生活 眼界 程序员 管理 系统设计 缓存 编程范型 美股 英语 西雅图 设计 问题 面向对象 面试

分类

  • Algorithm and Data Structure (30)
  • Concurrency and Asynchronization (6)
  • System Architecture and Design (43)
  • Distributed System (18)
  • Tools Frameworks and Libs (13)
  • Storage and Data Access (8)
  • Front-end Development (33)
  • Programming Languages and Paradigms (55)
  • Testing and Quality Assurance (4)
  • Network and Communication (6)
  • Authentication and Authorization (6)
  • Automation and Operation Excellence (13)
  • Machine Learning and Artificial Intelligence (6)
  • Product Design (7)
  • Hiring and Interviews (14)
  • Project and Team Management (14)
  • Engineering Culture (17)
  • Critical Thinking (25)
  • Career Growth (57)
  • Life Experience and Thoughts (45)

推荐文章

  • 谈谈分布式锁
  • 常见分布式系统设计图解(汇总)
  • 系统设计中的快速估算技巧
  • 从链表存在环的问题说起
  • 技术面试中,什么样的问题才是好问题?
  • 从物理时钟到逻辑时钟
  • 近期面试观摩的一些思考
  • RSA 背后的算法
  • 谈谈 Ops(汇总 + 最终篇):工具和实践
  • 不要让业务牵着鼻子走
  • 倔强的程序员
  • 谈谈微信的信息流
  • 评审的艺术——谈谈现实中的代码评审
  • Blog 安全问题小记
  • 求第 K 个数的问题
  • 一些前端框架的比较(下)——Ember.js 和 React
  • 一些前端框架的比较(上)——GWT、AngularJS 和 Backbone.js
  • 工作流系统的设计
  • Spark 的性能调优
  • “残酷” 的事实
  • 七年工作,几个故事
  • 从 Java 和 JavaScript 来学习 Haskell 和 Groovy(汇总)
  • 一道随机数题目的求解
  • 层次
  • Dynamo 的实现技术和去中心化
  • 也谈谈全栈工程师
  • 多重继承的演变
  • 编程范型:工具的选择
  • GWT 初体验
  • java.util.concurrent 并发包诸类概览
  • 从 DCL 的对象安全发布谈起
  • 不同团队的困惑
  • 不适合 Hadoop 解决的问题
  • 留心那些潜在的系统设计问题
  • 再谈大楼扔鸡蛋的问题
  • 几种华丽无比的开发方式
  • 我眼中的工程师文化
  • 观点的碰撞
  • 谈谈盗版软件问题
  • 对几个软件开发传统观点的质疑和反驳
  • MVC 框架的映射和解耦
  • 编程的未来
  • DAO 的演进
  • 致那些自嘲码农的苦逼程序员
  • Java 多线程发展简史
  • 珍爱生命,远离微博
  • 网站性能优化的三重境界
  • OSCache 框架源码解析
  • “ 你不适合做程序员”
  • 画圆画方的故事

近期评论

  • panshenlian.com on 初涉 ML Workflow 系统:Kubeflow Pipelines、Flyte 和 Metaflow
  • panzhixiang on 关于近期求职的近况和思考
  • Anonymous on 闲聊投资:亲自体验和护城河
  • 四火 on 关于近期求职的近况和思考
  • YC on 关于近期求职的近况和思考
  • mafulong on 常见分布式基础设施系统设计图解(四):分布式工作流系统
  • 四火 on 常见分布式基础设施系统设计图解(八):分布式键值存储系统
  • Anonymous on 我裸辞了
  • https://umlcn.com on 资源链接
  • Anonymous on 我裸辞了
© 2025 四火的唠叨 | Powered by Minimalist Blog WordPress Theme
Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接