首页 > 其他 > 详细

代码为什么要易于理解

时间:2015-04-28 17:42:50      阅读:213      评论:0      收藏:0      [点我收藏+]

? ?

"Code should be written to minimize the time it would take for someone else to understand it."

日常工作的事实是:

写代码前的思考和看代码的时间远大于真正写的时间

读代码是很平常的事情,不论是别人的,还是自己的,半年前写的可认为是别人的代码

代码可读性高,很快就可以理解程序的逻辑,进入工作状态

行数少的代码不一定就容易理解

代码的可读性与程序的效率、架构、易于测试一点也不冲突

整本书都围绕"如何让代码的可读性更高"这个目标来写。这也是好代码的重要标准之一。

如何命名

变量名中应包含更多信息

使用含义明确的词,比如用download而不是get,参考以下替换方案:

1

2

3

4

send -> deliver, dispatch, announce, distribute, route

find -> search, extract, locate, recover

start -> lanuch, create, begin, open

make -> create,set up, build, generate, compose, add, new

避免通用的词

像tmp和retval这样词,除了说明是临时变量和返回值之外,没有任何意义。但是给他加一些有意义的词,就会很明确:

1

2

3

tmp_file = tempfile.NamedTemporaryFile()

...

SaveData(tmp_file, ...)

不使用retval而使用变量真正代表的意义:

1

sum_squares += v[i]; // Where‘s the "square" that we‘re summing? Bug!

嵌套的for循环中,i、j也有同样让人困惑的时候:

1

2

3

4

for (int i = 0; i < clubs.size(); i++)

for (int j = 0; j < clubs[i].members.size(); j++)

for (int k = 0; k < users.size(); k++) if (clubs[i].members[k] == users[j])

cout << "user[" << j << "] is in club[" << i << "]" << endl;

换一种写法就会清晰很多:

1

if (clubs[ci].members[mi] == users[ui]) # OK. First letters match.

所以,当使用一些通用的词,要有充分的理由才可以。

使用具体的名字

CanListenOnPort就比ServerCanStart好,can start比较含糊,而listen on port确切的说明了这个方法将要做什么。

--run_locally就不如--extra_logging来的明确。

增加重要的细节,比如变量的单位_ms,对原始字符串加_raw

如果一个变量很重要,那么在名字上多加一些额外的字就会更加易读,比如将string id; // Example: "af84ef845cd8"换成string hex_id;。

1

2

3

4

Start(int delay) --> delay delay_secs

CreateCache(int size) --> size size_mb

ThrottleDownload(float limit) --> limit max_kbps

Rotate(float angle) --> angle degrees_cw

更多例子:

1

2

3

4

password -> plaintext_password

comment -> unescaped_comment

html -> html_utf8

data -> data_urlenc

对于作用域大的变量使用较长的名字

在比较小的作用域内,可以使用较短的变量名,在较大的作用域内使用的变量,最好用长一点的名字,编辑器的自动补全都可以很好的减少键盘输入。对于一些缩写前缀,尽量选择众所周知的(如str),一个判断标准是,当新成员加入时,是否可以无需他人帮助而明白前缀代表什么。

合理使用_、-等符号,比如对私有变量加_前缀。

1

2

3

4

5

6

7

8

var x = new DatePicker(); // DatePicker() 是类的"构造"函数,大写开始

var y = pageHeight(); // pageHeight() 是一个普通函数

?

var $all_images = $("img"); // $all_images 是jQuery对象

var height = 250; // height不是

?

//id和class的写法分开

<div id="middle_column" class="main-content"> ...

命名不能有歧义

命名的时候可以先想一下,我要用的这个词是否有别的含义。举个例子:

1

results = Database.all_objects.filter("year <= 2011")

现在的结果到底是包含2011年之前的呢还是不包含呢?

使用min、max代替limit

1

2

3

4

5

6

7

CART_TOO_BIG_LIMIT = 10

if shopping_cart.num_items() >= CART_TOO_BIG_LIMIT:

Error("Too many items in cart.")

?

MAX_ITEMS_IN_CART = 10

if shopping_cart.num_items() > MAX_ITEMS_IN_CART:

Error("Too many items in cart.")

对比上例中CART_TOO_BIG_LIMIT和MAX_ITEMS_IN_CART,想想哪个更好呢?

使用first和last来表示闭区间

1

2

3

4

print integer_range(start=2, stop=4)

# Does this print [2,3] or [2,3,4] (or something else)?

?

set.PrintKeys(first="Bart", last="Maggie")

first和last含义明确,适宜表示闭区间。

使用beigin和end表示前闭后开(2,9))区间

1

2

3

PrintEventsInRange("OCT 16 12:00am", "OCT 17 12:00am")

?

PrintEventsInRange("OCT 16 12:00am", "OCT 16 11:59:59.9999pm")

上面一种写法就比下面的舒服多了。

Boolean型变量命名

1

bool read_password = true;

这是一个很危险的命名,到底是需要读取密码呢,还是密码已经被读取呢,不知道,所以这个变量可以使用user_is_authenticated代替。通常,给Boolean型变量添加is、has、can、should可以让含义更清晰,比如:

1

2

SpaceLeft() --> hasSpaceLeft()

bool disable_ssl = false --> bool use_ssl = true

符合预期

1

2

3

4

5

6

7

public class StatisticsCollector {

public void addSample(double x) { ... }

public double getMean() {

// Iterate through all samples and return total / num_samples

}

...

}

在这个例子中,getMean方法遍历了所有的样本,返回总额,所以并不是普通意义上轻量的get方法,所以应该取名computeMean比较合适。

漂亮的格式

写出来漂亮的格式,充满美感,读起来自然也会舒服很多,对比下面两个例子:

1

2

3

4

5

6

7

8

9

10

11

12

class StatsKeeper {

public:

// A class for keeping track of a series of doubles

void Add(double d); // and methods for quick statistics about them

private: int count; /* how many so far

*/ public:

double Average();

private: double minimum;

list<double>

past_items

;double maximum;

};

什么是充满美感的呢:

1

2

3

4

5

6

7

8

9

10

11

12

// A class for keeping track of a series of doubles

// and methods for quick statistics about them.

class StatsKeeper {

public:

void Add(double d);

double Average();

private:

list<double> past_items;

int count; // how many so far

double minimum;

double maximum;

};

考虑断行的连续性和简洁

这段代码需要断行,来满足不超过一行80个字符的要求,参数也需要注释说明:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class PerformanceTester {

public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(

500, /* Kbps */

80, /* millisecs latency */

200, /* jitter */

1 /* packet loss % */);

?

public static final TcpConnectionSimulator t3_fiber = new TcpConnectionSimulator(

45000, /* Kbps */

10, /* millisecs latency */

0, /* jitter */

0 /* packet loss % */);

?

public static final TcpConnectionSimulator cell = new TcpConnectionSimulator(

100, /* Kbps */

400, /* millisecs latency */

250, /* jitter */

5 /* packet loss % */);

}

代码为什么要易于理解

原文:http://www.cnblogs.com/rootbin/p/4463280.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!