第2章 有意义的名称
2.2 名副其实
- 变量 函数或类的名称都应该已经回复了所有的大问题。它应该告诉你,它为什么会存在,它做什么事,应该怎么用。如果名称需要注释来补充,那就不算是名副其实。
2.3 避免误导
程序员必须避免留下掩藏代码本意的错误线索。
- 1.避免使用与本意相悖的的词: 别用accountArray来指称一组账号,除非它真的是Array类型。
- 2.提防使用差别较小的名称。
- 3.别用人眼误导性名称:小写i和大写O和常量“1”与“0”很相似。
2.4 做有意义的区分
- 废话是另一种没意义的区分。如果有一个Product类。如果还有一个ProductInfo或ProductDate类,那它们的名称虽然不同,意思却无区别
2.5 使用读得出来的名称
2.6 使用可搜索的名称
- 单字母名称和数字常量有个问题,就是很难在大篇文字中找出来。单字母的名称仅用于短方法中的本地变量,名称长短应与其作用域大小相对应。
2.9 类名
- 类名和对象名应该是具体的名称或名词短语,如Customer,WikiPage,Account,AddressParser。避免使用不具体的Manager,Processor,Data,Info这样的类名。类名不应该是动词。
2.10 方法名
- 方法名应当是动词或者动词短语,如postPayment,deletePage,或save
2.12 保持命名风格统一
- fetch,retrieve,get意思上相当相近,如在同一个项目中只使用一个则阅读起来相当明了。
2.16 添加有意义的语境
- 通常添加前缀为读者提供语境,会让读者明白这些变量是某一个更大结构的一部分。
2.17 不要添加没用的语境
- 如果短名称足够清楚,就要比长名称好。别给名称添加不必要的语境。
第3章 函数
3.1 短小
- 函数第一规则就是要短小,每行都不应该有150个字符那么长。函数也不应该有100行那么长,20行封顶最佳。
3.2 只做一件事
- 1.如果函数只是做了该函数名下同一抽象层的步骤,则函数还是做了一件事
- 2.要判断函数是否不止做了一件事,还有一个方法,就是看是否能再拆出一个函数,该函数不仅是单纯的重新诠释其实现。
3.3 每个函数一个抽象层级
- 我们想让代码拥有自顶向下的阅读顺序。我们想要每个函数后面都跟着位于下一抽象层级的函数,这个样子我们查看函数列表时,就能依循抽象层级向下阅读了。
3.4 switch语句
- 我们无法避开switch语句,不过还是能确保每个switch都埋在较低的抽象层级,而且永远不重复
3.5 使用描述性的名称
- 别害怕长名称。长而具有描述性的名称,要比短而费解的名称好。
3.6 函数参数
- 1.对于输入参数最理想的参数数量是零,其次是一,再次是二,应当尽力避免三
- 2.不要通过参数输出(也是就通常的对象改变影响外部对象),我们惯于通过参数输入函数,通过返回值从函数中输出。我们不太期望信息通过参数输出。
- 3.标示参数丑陋不堪。向函数传入布尔值简直就是骇人听闻的做法,着意味着大声宣布本函数不止做一件事。
3.7 无副作用
- 有副作用的函数,都是具有破坏性的,会导致古怪的时序耦合及顺序
3.8 分割指令与询问
- 函数要么做什么事,要么回答什么事,但二者不可兼得。函数应该修改某个对象的状态,或者返回该对象的有关信息。
3.9 使用异常代替返回错误码
- 将指令式函数错误代码返回一反面违反了分割指令与询问,另一方面有可能导致更深层的嵌套解构。使用try/catch将错误处理代码从主路径中分离出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14if(delatePage(page) == E_OK) {
if(registry.deleteReference(page.name) == E_OK) {
if(configKeys.deleteKey(page.name.makeKey()) == E_OK ){
console.log("page deleted");
} else {
console.log("configKey not deleted");
}
} else {
console.log("deletReference from regitry failed");
}
} else {
console.log("delete failed");
return E_ERROR;
}
1 | try{ |
3.9.1 抽离try/catch代码块
- 将try/catch代码块从主体中抽离出来,形成单独的函数。代码更整洁
3.10 别重复自己
- 重复可能是软件中一切的邪恶根源
3.12 如何写出这样的函数
- 写代码和写文章一样都是需要打磨的,一开始的混乱需要一点点的改变
第五章 格式
5.2 垂直格式
- 单个文件代码行数在500行以下平均在100左右是一个很好的建议。
5.2.2 概念间垂直方向上的区隔
- 几乎说有代码都是从上往下读,从左往右读。每行展示一个表达式或一个子句,每组代码行展示一条完整的思路。这些思路用空白行区隔开来。
5.2.3 垂直方向上的靠近
- 如果说空白行隔离概念。靠近的代码行则暗示它们之间紧密关系。所以,紧密相关的代码应该相互靠近。
5.2.4 垂直距离
关系密切的概念应该相互靠近。
- 如变量声明应尽可能靠近其使用位置
- 相关函数:若某个函数调用了另一个,就应该把它们放在一起,而且调用者应该尽可能放在被调用者上面.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17let request = null;
let crawler = null;
function makeResponse(context, request){
let pageName = getPageName(request, "FrontPage");
loadPage(pageName, context);
if(page == null){
return notFoundResponse(context, request);
}else{
return makePageResponse(context);
}
function getPageName(){}
function loadPage(){}
function notFoundResponse(){}
function makePageResponse(){}
} - 概念相关:概念相关的代码应该放在一起。相关性越强,彼此之间的距离就该越短,相关性赖在如函数间调用,或者使用某个变量,也可能来自执行相似操作的一组函数。
5.2.5垂直顺序
- 一般而言,我们想自上向下展示函数调用顺序。也就是说,被调用的函数应该放在执行调用的额函数下面。 我们希望最重要的概念先出来,指望以包括最少细节的方式表述它们,我们希望底层细节最后出来,而不是一开始就沉迷于细节。
5.3.1 水平方向上的间隔与靠近
- 我们使用空格字符将彼此紧密的连接到一起,也用空格字符将相关性较弱的事物隔开。
第6章 对象和数据结构
- 类并不是间断的取赋值,更多是抽象接口,以便用户无需了解数据的实际就能操作数据本体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function Point(){
let x;
let y;
function getX(){
return x;
}
function getY(){
return Y;
}
function getArea(){
return x*y*2;
}
return {
x:getX,
y:getY,
area:getArea
};
}