乐趣区

关于前端:提高代码可读性的8个技巧

编程有很大一部分工夫是在浏览代码,不仅要浏览本人的代码,而且要浏览他人的代码。因而,可读性良好的代码可能大大提高编程效率。可读性良好的代码往往会让代码架构更好,因为程序员更违心去批改这部分代码,而且也更容易批改。只有在外围畛域为了效率才能够放弃可读性,否则可读性是第一位。

用名字代表代码含意
一些比拟有表达力的单词:

单词
可代替单词

send
deliver、dispatch、announce、distribute、route

find
search、extract、locate、recover

start
launch、create、begin、open

make
create、set up、build、generate、compose、add、new

应用 i、j、k 作为循环迭代器的名字过于简略,user_i、member_i 这种名字会更有表达力。因为循环档次越多,代码越难了解,有表达力的迭代器名字可读性会更高。
为名字增加形容词等信息能让名字更具备表达力,然而名字也会变长。名字长短的准则是:作用域越大,名字越长。因而只有在短作用域能力应用一些简略名字。
名字不能带来歧义
起完名字要思考一下他人会对这个名字有何解读,会不会误会了本来想表白的含意。
布尔相干的命名加上 is、can、should、has 等前缀。

用 min、max 示意数量范畴;
用 first、last 示意拜访空间的蕴含范畴;
begin、end 示意拜访空间的排除范畴,即 end 不蕴含尾部。

良好的代码格调
适当的空行和缩进。
排列参差的正文:
int a = 1; // 正文
int b = 11; // 正文
int c = 111; // 正文

语句程序不能随便,比方与 html 表单相关联的变量的赋值应该和表单在 html 中的程序统一。
为何编写正文
浏览代码首先会留神到正文,如果正文没太大作用,那么就会节约代码浏览的工夫。那些能间接看出含意的代码不须要写正文,特地是不须要为每个办法都加上正文,比方那些简略的 getter 和 setter 办法,为这些办法写正文反而让代码可读性更差。
不能因为有正文就轻易起个名字,而是争取起个好名字而不写正文。
能够用正文来记录采纳以后解决办法的思考过程,从而让读者更容易了解代码。
正文用来揭示一些非凡状况。
用 TODO 等做标记:

标记
用法

TODO
待做

FIXME
待修复

HACK
毛糙的解决方案

XXX
危险!这里有重要的问题

如何编写正文
尽量简洁明了:
// The first String is student’s name
// The Second Integer is student’s score
Map<String, Integer> scoreMap = new HashMap<>();

// Student’s name -> Student’s score
Map<String, Integer> scoreMap = new HashMap<>();

增加测试用例来阐明:
// …

// Example: add(1, 2), return 3

int add(int x, int y) {
return x + y;
}

应用专业名词来缩短概念上的解释,比方用设计模式名来阐明代码。
进步控制流的可读性
条件表达式中,左侧是变量,右侧是常数。比方上面第一个语句正确:
if (len < 10)
if (10 > len)

只有在逻辑简略的状况下应用 ? : 三目运算符来使代码更紧凑,否则应该拆分成 if / else;
do / while 的条件放在前面,不够简单明了,并且会有一些蛊惑的中央,最好应用 while 来代替。
如果只有一个 goto 指标,那么 goto 尚且还能承受,然而过于简单的 goto 会让代码可读性特地差,应该防止应用 goto。
在嵌套的循环中,用一些 return 语句往往能缩小嵌套的层数。
拆分长表达式
长表达式的可读性很差,能够引入一些解释变量从而拆分表达式:
if line.split(‘:’)[0].strip() == “root”:

...

username = line.split(‘:’)[0].strip()
if username == “root”:

...

应用摩根定理简化一些逻辑表达式:
if (!a && !b) {

...

}

if (!(a || b)) {

...

}

变量与可读性
去除控制流变量。在循环中通过应用 break 或者 return 能够缩小控制流变量的应用。
boolean done = false;

while (/ condition / && !done) {

if (…) {

done = true;
continue;

}
}

while(/ condition /) {

if (…) {

break;

}
}

减小变量作用域。作用域越小,越容易定位到变量所有应用的中央。
JavaScript 能够用闭包减小作用域。以下代码中 submit_form 是函数变量,submitted 变量管制函数不会被提交两次。第一个实现中 submitted 是全局变量,第二个实现把 submitted 放到匿名函数中,从而限度了起作用域范畴。
submitted = false;

var submit_form = function(form_name) {
if (submitted) {

return;

}
submitted = true;
};

var submit_form = (function() {
var submitted = false;
return function(form_name) {

if(submitted) {return;}
submitted = true;

}
}()); // () 使得外层匿名函数立刻执行

JavaScript 中没有用 var 申明的变量都是全局变量,而全局变量很容易造成蛊惑,因而该当总是用 var 来申明变量。
变量定义的地位该当离它应用的地位最近。
实例解析
在一个网页中有以下文本输出字段:
<input type = “text” id = “input1” value = “a”>
<input type = “text” id = “input2” value = “b”>
<input type = “text” id = “input3” value = “”>
<input type = “text” id = “input4” value = “d”>

当初要承受一个字符串并把它放到第一个空的 input 字段中,初始实现如下:
var setFirstEmptyInput = function(new_alue) {
var found = false;
var i = 1;
var elem = document.getElementById(‘input’ + i);
while (elem != null) {

if (elem.value === '') {
  found = true;
  break;
}
i++;
elem = document.getElementById('input' + i);

}
if (found) elem.value = new_value;
return elem;
}

以上实现有以下问题:

found 能够去除;
elem 作用域过大;
能够用 for 循环代替 while 循环;

var setFirstEmptyInput = function(new_value) {
for (var i = 1; true; i++) {

var elem = document.getElementById('input' + i);
if (elem === null) {return null;}
if (elem.value === '') {
  elem.value = new_value;
  return elem;
}

}
};

抽取函数
工程学就是把大问题拆分成小问题再把这些问题的解决方案放回一起。
首先应该明确一个函数的高层次指标,而后对于不是间接为了这个指标工作的代码,抽取进去放到独立的函数中。
介绍性的代码:
int findClostElement(int[] arr) {

int clostIdx;
int clostDist = Interger.MAX_VALUE;
for (int i = 0; i < arr.length; i++) {
    int x = ...;
    int y = ...;
    int z = ...;
    int value = x * y * z;
    int dist = Math.sqrt(Math.pow(value, 2), Math.pow(arr[i], 2));
    if (dist < clostDist) {
        clostIdx = i;
        clostDist = value;
    }
}
return clostIdx;

}

以上代码中循环局部次要计算间隔,这部分不属于代码高层次指标,高层次指标是寻找最小间隔的值,因而能够把这部分代替提取到独立的函数中。这样做也带来一个额定的益处有:能够独自进行测试、能够疾速找到程序谬误并批改。
public int findClostElement(int[] arr) {

int clostIdx;
int clostDist = Interger.MAX_VALUE;
for (int i = 0; i < arr.length; i++) {int dist = computDist(arr, i);
    if (dist < clostDist) {
        clostIdx = i;
        clostDist = value;
    }
}
return clostIdx;

}

并不是函数抽取的越多越好,如果抽取过多,在浏览代码的时候可能须要一直跳来跳去。只有在以后函数不须要去理解某一块代码细节而可能表白其内容时,把这块代码抽取成子函数才是好的。
函数抽取也用于减小代码的冗余。
一次只做一件事
只做一件事的代码很容易让人晓得其要做的事;
根本流程:列出代码所做的所有工作;把每个工作拆分到不同的函数,或者不同的段落。
用自然语言表述代码
先用自然语言书写代码逻辑,也就是伪代码,而后再写代码,这样代码逻辑会更清晰。
缩小代码量
不要适度设计,编码过程会有很多变动,适度设计的内容到最初往往是无用的。
多用规范库实现。

最初

为了不便其余设施和平台的小伙伴观看往期文章,链接奉上:

牛客 知乎 开源中国 CSDN 思否 掘金 InfoQ 简书 博客园 慕课 51CTOhelloworld 腾讯开发者社区 阿里开发者社区

看完如果感觉有帮忙,欢送 点赞、珍藏 关注

退出移动版