本文章学习自英文版书籍《The Art of Readable Code》。
变量不恰当使用会导致很多问题:
1、变量越多,脑袋就很难全部装下他们
2、变量作用域越大,你就更难追踪他们
3、变量变化的地方越多,你就越难追踪他
- 减少不必要的中间变量
var remove_one = function (array, value_to_remove) {
var index_to_remove = null;
for (var i = 0; i < array.length; i += 1) {
if (array[i] === value_to_remove) {
index_to_remove = i;
break;
}
}
if (index_to_remove !== null) {
array.splice(index_to_remove, 1);
}
};
修改后的版本:
var remove_one = function (array, value_to_remove) {
for (var i = 0; i < array.length; i += 1) {
if (array[i] === value_to_remove) {
array.splice(i, 1);
return;
}
}
};
- 减少变量名的作用域,解放你的大脑,类也是一个mini-global。
1尽量少的类属性
2让方法是static
3将大的类分解为小的类
从:
class LargeClass {
string str_;
void Method1() {
str_ = ...;
Method2();
}
void Method2() {
// Uses str_
}
// Lots of other methods that don't use str_ ...
};
到,这样就很容易追中str的变化
class LargeClass {
void Method1() {
string str = ...;
Method2(str);
}
void Method2(string str) {
// Uses str
}
// Now other methods can't see str.
};
- 将变量定义尽量靠后
def ViewFilteredReplies(original_id):
filtered_replies = []
root_message = Messages.objects.get(original_id)
all_replies = Messages.objects.select(root_id=original_id)
root_message.view_count += 1
root_message.last_view_time = datetime.datetime.now()
root_message.save()
for reply in all_replies:
if reply.spam_votes <= MAX_SPAM_VOTES:
filtered_replies.append(reply)
return filtered_replies
def ViewFilteredReplies(original_id):
root_message = Messages.objects.get(original_id)
root_message.view_count += 1
root_message.last_view_time = datetime.datetime.now()
root_message.save()
all_replies = Messages.objects.select(root_id=original_id)
filtered_replies = []
for reply in all_replies:
if reply.spam_votes <= MAX_SPAM_VOTES:
filtered_replies.append(reply)
return filtered_replies
认识你的代码
-
提炼出不相关的代码
- Look at a given function or block of code, and ask yourself, “What is the high-level goal
of this code?” - For each line of code, ask, “Is it working directly to that goal? Or is it solving an unrelated
subproblem needed to meet it?” - If enough lines are solving an unrelated subproblem, extract that code into a separate
function.
- 重新封装ugly接口
但封装得太细也不行
一次只做一件事
把想法转化为代码
先用英语描述下程序的过程在写程序
写更少的代码
不要实现那些没有必要的功能
仔细思考和分解需求
熟悉库
测试
- 这个测试错在哪里?看完本章你就会找出8个错误
void Test1() {
vector<ScoredDocument> docs;
docs.resize(5);
docs[0].url = "http://example.com";
docs[0].score = -5.0;
docs[1].url = "http://example.com";
docs[1].score = 1;
docs[2].url = "http://example.com";
docs[2].score = 4;
docs[3].url = "http://example.com";
docs[3].score = -99998.7;
docs[4].url = "http://example.com";
docs[4].score = 3.0;
SortAndFilterDocs(&docs);
assert(docs.size() == 3);
assert(docs[0].score == 4);
assert(docs[1].score == 3.0);
assert(docs[2].score == 1);
}
隐藏那些不重要的细节
上面赋值的部分可以用函数封装起来使用增强版的断言
输入要做到小而全
没有负数
CheckScoresBeforeAfter("1, 2, 3", "3, 2, 1");
没有必要的复杂
CheckScoresBeforeAfter("123014, -1082342, 823423, 234205, -235235",
"823423, 234205, 123014");
yes!
CheckScoresBeforeAfter("-5, 1, 4, -99998.7, 3", "4, 3, 1");
- 短小精悍
CheckScoresBeforeAfter("2, 1, 3", "3, 2, 1"); // Basic sorting
CheckScoresBeforeAfter("0, -0.1, -10", "0"); // All values < 0 removed
CheckScoresBeforeAfter("1, -2, 1, -2", "1, 1"); // Duplicates not a problem
CheckScoresBeforeAfter("", ""); // Empty input OK
- 最好还有一个C++的项目和附录......没有看完