命名 命名
首页 U 开头 本地查找local find 不用本地查找帧,全屏 Google 搜索特定话题的网页 jump to footer translate with Babelfish by Roedy Green ©1996-2008 Canadian Mind Products  翻译:SuperMMX ©2003-2008 自由 SuperMMX

“When I use a word,” Humpty Dumpty said, in a rather scornful tone, “it means just what I choose it to mean - neither more nor less.”
~ Lewis Carroll — Through the Looking Glass, Chapter 6

很多编写不可维护代码的技巧就是给变量和方法命名的艺术。这些名字对于编译器来说无关紧要。 因此你就能在很大的范围内使用这些技巧,把那些后继的维护程序员搞得晕头转向。

  1. 给小孩取名的新用途

    :
    book_cover recommend book⇒20,001 Names For Baby
    ISBN10: 0-380-78047-X
    ISBN13: 978-0-380-78047-1
    publisher: Harper
    published: 1995-05-01
    by: Carol McD. Wallace
    Canadian flag amazon.ca amazon.com American flag
    Canadian flag chapters.indigo.ca powells.com American flag
    French flag amazon.fr barnesandnoble.com American flag
    German flag amazon.de amazon.co.uk UK flag
    买一本给小孩取名的书,那么你就永远不会缺变量名了。Fred 是一个非常好的名字, 也很容易输入。如果你在寻找容易输入的变量名,就试一试 asdf, 如果你使用的是 DSK 键盘,就是 aoeu
  2. 单字母变量名

    : 如果你把变量叫做 a、b、c,那么用简易编辑器几乎不可能搜索变量的实例。而且, 没有人能猜出它们用来干什么。如果有人想打破自从 FØRTRAN 时代就使用 i、j、k 作为索引变量的传统, 或者分别使用 ii、jj、kk 来代替,那就警告他们,想想西班牙审理曾对异教徒做过些什么。
  3. 创造性的拼写错误

    : 如果你必须使用描述性的变量和函数名,不妨把它们拼错。在一些地方拼错函数和变量名, 在其他地方又拼写正确(就象 SetPintleOpening SetPintalClosing),就能有效地使 grep 或者 IDE 的搜索技术无效。这种方法的效果出奇地好。还可以增加国际化口味, 比如在不同的剧院(theaters/theatres)拼写为 tory 或者 tori
  4. 保持抽象

    : 在命名函数和变量时,大量使用象 iteverythingdatahandlestuffdoroutineperform 以及数字之类的抽象词,例如 routineX48PerformDataFunctionDoItHandleStuff 以及 do_args_method
  5. 使.用.缩.写.

    : 用缩写来保持代码简洁。真正的程序员从来不定义缩写;他们能够本能地看懂它。 如果缩写把你自己都弄糊涂了,可以在写代码的时候偷偷地使用有意义的名字, 然后在代码发挥作用的时候,用 Elcipse 的全局改名功能,把你的变量和方法换成难以理解的名字或者是缩写, 就象混淆器一样。
  6. 同义词代用

    : 以防单调,可以使用同义词典来为一个词查找尽可能多的替代词语,而意思不变,比如 displayshowpresent。这样你含糊地表明一些细微的不同之处,但实际上并不存在。 然而,如果两个类似的函数有着极大的不同,那么始终使用相同的词来描述两个函数(比如,print 意味着"写入文件",或者"打印到纸上",或者"显示在屏幕上")。
  7. 远离项目术语表

    在任何情况下,如果有人要求你写一份术语表,列出项目中明确定义的词汇所代表的含义,一定不要屈从。 这样做就不专业地打破了信息隐藏的结构化设计原则。如果被迫写这样一个词汇表, 可以使用循环定义,就像从 Ant 1.6.5 手册中摘抄出来的: 起始目录(basedir) : 项目起始目录的绝对路径(就如设定了 <project> 的 basedir 属性)。虽然绝对路径这个线索已经给出了, 即使所有的例子都用.(真不巧,正好是相对路径), 读者还是不知道起始目录是个什么东西。

    假装在给出实际上并不存在的信息,让你的对手干着急,让他疲惫不堪。把你空洞的描述充分地掩饰, 这样读者就会责怪自己看不懂。

    读者问自己,如果我要编译 com.mindprod.holidays 这个包, 起始目录是 c:\c:\comc:\com\mindprod 还是 c:\com\mindprod\holidays 呢? 现在明白了为什么不要给出具体的例子了吧。这样太清楚了。如果被迫要给出具体的例子, 就抱怨说这样看起来太小孩子气,而且一点都不专业。 抱怨说这些例子让人感到一个产品能干的全部,就只有这么一点点。 你想让人们从一开始就能完全感受到可能的变化。你不是在告知,而是在给人们留下深刻印象! 毕竟没有人因为举例子而出洋相。人们只尊敬那些太抽象而不容易掌握的东西。

    有太多的东西需要记忆了。不过你会干得很好,只要你在写文档的时候保持一种态度, 不知道这篇文章的都是傻瓜,他们本就不应该理解你的文档。

  8. 使用其他语言的复数形式

    : 一个 VMS 脚本保存了从各种"Vaxen"返回的"statii"。EsperantoKlingonHobbitese 都有资格作为起这个作用的语言。你可以给伪世界语的复数形式(pluraloj)添加 oj,你正在为世界和平而尽力呢。
  9. 字母大写(CapiTaliSaTion)

    : 随机地把单词中间的某个音节的首字母大写。例如: ComputeRasterHistoGram()
  10. 重用名字

    : 在语言允许的任何地方,给类,构造函数,方法,成员变量,参数和局部变量都起相同的名字。 另外,在 {} 块内,重用局部变量的名字。目的就是强迫维护程序员仔细检查每个变量实例的作用范围。 特别在 Java 中,可以用一般的方法冒充构造函数。
  11. 重音字母(Åccented Letters)

    : 在变量名中使用加重音的字母。例如:
    typedef struct { int i; } ínt;
    其中第二个 ínt 中的 í 实际上是一个尖重音的 i。一个简单的编辑器几乎不可能分辨出重音符号的斜体部分。
  12. 利用编译器的名字长度限制

    : 假如编译器只能识别出一个名字的前比如 8 个字符,然后可以是任意结尾,例如,一种情况下是 var_unit_update(),另一种情况下是 var_unit_setup(), 编译器就会把两者都识别为 var_unit
  13. 下划线,真正的朋友

    : 使用 _ 和 __ 作为标识符。
  14. 混和语言

    : 随机地混合使用两种语言(自然语言或者计算机语言)。如果你老板坚持让你使用他的语言, 告诉他,用你自己的语言,你能更好的组织你的想法。如果这个没用的话,就以语言歧视指控你的雇主, 并威胁说要起诉他获得高额赔偿。
  15. 扩展 ASCII

    : 扩展的 ASCII 字符作为变量名也是完全有效的,包括 ß、Ð 和 ñ 等字符。但是在一个简单编辑器中, 不用拷贝/粘贴的方法几乎不可能输入它们。
  16. 来自其他语言的名字

    : 使用外语字典作为变量名字的来源,例如,使用德语 punkt 代替 point。 那些没有象你那样很好地掌握德语的维护程序员们,一定会很满意猜测单词意义的多文化体验过程。
  17. 来自数学的名字

    : 选用那些以数学运算作掩饰的名字作为变量名。例如:
    openParen = ( slash + asterix ) / equals;
  18. 眼花缭乱的名字

    : 给变量取一些与程序无关的但是具有意义的名字。例如:
    marypoppins = ( superman + starship ) / god;
    这会让读者混淆,因为他们很难把这些具有情绪化涵义的词语,从当前正在考虑的逻辑种分离开来。
  19. 改名重用

    : 这个技巧在 Ada 里面很有用,这种语言对很多标准的迷惑技术都免疫。你现在使用的包和对象的命名者都是笨蛋。 与其说服他们修改,不如使用新名字和子类型来重新把它们命名为你自己的一套。保证留下了一些老名字的引用, 让人一不注意就掉进陷阱。
  20. 用 i 的时机

    : 不要使用 i 作为最里层的循环变量。使用任何其他东西来代替。 把 i 随便用作其他目的,尤其是非 int 的变量。类似地, 使用 n 作为循环变量。
  21. 惯例方案

    : 不要理会
    Sun 的编码惯例:编码惯例, 毕竟, Sun 也是这么做的。幸运的是,当你违反的时候, 编译器并不会透漏出去。目标就是想一些只在大小写上不一样的名字。如果你被迫使用大写惯例, 你仍然可以在任何选择不明确的时候捣乱。例如,同时使用 inputFilenameinputfileName。发明你自己的异常复杂的命名规范,然后指责其他人不遵循它。
  22. 小写的 l 看起来非常象数字 1

    : 使用小写 l 表示 long 常量。例如,10l 看起来更象写错的 101,而不是 10L。 摒弃任何可以明确区别以下字母的字体: uvw wW gq9 2z 5s il17|!j oO08 `'" ;: ,。 m nn rn {[()]}。要有创造性。
  23. 把全局名字作为私有名字重新使用

    : 在模块 A 中定义一个全局数组,并且在模块 B 的头文件中定义一个具有相同名字的私有数组。 这样看起来你在模块 B 中使用的是全局的数组,而实际上不是。在注释中不要提到这种重复。
  24. 循环再用

    : 通过以矛盾的方法循环重用变量名来尽可能地混淆作用范围。例如,假设有全局变量 A 和 B, 以及函数 foo 和 bar。如果你知道 A 经常传递给 foo,而 B 经常传递给 bar,那么保证你把 foo 定义成 foo(B),bar 定义成 bar(A),这样在函数中 A 经常是 B 的引用,反过来也一样。 有了更多的函数和全局变量,你就能创建了非常混乱的一个网络,充满了相同名字的相关但又矛盾的用法。
  25. 再循环使用变量

    : 在任何作用范围允许的规则下,重用已有但无关的变量。类似的,把同一个临时变量用于两个不相关的地方(减少栈空间)。 一种更恶毒的变体,就是搞乱你的变量,比如,在一个非常长的方法开头给一个变量赋值,在中间再赋值一次, 巧妙地改变变量的意思,例如,把从 0 开始的下标改为从 1 开始。一定不要对这个改变给出解释。
  26. Cd wrttn wtht vwls s mch trsr

    : 在变量或者方法名中使用缩写时,为了不至于厌烦可以使用同一个单词的几个变体。 甚至不时地写出普通写法。这就有效地打击了那些懒惰的程序员,他们只使用文本搜索就想看懂你程序的一部分。 把变化拼写看作是一种乐趣,例如,把国际拼法 colour 和美国拼写 color, 以及 网络用语 kulerz 混合起来。 如果你把它们完全拼出来,那么每个名字只有一种可能的拼法,对于维护者来说太容易记住了。 因为一个词的缩写可以有很多种,所以,使用缩写,就有好几个不同的变量用于同一个显而易见的目的。 额外的好处就是,维护者甚至可能没有注意到它们是不同的变量。
  27. 误导的名字

    : 保证一个方法比它的名字所表明的事要多做或者少做一些。一个简单的例子, 一个叫做 isValid(x) 的方法有其他的副作用,把 x 转化为二进制并存入数据库。
  28. m_

    : 来自 C++ 世界的一个命名惯例是在类成员之前加 "m_"。这本来是用来把它们和方法区分开的, 只要你忘了方法的开头字母也是 "m"。
  29. o_apple obj_apple

    : 在每个类实例前面用 "o" 或 "obj" 作为前缀,表明你正在考虑一个庞大的多态结构。
  30. 匈牙利命名法

    : 匈牙利命名法是代码混淆技术中的核武器,一定要用它; 由于被这个命名法所污染的代码量, 没有其他方法能比精心设计的匈牙利命名法攻击更快地杀死一个维护工程师。 下面的一些技巧能帮助你破坏匈牙利命名法原来的意图:
  31. 再看匈牙利命名法

    : 有关匈牙利命名法接下来一个技巧是"改变一个变量的类型,但是不改变它的名字"。这在从 Win16 :- WndProc(HWND hW, WORD wMsg, WORD wParam, LONG lParam) 到 Win32 WndProc(HWND hW, UINT wMsg, WPARAM wParam, LPARAM lParam) 的移植中常常会用到, 其中 w 表示它们是字(word),而实际上它们常常表示的是长整(long)。当移植到 Win64 的时候这个方法的真正价值才体现出来, 那时候参数都是 64 位长,但是老的 "w" 和 "l" 前缀却永远保留下来。
  32. 简化,重用,再循环

    : 如果你需要定义一个结构来保存回调数据的话,始终把它叫做 PRIVDATA。每个模块都可以定义自己的 PRIVDATA。在 VC++ 中,具有混淆调试器的优势,这样当你有一个 PRIVDATA 结构,在 watch 窗口中想要展开时,它不知道你需要的是哪个 PRIVDATA,所以它就随便选择一个。
  33. 模糊的电影参考

    : 用一些象 LancelotsFavouriteColour 之类的常量名字, 而不是 blue,并赋值为十六进制 $0204FB。这个颜色在屏幕上看起来是纯蓝的, 一个维护程序员必须算算(或者使用图形工具)来看看 0204FB 看起来到底是什么样的。 只有非常熟悉 Monty Python 和电影 the Holy Grail,才知道 Lancelot 最喜欢的颜色是蓝色。 如果一个维护程序员不能想到所有 Monty Python 的电影,他或者她就没有资格作为一个程序员。
  34. 玩弄颜色

    不言而喻,应该使用数字形式的颜色常量,而不是有名字的常量。不幸的是, 大多数熟练的维护程序员都已经知道十六进制编码的颜色值很容易解码。比如 0x0204FB 就是
    红 = 02
    绿 = 04
    蓝 = FB

    这种颜色明显几乎就是完全的蓝色。

    你所需要的就是使用十进制的数值,132347。没有纸或者计算器的帮助, 任何一个普通人不可能把这个值换算成'蓝'色。额外的好处就是,可以做出一个十进制的颜色值, 但看起来却象是十六进制,比如 808000。一眼扫过去象是半红 + 半绿 = 暗黄色, 但实际上不是十六进制,真正的颜色是 0xc5440(暗青色)。

    Netscape 颜色都经过仔细地命名。 例如,papayawhip 是 0xffefd5。为了保持警觉, 把 papayawhip 这个颜色常量定义为 0xff00ff,是一种亮品红色。 享受虚构含糊颜色名字的乐趣,象 algae = 0x556b2f, 而不用 darkolivegreen(暗橄榄绿)。很少人知道 puce(紫褐色)和 teal(凫蓝)是什么颜色, 但却从不承认。利用这一点。

    甚至可以为你的后继者布下陷阱。使用精确命名但是很丑陋的颜色。如果后援程序员比较懒, 他会把颜色定义改成清楚一些的,但会留着你原来的颜色名字。