永远不要(把自己遇到的问题)歸因于(他人的)恶意这恰恰说明了(你自己的)无能。 — 拿破仑
为 了造福大众在Java编程领域创造就业机会,兄弟我在此传授大师们的秘籍这些大师写的代码极其难以维护,后继者就是想对它做最简单的修改都需要花上数 年时间而且,如果你能对照秘籍潜心修炼你甚至可以给自己弄个铁饭碗,因为除了你之外没人能维护你写的代码。再而且如果你能练就秘籍中的全部招式,那么连你自己都无法維护你的代码了!
你不想练功过度走火入魔吧那就不要让你的代码一眼看去就完全无法维护,只要它实质上是那样就行了否则,你的玳码就有被重写或重构的风险!
想挫败维护代码的程序员你必须先明白他的思维方式。他接手了你的庞大程序没有时间把它全部读一遍,更别说理解它了他无非是想快速找到修改代码的位置、改代码、编译,然后就能交差并希望他的修改不会出现意外的副作用。
他查看你的代码不过是管中窥豹一次只能看到一小段而已。你要确保他永远看不到全貌要尽量让他难以找到他想找的代码。但更重要的昰要让他不能有把握忽略任何东西。
程序员都被编程惯例洗脑了还为此自鸣得意。每一次你处心积虑地违背编程惯例都会迫使他必須用放大镜去仔细阅读你的每一行代码。
你可能会觉得每个语言特性都可以用来让代码难以维护其实不然。你必须精心地误用它们才行
“当我使用一个单词的时候” Humpty Dumpty 曾经用一种轻蔑的口气说, “它就是我想表达的意思,不多也不少“
编写无法维护代码的技巧的重中之重昰变量和方法命名的艺术。如何命名是和编译器无关的这就让你有巨大的自由度去利用它们迷惑维护代码的程序员。
看上去没啥不对是吧?嘿嘿嘿…这里的第二个 ínt 的 í 实际上是东北欧字母并不是英语中的 i 。茬简单的文本编辑器里想看出这一点点区别几乎是不可能的。
巧妙利用编译器对于命名长度的限制
惯例 — 明修栈道暗度陈仓
忽视 Java 编码惯例,Sun 自己就是这样做的幸运的是,你违反了它编译器也不会打小报告这一招的目的是搞出一些在某些特殊情况下有细微差别的名字来。如果你被强迫遵循驼峰法命名你还是可以在某些模棱两可的情况下颠覆它。例如inputFilename 和 inputfileName 两个命名都可以合法使用。在此基础上自己发明一套复杂到变态的命名惯例然后就可以对其他人反咬一口,说他们违反了惯例
小写的 l 看上去很像数字 1
当一个bug需要越长的时间才会暴露它就越难被发现。- Roedy Green(本文作者)
编写无法维护代码嘚另一大秘诀就是伪装的艺术即隐藏它或者让它看起来像其他东西。很多招式有赖于这样一个事实:编译器比肉眼或文本编辑器更有分辨能力下面是一些伪装的最佳招式。
把代码伪装成注释反之亦然
如果不是用绿色标出来,你能注意到这三行代码被注释掉了么
可以把 “xy_z” 打散到两行里:
这样全局搜索 xy_z 的操作在这个文件里就一无所获了。 对于 C 预处理器来说第一行最后的 “\” 表示继续拼接下一行的内容。
不正确的文档往往比没有文档还糟糕- Bertrand Meyer
既然计算机是忽略注释和文檔的,你就可以在里边堂而皇之地编织弥天大谎让可怜的维护代码的程序员彻底迷失。
这套技巧对于SSI软件服务公司的那帮蠢材来说太高深了他们只会
用 <math.h> 里的笨例程,消耗50倍的内存和处理时间
编写无法维护代码的基本规则就是:在尽可能多的地方以尽可能多的方式表述每一个事实。- Roedy Green
全局变量怎么强调都不过分
遗憾的是这一招只能在本地C类里用,Java 还不行
在程序里留些bug,让后继的维护代码的程序员能做点有意思的事精心设计的bug是无迹可寻的,而且谁也不知道它啥时候會冒出来要做到这一点,最简单的办法的就是不要测试代码
永远不要写任何測试用例
如果我们对自己的编程能力有充分信心那么测试就没有必要了。如果我们逻辑地看待这个问题随便一个傻瓜都能认 识到测试根本都不是为了解决技术问题,相反它是一种感性的信心问题。针对这种缺乏信心的问题更有效的解决办法就是完全取消测试,送我们的程序员去参加 自信心培训课程毕竟说起来,如果我们选择做测试那么峩们就要测试每个程序的变更,但其实我们只需要送程序员去一次建立自信的培训课就行了很显然这么 做的成本收益是相当可观的。
计算机语言正在逐步进化变得更加傻瓜化。使用最新的语言算什么好汉尽可能坚持使用你会用的最老的语言,先考虑用穿孔纸带不行僦用汇编,再不行用FORTRAN 或者 COBOL再不行就用C 还有 BASIC,实在不行再用 C++
你一直想写系统级的代码。现在机会来了忽略标准库, 编写你自己的标准这将会是你简历中的一大亮点。
推出你自己的 BNF 范式
如果你给某人一段程序你会让他困惑一天;如果你敎他们如何编程,你会让他困惑一辈子 — Anonymous
让我们从一条可能是有史以来最友好的技巧开始:把代码编译成可执行文件。如果它能用就茬源代码里做一两个微小的改动 — 每个模块都照此办理。但是不要费劲巴拉地再编译一次了 你可以留着等以后有空而且需要调试的时候洅说。多年以后等可怜的维护代码的程序员更改了代码之后发现出错了,他会有一种错觉觉得这些肯定是他自己最近修改的。这样你僦能让他毫无头绪地忙碌很长时间
对于试图用行调试工具追踪来看懂你的代码的人,简单的一招就能让他狼狈不堪那就是把每一行代碼都写得很长。特别要把 then 语句 和 if 语句放在同一行里他们无法设置断点。他们也无法分清在看的分支是哪个 if 里的
在工程方面有两种编码方式。一种是把所有输入都转换为公制(米制)计量单位然后在输出的时候自己换算回各种民用计量单位。另一种是从头到尾都保持各種计量单位混合在一起总是选择第二种方式,这就是美国之道!
要 持续不懈地改进要常常对你的代码做出“改进”,并强迫用户经常升级 — 毕竟没人愿意用一个过时的版本嘛即便他们觉得他们对现有的程序满意了,想想看如果他们看到你又“完善“了它,他们会多麼开心啊!不要告诉任何人版本之 间的差别除非你被逼无奈 — 毕竟,为什么要告诉他们本来永远也不会注意到的一些bug呢
” 关于“一栏應该只包含程序名、程序员姓名和一份用法律用语写的版权声明。理想情况下它还应该链接到几 MB 的代码,产生有趣的动画效果但是,裏边永远不要包含程序用途的描述、它的版本号、或最新代码修改日期、或获取更新的网站地址、或作者的email地址 等这样,所有的用户很赽就会运行在各种不同的版本上在安装N+1版之前就试图安装N+2版。
在两个版本之间你能做的变更自然是多多益善。你不会希望用户年复一姩地面对同一套老的接口或用户界面这样会很无聊。最后如果你能在用户不注意的情况下做出这些变更,那就更好了 — 这会让他们保歭警惕戒骄戒躁。
写无法维护代码不需要多高的技术水平喊破嗓子不如甩开膀子,不管三七二十一开始写代码就行了记住,管理层還在按代码行数考核生产率即使以后这些代码里的大部分都得删掉。
一招鲜吃遍天会干什么就吆喝什么,轻装前进如果你手头只有┅把锤子,那么所有的问题都是钉子
有可能的话,忽略当前你的项目所用语言和环境中被普罗大众所接受的编程规范比如,编写基于MFC 嘚应用时就坚持使用STL 编码风格。
把常用的 true 和 false 的定义反过来用这一招听起来平淡无奇,但是往往收获奇效你可以先藏好下面的定义:
紦这个定义深深地藏在代码中某个没人会再去看的文件里不易被发现的地方,然后让程序做下面这样的比较
某些人肯定会迫不及待地跳出來“修正”这种明显的冗余并且在其他地方照着常规去使用变量var:
还 有一招是为 TRUE 和 FALSE赋予相同的值,虽然大部分人可能会看穿这种骗局給它们分别赋值 1 和 2 或者 -1 和 0 是让他们瞎忙乎的方式里更精巧的,而且这样做看起来也不失对他们的尊重你在Java 里也可以用这一招,定义一个叫 TRUE 的静态常量在这种情况下,其他程序员更有可能怀疑你干的不是好事因为Java里已经有了内建的标识符 true。
在你的项目里引入功能强大的苐三方库然后不要用它们。潜规则就是这样虽然你对这些工具仍然一无所知,却可以在你简历的“其他工具”一节中写上这些没用过嘚库
假装不知道有些库已经直接在你的开发工具中引入了。如果你用VC++编程忽略MFC 或 STL 的存在,手工编写所有字符串和数组的实现;这样有助于保持你玩指针技术的高水平并自动阻止任何扩展代码功能的企图。
创建一套Build顺序
把 这套顺序规则做得非常晦涩让维护者根本无法編译任何他的修改代码。秘密保留 SmartJ 它会让 make脚本形同废物。类似地偷偷地定义一个 javac 类,让它和编译程序同名说到大招,那就是编写和維护一个定制的小程序在程序里找到需要编译的文件,然后通过直接调用 sun.tools.javac.Main 编译类来进行编译
用一个 makefile-generated-batch-file 批处理文件从多个目录复制源文件,文件之间的覆盖规则在文档中是没有的这样,无需任何炫酷的源代码控制系统就能实现代码分支,并阻止你的后继者弄清哪 个版本嘚 DoUsefulWork() 才是他需要修改的那个
尽可能搜集所有关于编写可维护代码的建议,例如 SquareBox 的建议 然后明目张胆地违反它们。
某些公司有严格的规定不允许使用数字标识符,你必须使用预先命名的常量要挫败这种规定背后的意图太容易了。比如一位聪明的 C++ 程序员是这么写的:
一 萣要保留一些编译器警告。在 make 里使用 “-” 前缀强制执行忽视任何编译器报告的错误。这样即使维护代码的程序员不小心在你的源代码裏造成了一个语法错误,make 工具还是会重新把整个包build 一遍甚至可能会成功!而任何程序员要是手工编译你的代码,看到屏幕上冒出一堆其實无关紧要的警告他们肯定会觉得是自己搞坏了代码。同样他们一定会感 谢你让他们有找错的机会。学有余力的同学可以做点手脚让編译器在打开编译错误诊断工具时就没法编译你的程序当然了,编译器也许能做一些脚本边界检查但 是真正的程序员是不用这些特性嘚,所以你也不该用既然你用自己的宝贵时间就能找到这些精巧的bug,何必还多此一举让编译器来检查错误呢
把 bug 修复和升级混在一起
永 遠不要发布什么“bug 修复”版本。一定要把 bug 修复和数据库结构变更、复杂的用户界面修改还有管理界面重写等混在一起。那样的话升级僦变成一件非常困难的事情,人们会慢慢习惯 bug 的存在并开始称他们为特性那些真心希望改变这些”特性“的人们就会有动力升级到新版夲。这样从长期来说可以节省你的维护工作量并从你的客户那里获得更 多收入。
在你的产品发布每个新版本的时候都改变文件结构
没错你的客户会要求向上兼容,那就去 做吧不过一定要确保向下是不兼容的。这样可以阻止客户从新版本回退再配合一套合理的 bug 修复规則(见上一条),就可以确保每次新版本发布后客户都会留在新版本。学有余力的话还可以想办法让旧版本压根无法识别新版本产生嘚文件。那样的话 老版本系统不但无法读取新文件,甚至会否认这些文件是自己的应用系统产生的!温馨提示:PC 上的 Word
文字处理软件就典型地精于此道
不 用费劲去代码里找 bug 的根源。只要在更高级的例程里加入一些抵销它的代码就行了这是一种很棒的智力测验,类似于玩3D棋而且能让将来的代码维护者忙乎很长时间都想不明白问 题到底出在哪里:是产生数据的低层例程,还是莫名其妙改了一堆东西的高层玳码这一招对天生需要多回合执行的编译器也很好用。你可以在较早的回合完全避免 修复问题让较晚的回合变得更加复杂。如果运气恏你永远都不用和编译器前端打交道。学有余力的话在后端做点手脚,一旦前端产生的是正确的数据就让后 端报错。
不要用真正的哃步原语多种多样的旋转锁更好 — 反复休眠然后测试一个(non-volatile的) 全局变量,直到它符合你的条件为止相比系统对象,旋转锁使用简便”通用“性强,”灵活“多变实为居家旅行必备。
把 某些系统同步原语安插到一些用不着它们的地方本人曾经在一段不可能会有第二个線程的代码中看到一个临界区(critical section)代码。本人当时就质问写这段代码的程序员他居然理直气壮地说这么写是为了表明这段代码是很”关鍵“(单词也是critical)的!
如 果你的系统包含了一套 NT 设备驱动,就让应用程序负责给驱动分配 I/O 缓冲区然后在任何交易过程中对内存中的驱动加锁,并在交易完成后释放或解锁这样一旦应用非正常终止,I/O缓存又没有被解锁NT服务器就会当机。但 是在客户现场不太可能会有人知噵怎么弄好设备驱动所以他们就没有选择(只能请你去免费旅游了)。
在你的 C/S 应用里嵌入一个在运行时按字节编译的脚本命令语言
如果你发现在你的编译器或解释器里有个bug,一定要确保这个bug的存在对于你的代码正常工作是至关重要的毕竟你又不会使用其他的编译器,其他任何人也不允许!
下面是一位大师编写的真实例子让我们来瞻仰一下他在这样短短几行 C 函数里展示的高超技巧。
如果你的编译器冒出了 “unused local variable” 警告不要去掉那个变量。相反要找个聪明的办法把它用起来。我最喜欢的方法是:
差点忘了说了函数是越大越好。跳转和 GOTO 语句越多越好那样的话,想做任何修改都需要分析很多场景这会让维护代码的程序员陷入千头万绪之中。如果函数真的体型庞大的话对于维护代码的程序员僦是哥斯拉怪兽了,它会在他搞清楚情况之前就残酷无情地将他踩翻在地
一张图片顶1000句话,一个函数就是1000行
把每个方法体写的尽可能的長 — 最好是你写的任何一个方法或函数都不会少于1000行代码而且里边是深度嵌套,这是必须的
一定要保证一个或多个关键文件无法找到。利用includes 里边再 includes 就能做到这一点例如,在你的 main 模块里你写上:
然后,refcode.h 就没地方能找到了
(【译者注】为啥找不到呢?仔细看看现在還有人知道 a:\ 是什么吗?A盘!传说中的软盘…)
至少要把一个变量弄成这样:到处被设置但是几乎没有哪里用到它。不幸的是现代编译器通常会阻止你做相反的事:到处读,没处写不过你在C 或 C++ 里还是可以这样做的
美国科學家电报发明人。
1791年4月27日生于美国马萨诸塞州1872年4月2日卒于纽约市。
1810年毕业于耶鲁大学早期曾从事印刷和绘画。
1837年在美国电学家J.亨利等帮助下经过反复试验研制出最早的电磁式电报机。
1838年在A.L.范尔的启示下创造了点划组合的摩尔斯电码使电报机进入了实用阶段。后在媄国国会的资助下莫尔斯用了约两年时间建成从华盛顿到巴尔的摩全程64公里的电报线路。
1844年5月24日开始通报揭开了人类通信史新的一页。
萨缪尔?摩尔斯(1791年4月27日-1872年4月2日)美国发明家,摩尔斯电码的创立者
萨缪尔?摩尔斯生于麻省查尔斯镇,是美國地理学之父、兼基督教公理会牧师迦地大摩尔斯及Elizabeth Ann Breese Morse的长子迦地大摩尔斯是一个加尔文主义的传道者,也是一个美国联邦党的拥护者怹不但保存了清教徒严格遵守安息日的传统,也相信强大的中央政府以英语建立的联盟他相信联邦内的教育能够把加尔文主义的美德、噵德及祷告灌输给他的儿子。
当到访麻省菲腊学院后萨缪尔?摩尔斯便到耶鲁学院修读宗教哲学、数学及有关马匹的科学。当时他曾经絀席本杰明?西利曼及Jeremiah Day有关电的课堂他最后在1810年毕业。经过在欧洲的一段短暂艺术研究之旅后萨缪尔?摩尔斯在返回时的船上,沉醉於一段关于电磁石的谈话之中这正是他最初关于电报机的想法。五年之后也就是1837年,他进入了实际验证阶段用电线将信号传送了1700英呎远。到1844年他成功地用摩尔斯电码;在华盛顿特区和巴尔的摩之间进行了信号发送。
萨缪尔?摩尔斯这位颇有影响的美国画家兼出版商,同时也是一位发明家创造了通信交流的全新方式。
萨缪尔?摩尔斯的绘画风格很明显的在他的绘画《降落的朝聖者》(Landing of the Pilgrims)表现:简单的衣着和朴素的面部特征美南北战争时期联邦党拥护者的心理特征,加尔文主义教徒们从英格兰带到美国的宗教思想和政府以此不断地连接两国家。更重要的是这幅独特的作品吸引了著名艺术家华盛顿?奥尔斯顿(Washington Allston),奥尔斯顿想让摩尔斯去陪哃自己到英格兰去见艺术家本杰明?维斯特(Benjamin West)摩尔斯在吕迪亚待了三年。在1811年6月14日和奥尔斯顿乘坐Lydia出航英格兰。
到达英国后摩尔斯茬维斯特的留意下摩尔斯努力地完善绘画技法。在1811年年底被英国皇家学院录取。
摩尔斯电码(又译为摩斯电碼)是一种时通时断的信号代码通过不同的排列顺序来表达不同的英文字母、数字和标点符号。它由美国人艾尔菲德?维尔发明当时他囸在协助S萨缪尔?摩尔斯进行摩尔斯电报机的发明(1835年)。4月27日为萨缪尔?摩尔斯诞辰218周年
摩尔斯电码是一种早期的数字化通信形式,但是咜不同于现代只使用零和一两种状态的二进制代码它的代码包括五种:点,划每个字符间短的停顿,每个词之间中等的停顿以及句孓之间长的停顿。
虽然摩尔斯发明了电报但他缺乏相关的专门技术。他与艾尔菲德?维尔签定了一个协议让他帮自己制造更加实用的设备。艾尔菲德?维尔构思了一个方案通过点、划和中间的停顿,可以让烸个字符和标点符号彼此独立地发送出去他们达成一致,同意把这种标识不同符号的方案放到摩尔斯的专利中这就是现在我们所熟知嘚美式摩尔斯电码,它被用来传送了世界上第一条电报
这种代码可以用一种音调平稳时断时续的无线电信号来传送,通常被称做连续波(Continuous Wave)缩写为CW。它可以是电报电线里的电子脉冲也可以是一种机械的或视觉的信号(比如闪光)。
一般来说任何一种能把书面字符用可变长度嘚信号表示的编码方式都可以称为摩尔斯电码。但现在这一术语只用来特指两种表示英语字母和符号的摩尔斯电码:美式摩尔斯电码被使鼡了在有线电报通信系统;今天还在使用的国际摩尔斯电码则只使用点和划(去掉了停顿)
clearly.")。这些五个字符的简语可以用摩尔斯电码单独发送在网络用辞中,我们也会说一些最常用的摩尔斯商用代码现在仍然在业余无线电中使用的有Q简语和Z简语:他们最初是为报务员之间交鋶通信质量、频率变更、电报编号等信息服务的。
1838年1月8日Alfred Vail展示了一种使用点和划的电报码,这是摩尔斯电码前身
作为一种信息编码标准,摩尔斯电码拥有其他编码方案无法超越的长久的生命摩尔斯电码在海事通讯中被作为国际标准一直使用到1999年。1997年当法国海军停止使用摩尔斯电码时,发送的最后一条消息是:“所有人注意这是我们在永远沉寂之前最后的一声呐喊”!
做为一种实际上已经绝迹的电码,美式摩尔斯电码使用不太一样的点、划和独特地间隔来表示数字、字符和特殊符号这种摩尔斯电码的设计主要是针对地面报务员通过電报电线传输的,而非通过无线电波这种古老的、交错的电码是为了配合报务员接听方式而设计的。不象现在可以从扬声器或者耳机中聽到电码的音调你只能从这些最早期的电报机的一个机械发生装置听到嗒嗒的声音,甚至是从发送电键接听:这种电键在不发送信号时被设置为从动模式负责发声。
这些报务员大多是为铁路或以后的西联电传等服务象那时的许多年轻人一样,十几岁的爱迪生就是这样┅名话务员
字母 编码 字母 编码
1912年,著名的泰坦尼克号邮轮首航遇险时曾使用当时刚通过并准备使用的新求救信号SOS(*** --- ***)发报,结果没有被理睬泰坦尼克号沉没后,SOS(*** --- ***)才被广泛接受和使用泰坦尼克号也因此成为世界上第一艘发出SOS电码的船只。这也成为了4月27日萨缪尔?摩尔斯诞辰218周年当中一个非常著名的案例
1836年他以夲土党的身份和口号参加了纽约市市长的竞选,但最终并不成功只获得了1496票。
有一次摩尔斯到罗马访问在出席会上,他拒绝向罗马教瑝脱帽以示抗议见到如此情形,一个瑞士近卫队士兵怒气冲冲地跑了过来把帽子从他的头上打翻掉地。摩尔斯一直致力于联合新教去反对天主教协会希望能够制止天主教控制公共部门,同时也希望能够通过修订和加强《移民法》来限制那些来自信仰天主教的国家的移囻在这个议题上,他曾写道:“为了大船不被沉没我们必须尽快堵住这个流着污泥脏水的漏洞。”
摩尔斯还是《纽约观察者》的专栏莋家(他哥哥西德尼时任该报主编)文章提醒民众要警觉天主教的威胁,并提倡为之而战这些文章被各大报纸广泛的再版刊登。在这個主张讨论上他认为奥地利政府和天主教救助组织对那些移民美国的天主教徒的援助,目的是为了逐渐控制美国
在他的著作《外国阴謀美国的自由》(Conspiracy Against the Liberties of the United States)中,他写道:“当然美国的新教教徒,自由民有足够的洞察力去发觉那些外国异教徒在他们眼皮底下搞破坏他们會明白天主教会无论过去还是现在,都一直是最邪恶的且已经体制化了的政治阴谋家和独裁者只不过利用‘宗教’ 这一神圣的幌子来保護自己不受攻击。他们最终会明白这一真相:天主教会是一个政教合一的组织这种关系完全有别于现存于我国的其他宗教组织,有别于其他形式的宗教信仰”
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。