第1章 有意义的命名
- 废话是另一种没意义的区分
Info,Data就像a,an,the意义,是意义含混的废话
Product——ProductInfo——ProductData
Money——MoneyAccount
CustomInfo——Customer
AccountData——Account
TheMessage——Message
NameString
CustomerObject
第3章 函数
-
标识参数
标识参数丑陋不堪。reander(Boolean isSuite)应该改为reanderForSuite和reanderForSingleTest -
将二元函数转化为一元函数(应该尽量减少或者消灭参数)
二元函数一般比一元函数难以理解,可以通过下面的手法进行转化:
- 在类中将其中一个参数用字段表示,就不用传参了。
- 也可以将方法作为其中一个参数的方法,这种手法实际上是将函数(包括参数)的参数向上提到类中去。
-
将参数编码到函数名称
writeField(name)比write(name)好,因为前者告诉了我们name是一个field
assertExpectedEqualActual(expected, actual)比assertEqual好一些,这大大减轻了记忆参数顺序的负担。 -
无副作用
函数应该只做一件事,但是还是可能会做其他预料之外的事情。 -
参数应该只用作输入
appendFooter(s)会让人疑惑,这个函数是将s添加到某个什么东西后面?还是他把什么东西添加到s后面?s是输入参数还是输出参数?我们得稍微看下函数签名才能知道。
public void appendFooter(StringBuffer report)
面向对象中对输出参数的大部分需求以及小时了,因为 this也有输出参数的意味在内,最好是下面这样调用:
report.appendFooter
-
分隔指令与询问
只做一件事。函数要么做什么事,要么回答什么事,但二者不可兼得。不然会引起一些混乱,因为做什么事和回答什么事组合在一起,可能引起多种猜测。 -
使用异常代替错误码
可以看到前者不会那么混乱,流程比较正常,跟平常的代码一样
-
错误处理就是一件事
void func(){
try{
XXX;
}catch{
YYY;
}
}
第4章 注释
-
注释很烂
只有在表达失败的时候才需要注释;程序员不能维护注释,只有代码能忠实地告诉你它做的事 -
函数名或者变量名都可以起到注释的作用
第5章 格式
-
垂直距离
若某个函数调用了另外一个,就应该把它们放在一起,而且调用者应该尽可能放在被调用者上面。 -
为什么调用者要放到上面?
我们指望最重要的概念先出来,细节在后面,查看前面的函数可能就知道了代码的意图。 -
概念相关
概念相关的代码应该放到一起。 -
水平方向上的区隔与靠近
我们使用空格字符将彼此紧密相关的事务连接到一起,也用空格字符把习惯性较弱的事物分隔开。
赋值语句的左边和右边用空格隔开
第6章 对象和数据结构
-
数据抽象
隐藏实现并非只是在变量之间放上一个函数层那么简单。隐藏实现关乎抽象!用户无需了解数据的实现就能操作数据本体。 -
数据、对象的反对称性
这小节说的是过程式代码和面向对象代码的区别:
过程式代码就像集体主义,面向对象代码就像个人主义。
过程式代码函数书写的时候,操作全体数据(结构体),手把手,集体进行书写。如果添加多一个对象,那么所有函数都需要重新书写。
面向对象代码函数书写的时候,尽量让全体数据(对象)操作自己(对象.方法()),添加多一个数据(类),那么所有函数不需要重新书写,因为有多态。
过程式代码:方便添加函数,不方便添加数据。
面向对象代码:方便添加数据,不方便添加函数。 -
德墨忒耳律
方法不应调用由任何函数返回的对象的方法,换而言之,只跟朋友谈话,不与陌生人(朋友的朋友)谈话。因为这样暴露了类的内部结构。书中举了这样的例子:final String outputDir = ctxt.getOptions().getScratchDir()...
我们取得这些内部结构,往往是为了用他们去做一些事情。类可以做的这些事情作为方法放在类的内部,这样外部也就不用去获取类的内部结构。
第7章 错误处理
- 别返回null值
返回一个null对象,在其中定义特殊情况的处理,这样程序中就不会有很多null判断的嵌套语句。
第17章 味道与启发
G8:信息过多
通过限制信息来控制耦合度
G18:不恰当的静态方法
非静态方法有一个好处就是可以实现多态。
G27:结构甚于约定
多态代替switch的时候,每次派生类都需要实现基类的功能,但是switch分支却没有这样的要求,特别是如果有多个switch,也就是多个抽象方法的时候,这样的结构更加使人不会犯错,少写一些代码。
网友评论