热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

忍者代码

学而不思则罔,思而不学则殆。孔子过去的程序员忍者使用这些技巧来使代码维护者的头脑更加敏锐。代码审查大师在测试任务中寻找它们。一些新入门的开发者有时候甚至比忍者程序员更

学而不思则罔,思而不学则殆。@孔子

过去的程序员忍者使用这些技巧来使代码维护者的头脑更加敏锐。

代码审查大师在测试任务中寻找它们。

一些新入门的开发者有时候甚至比忍者程序员更好的使用它们。

仔细阅读它们,找出你是谁 —— 一个忍者、一个新手、或者一个代码审查者?

检测到讽刺意味,许多人试图追随忍者的脚步。只有极少数成功了。

简洁是智慧的灵魂

让代码尽可能地短一点。展示出你是多么的聪明啊。

让一些巧妙的语言特性来指导你。

例如,看一下这个三元运算符 '?':

// 从一个著名的 Javascript 库中取到的代码
i &#61; i ? i <0 ? Math.max(0, len &#43; i) : i : 0;

很酷&#xff0c;对吗&#xff1f;如果你这样写了&#xff0c;那些看到这一行代码并尝试去理解 i 的值是什么的开发者们就会有一个“快活的”的时光了。然后会来找你寻求答案。

告诉他短一点总是更好的。引导他进入忍者之路。

一个字母的变量

道隐无名。夫唯道善贷且成。&#64;老子&#xff08;道德经&#xff09;

编码更快&#xff08;也更糟糕&#xff09;的另一种方式是到处使用单字母的变量名。像是 a、b 或 c。

短变量会像森林中真正的忍者一样在代码中消失不见。没有人能够通过编辑器的“搜索”找到它。即使有人做到了&#xff0c;他也不能“破译”出变量名 a 或 b 是什么意思。

…但是有一个例外情况。一个真正的忍者绝不会在 "for" 循环中使用 i 作为计数器。在任何地方都可以&#xff0c;但是这里不会用。看一下四周吧&#xff0c;还有很多不常用的字母呢。例如 x 或 y。

如果循环体能够达到 1-2 页&#xff08;如果可以的话可以让它更长&#xff09;那么长的话&#xff0c;使用一个不常用的变量作为循环的计数器就更酷了。如果某人看到循环内部的深处后&#xff0c;他就不能很快地找出变量 x 是循环计数器啦。

使用缩写

如果团队规则中禁止使用一个字母和模糊的名字&#xff0c;那就缩短他们&#xff0c;使用缩写吧。

像这样&#xff1a;

  • list → lst

  • userAgent → ua

  • browser → brsr

  • …等等

只有具有真正良好直觉的人才能够理解所有的这些名字。尽量缩短一切。只有一个有价值的人才能够维护这种代码的开发。

Soar high&#xff0c;抽象化。

大方无隅,大器晚成,大音希声,大象无形。&#64;老子&#xff08;道德经&#xff09;

当选择一个名字时尽可能尝试使用最抽象的词语。例如 obj、data、value、item、elem 等等。

一个变量的理想名称是 data。在任何能用的地方都使用它。的确&#xff0c;每个变量都持有 data&#xff0c;对吧&#xff1f;

…但是 data 已经用过了怎么办&#xff1f;可以尝试一下 value&#xff0c;它也很普遍呢。一个变量总会有一个 value&#xff0c;对吧&#xff1f;

根据变量的类型命名&#xff1a;str、num…

尝试一下吧。新手可能会诧异 —— 这些名字对于忍者来说真的有用吗&#xff1f;事实上&#xff0c;是的&#xff01;

一方面&#xff0c;变量名仍然有着一些含义。它说明了变量内是什么&#xff1a;一个字符串、一个数字或是其他的东西。但是当一个局外人试图理解代码时&#xff0c;他会惊讶地发现实际上没有任何有效信息&#xff01;最终无法改变你精心思考过的代码。

事实上&#xff0c;值的类型很容易就能通过调试看出来。但是变量名的含义呢&#xff1f;它存了哪一个字符串/数字&#xff1f;

如果不深思是没有办法找出来的&#xff01;

…但是如果找不到更多这样的名字呢&#xff1f;可以加一个数字&#xff1a;item1、item2、elem5、data1…

注意测试

只有一个真正细心的程序员才能理解代码。但是怎么检验呢&#xff1f;

方式之一 —— 使用相似的变量名&#xff0c;像 date 和 data。

尽你所能地将它们混合在一起。

快速阅读这些代码是不可能的。并且如果有一个错别字时… (⊙v⊙)嗯…我们卡在这里很久没有喝茶了。

智能同义词

最难的事情是在黑暗的房间里找到一只黑猫&#xff0c;特别是如果没有猫。&#64;孔子

对于同样的事情使用相同的名字&#xff0c;可以使生活更有趣&#xff0c;并向公众展示出你的创意。

例如&#xff0c;函数前缀。如果一个函数是在屏幕上展示一个消息 —— 可以以 display… 开始&#xff0c;例如 displayMessage。如果另一个函数展示别的东西&#xff0c;比如一个用户名&#xff0c;可以以 show… 开始&#xff08;例如 showName&#xff09;。

暗示这些函数之间有微妙的差异&#xff0c;实际上并没有。

与团队中的其他忍者们达成一个协议&#xff1a;如果 John 在他的代码中以 display... 来开始一个"显示"函数&#xff0c;那么 Peter 可以用 render..&#xff0c;Ann 可以使用 paint...。你可以发现代码变得多么的有趣多样呀。

现在是帽子戏法&#xff01;

对于有非常重要的差异的两个函数使用相同的前缀。

例如&#xff0c;printPage(page) 函数会使用一个打印机。printText(text)函数会将文字显示到屏幕上。让一个陌生的读者来思考一下&#xff1a;“printMessage(message)会将消息放到哪里呢&#xff1f;打印机还是屏幕上&#xff1f;”&#xff0c;为了使它真正耀眼&#xff0c;printMessage(message)&#96; 应该将消息输出在新窗口中&#xff01;

重用名字

始制有名&#xff0c;名亦既有&#xff0c;夫亦将知止&#xff0c;知止可以不殆。&#64;老子&#xff08;道德经&#xff09;

仅在绝对必要时才添加新变量。

否则&#xff0c;重用已经存在的名字。只需要将新值写进变量即可。

在一个函数中&#xff0c;尝试仅使用作为参数传递的变量。

这样就无法确定这个变量现在是什么了。也不知道它是从哪里来的。一个弱直觉的人必须逐行分析代码&#xff0c;并通过每个代码分支跟踪变化。

这个方法的一个进阶方案是在一个循环或函数中偷偷地替换掉它的值。

例如&#xff1a;

function ninjaFunction(elem) { // 基于变量 elem 进行工作的 20 行 elem &#61; clone(elem); // 又 20 行&#xff0c;现在是使用 clone 后的 elem 变量。
}

想要在第二部分中使用 elem 的程序员会非常的诧异滴…只有在调试期间&#xff0c;在检查代码之后&#xff0c;他会发现他正在使用克隆过的变量&#xff01;

经常看到这样的代码&#xff0c;即使对经验丰富的忍者来说也是致命的。

下划线的乐趣

在变量名前使用 _ 和 _。例如 _name 和 _value。如果只有你知道他们的含义的话将会非常棒。或者&#xff0c;更棒的是&#xff0c;其实没有意义。

你一枪杀死了两只兔子。首先&#xff0c;代码变得更长降低了可读性&#xff1b;第二&#xff0c;你的开发者小伙伴可能会花费很长时间来弄清楚下划线是什么意思。

一个聪明的忍者会在代码的一个地方使用下划线然后在其他地方刻意避免使用它们。这会使得代码变得更加脆弱&#xff0c;并增加未来出现错误的可能性。

展示你的爱

让大家看看你的实体是多么壮观&#xff01;像 superElement、megaFrame 和 niceItem 这样的名字一定会启发读者。

事实上&#xff0c;从一方面来说&#xff0c;看似写了一些东西&#xff1a;super..、mega..、nice..&#xff0c;但是从另一方面来说 —— 并没有提供任何细节。读者可能要寻找一个隐藏的含义或深思一两个小时。

重叠外部变量

处明者不见暗中一物&#xff0c; 处暗者能见明中区事。&#64;关尹子

对函数内外的变量使用相同的名称。很简单&#xff0c;一点也不费劲。

let user &#61; authenticateUser();
function render() { let user &#61; anotherValue(); ... ...many lines... ... ... // <-- 某个程序员想要在这里使用 user 变量... ...
}

跳过 render 的程序员可能不会注意到有一个本地 user 遮挡外部的 user 了。

然后他会假设 user 仍然是外部的变量然后使用它&#xff0c;authenticateUser() 的结果… 陷阱出来啦&#xff01;你好呀&#xff0c;调试器…

无处不在的副作用&#xff01;

有些函数看起来它们不会改变任何东西。例如 isReady()、checkPermission()、findTags()… 它们被假定为会执行计算&#xff0c;查找和返回数据&#xff0c;而不需要更改任何外部的数据。这被称为“无副作用”。

一个非常好的技巧 – 除了主要任务之外&#xff0c;还要向它们添加一个“有用的”动作

当你的同事看到被命名为 is..、check.. 或 find... 的函数改变了某些东西的时候&#xff0c;他的脸上肯定是一脸懵逼的状态。

另一种惊喜的方式是返回非标准的结果。

展示你原来的想法&#xff01;让调用 checkPermission 时返回的不是 true/false&#xff0c;而是一个包含检查结果的复杂对象。

那些尝试写 if (checkPermission(..)) 的开发者会怀疑为什么它不能工作。告诉他们&#xff1a;“去读文档吧”。然后给出这篇文章。

强大的函数&#xff01;

大道泛兮&#xff0c;其左可右。&#64;老子&#xff08;道德经&#xff09;

不要让函数受限于名字中写的那样。变得更宽泛一点吧。

例如&#xff0c;函数 validateEmail(email) 可以&#xff08;除了检查邮件的正确性之外&#xff09;显示一个错误消息并要求重新输入邮件。

额外的动作在函数名称中不应该很明显。一个真正的忍者会使它们在代码中也不明显。

将多个动作加入到一起可以保护您的代码避免重用。

想象一下&#xff0c;另一个开发者只想检查邮箱而不想输出任何信息。你的函数 validateEmail(email) 对他而言就不合适啦。所以他不会找你问一些关于这些函数的事情从而打断你的思考。

总结

上面的所有“建议”都是从真实的代码中提炼而来… 有时&#xff0c;这些代码是由有经验的开发人员写的。也许比你更有经验 ;&#xff09;

  • 遵从其中的一丢丢&#xff0c;你的代码就会变得充满惊喜。

  • 遵从其中的一大部分&#xff0c;你的代码将真正成为你的代码&#xff0c;没有人会想改变它。

  • 遵从所有&#xff0c;你的代码将成为寻求启发的年轻开发人员的宝贵案例。

关于本文

原文&#xff1a;https://zh.Javascript.info/ninja-code#jian-jie-shi-zhi-hui-de-ling-hun

 好文 推 荐 

☞ 

☞ 

好文章&#xff0c;我 在看 

640?wx_fmt&#61;jpeg


推荐阅读
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 微软发布OneNote for WordPress插件,支持一键从OneNote获取内容发布
    微软今日发布了OneNoteforWordPress插件,该插件支持从OneNote一键获取 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了响应式页面的概念和实现方式,包括针对不同终端制作特定页面和制作一个页面适应不同终端的显示。分析了两种实现方式的优缺点,提出了选择方案的建议。同时,对于响应式页面的需求和背景进行了讨论,解释了为什么需要响应式页面。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • Android源码中的Builder模式及其作用
    本文主要解释了什么是Builder模式以及其作用,并结合Android源码来分析Builder模式的实现。Builder模式是将产品的设计、表示和构建进行分离,通过引入建造者角色,简化了构建复杂产品的流程,并且使得产品的构建可以灵活适应变化。使用Builder模式可以解决开发者需要关注产品表示和构建步骤的问题,并且当构建流程发生变化时,无需修改代码即可适配新的构建流程。 ... [详细]
  • 项目运行环境配置及可行性分析
    本文介绍了项目运行环境配置的要求,包括Jdk1.8、Tomcat7.0、Mysql、HBuilderX等工具的使用。同时对项目的技术可行性、操作可行性、经济可行性、时间可行性和法律可行性进行了分析。通过对数据库的设计和功能模块的设计,确保系统的完整性和安全性。在系统登录、系统功能模块、管理员功能模块等方面进行了详细的介绍和展示。最后提供了JAVA毕设帮助、指导、源码分享和调试部署的服务。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
author-avatar
2013丶峰峰最逆天_192
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有