原文链接:https://javascript.info/ninja-code,translate with ❤️ by zhangbao.
学而不思则罔,思而不学则殆。 —— 孔子
程序员ninjas过去使用这些技巧来提高代码维护者的思维。
代码审查大师在测试任务中寻找他们。
新手开发人员有时甚至比程序员忍者更好地使用它们。
仔细阅读它们,找出你是谁 - 忍者,新手,或者代码审查员?
⚠️具有讽刺意味的检测
许多人试图追随忍者之路。很少有成功的。
言以简为贵
使代码尽可能短。表现出你有多聪明。
让微妙的语言特征引导你。
举个例子,看一下这个三元运算符:’?’:
// taken from a well-known javascript library
i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
很酷,对吗? 如果你这样写,那么遇到这一行的开发人员试图理解 i 的值是多么快乐。然后来找你,寻求答案。
告诉他,短的总是更好。让他进入忍者的道路。
单个字符变量
The Dao hides in wordlessness. Only the Dao is well begun and well completed. ——老子《道德经》
另一种更快编码的方法是在任何地方使用单字母变量名,像 a,b 或者 c。
一个简短的变量在代码中消失了,就像森林里真正的忍者一样。没有人能够使用编辑器的“搜索”找到它。即使有人做了,也不能“解释”像 a,b 这样的名字表示什么意思。
但是有一个例外。一个真正的忍者永远不会把 i 当作“for”循环中的计数器。任何地方,但不在这里。环顾四周,有许多异国情调的字符,例如 x 或 y。
如果循环体需要 1-2 页(如果可以的话,使它更长),那么一个带有异国情调的变量就特别酷了。然后,如果有人深入到循环中,他就不能很快地发现名为 x 的变量是循环计数器。
使用缩写
如果团队规则禁止使用单字母和模糊的名称来缩短它们,那么就做缩写。
像这样:
list → lst。
userAgent → ua。
brower → brsr。
等等
只有具有真正良好直觉的人才能理解这些名字。尽量缩短一切。只有一个有价值的人应该能够维护你的代码的开发。
飞得很高, 是抽象的
The great square is cornerless
The great vessel is last complete,
The great note is rarified sound,
The great image has no form. —— 老子《道德经》
在选择一个名字的时候,试着使用最抽象的词。像 obj,data,value,item,elem 等等。
- 理想名字是
data
。可以在任何地方使用,确实,什么变量不是数据呢,对吧?
但是,如果 data 已经被采用,该怎么办呢?尝试 value,它也是普遍的。毕竟,一个变量最终会得到一个值。
- 通过类型来命名变量:
str
,num
…
试一试。 一位年轻的创始人可能会怀疑 - 这样的名字真的对忍者有用吗?的确,他们是!
当然,变量名仍然意味着什么。它说变量里面有什么:字符串,数字或其他东西。但是当一个局外人试图理解代码时,他会惊讶地发现实际上根本就没有信息!最终将无法改变您精心设计的代码。
通过调试很容易找到值类型。但变量的含义是什么?它存储哪个字符串/数字?
没有好的冥想就没有办法弄明白!
- 但是如果没有更多这样的名字呢?只要加上一个数字:
data1
,item1
,elem5
等。
注意力测验
只有真正细心的程序员才应该能够理解您的代码。但是如何检查呢?
其中一种方法——使用类似的变量名,比如 date 和 data。
把它们混合在一起。
快速阅读这类代码是不可能的。当有一个印刷错误的时候。嗯。我们被困了很长时间,喝了茶。
聪明的同义词
The hardest thing of all is to find a black cat in a dark room, especially if there is no cat. ——孔子
用相似的名字来做同样的事情会让生活更有趣,并向公众展示你的创造力。
例如,考虑函数前缀。如果一个函数在屏幕上显示一条消息——以 diaplay… 开头,像 displayMessage。然后,如果另一个函数在屏幕上显示其他东西,比如用户名,那么就以 show 开头(像 showName)。
暗示这些功能之间有细微的差别,但却没有。
与团队的其他忍者们达成协议:如果约翰在代码里以 display… 开头来写“显示”函数……,彼得使用 render..,还有安——paint……请注意,代码变得更加有趣和多样化。
现在是帽子戏法!
例如,函数 printPage(page) 将使用打印机。 而 printText(text) 函数会将文本放在屏幕上。让一个不熟悉的读者仔细思考类似命名的函数 printMessage:“它在哪里放置消息?到打印机或屏幕上?”为了让它真正闪耀,printMessage(message) 应该在新窗口中输出它!
重用名称
Once the whole is divided, the parts
need names.
There are already enough names.
One must know when to stop. ——老子《道德经》
仅在绝对必要时添加新变量。
相反,重用现有名称。只需在其中写入新值即可。
在函数中尝试仅使用作为参数传递的变量。
这将使现在很难确定变量中的确切内容。它也来自哪里。直觉较弱的人必须逐行分析代码并跟踪每个代码分支的变化。
该方法的一个高级变体是隐蔽地(!)在循环或函数的中间用类似的东西替换值。
例如:
function ninjaFunction(elem) {
// 20 lines of code working with elem
elem = clone(elem);
// 20 more lines, now working with the clone of the elem!
}
想要在函数的后半部分使用 elem 的同事程序员会感到惊讶……只有在调试过程中,在检查代码后他才会发现他正在使用克隆!
甚至对经验丰富的忍者也有致命的效果。经常在代码中看到。
下划线乐趣
在变量前面加 或者 __,像 _name 或 __value。如果你知道他们的意思,那就太好了。或者,更好的是,把它们加起来只是为了好玩,没有特别的意义。或者在不同的地方有不同的含义。
你一枪杀了两只兔子。 首先,代码变得更长,更不易读,第二,同事开发人员可能花费很长时间试图找出下划线的含义。
一个聪明的忍者将下划线放在一个代码点,并在其他地方躲避它们。 这使得代码更加脆弱,并增加了未来错误的可能性。
表达你的爱
让每个人都看到你的实体是多么壮观! 像superElement,megaFrame和niceItem这样的名字肯定会启发读者。
事实上,从一方面来说,有些东西是写的:super……,mega……,nice……但另一方面 - 没有带来任何细节。 读者可能会决定寻找隐藏的意义并冥想一两个小时。
重叠的外部变量
When in the light, can’t see anything in the darkness.
When in the darkness, can see everything in the light. —— Guan Yin Zi
对函数内外的变量使用相同的名称。一样简单。不需要努力。
let user = authenticateUser();
function render() {
let user = anotherValue();
...
...many lines...
...
... // <-- a programmer wants to work with user here and...
...
}
一个在 render
中跳跃的程序员可能没有注意到有一个本地用户跟踪外部的用户。
然后,他会尝试与 user 一起工作,假设它是外部变量,是 authenticateUser()的结果。陷阱就会出现!你好,调试器……
到处都有副作用
有些功能看起来不会改变任何东西。 像isReady(),checkPermission(),findTags()……假设它们执行计算,查找并返回数据,而不更改它们之外的任何内容。 换句话说,没有“副作用”。
一个非常漂亮的技巧是给他们添加一个“有用的”动作,除了主要的任务。
当他看到一个名为 is… 的函数,check…..或者 find……改变某些东西时,他会在你的同事面前表达茫然的惊讶 - 这肯定会扩大你的理性界限。
另一种令人惊讶的方法是返回非标准结果。
展现你的原始思维! 让 checkPermission 的调用返回不是 true/false,而是一个带有检查结果的复杂对象。
那些尝试编写 if( checkPermission(..) ) 的开发人员会想知道为什么它不起作用。告诉他们:“阅读文档!”。并给出这篇文章。
强大的函数
he great Tao flows everywhere,
both to the left and to the right. ——老子《道德经》
不要通过名称中的内容来限制功能。 更广泛。
例如,函数 validateEmail(email) 可以(除了检查电子邮件的正确性)显示错误消息并要求重新输入电子邮件。
功能名称中不应显示其他操作。 一个真正的忍者编码器也会使代码不明显。
将多个操作合并为一个可以保护您的代码不被重用。
想象一下,另一位开发人员只想检查电子邮件,而不是输出任何消息。 你的函数 validateEmail(email)这两个都不适合他。 所以他不会通过询问任何事情来打破你的冥想。
总结
上面的所有“建议”都来自真实的代码…有时,由经验丰富的开发人员编写。 也许比你更有经验;)
关注其中一些,您的代码将充满惊喜。
关注其中的许多内容,您的代码将真正成为您的代码,没有人愿意更改它。
全部跟进,您的代码将成为寻求启发的年轻开发人员的宝贵经验。
(完)