读书笔记
来源:互联网 发布:全国汽车保有量数据 编辑:程序博客网 时间:2024/05/22 02:19
作者: 戈峰 欧永广 郑德立 张雁
1. 《实现模式》
I.实现模式价值观
Ø 沟通:代码是与人沟通的桥梁
Ø 简单:通常简单和沟通都是不可分割的
Ø 灵活性:灵活性的提高可能以复杂性的提高为代价
II.实现模式原则
Ø 局部化影响:组织代码结构时,保证变化只会产生局部性影响
Ø 最小化重复
Ø 逻辑与数据捆绑:逻辑与逻辑所处理的数据放在一起,修改它们只会影响局部化
Ø 对称性:对称性是指概念上的对称,而不是图形上的对称
Ø 声明式表达:尽可能声明式地表达出意图
Ø 变化率:具有相同变化率的逻辑、数据放在一起,具有不同变化率的逻辑、数据隔离
III.类
Ø 简单的超类名:类名需权衡“简短”和“表现力”,重要的类尽量用一个单词命名
Ø 限定性的子类名:子类名需权衡“长度”和“表现力”,通常在超类名的基础上扩展一两个单词
Ø 抽象接口:针对接口编程,不要针对实现编程
Ø interface命名:一种风格像给类命名一样;另一种风格在名字加前缀“I”
Ø 子类:优点是抽取继承体系中共同实现的部分,达到代码复用、最小化重复功效;缺点是不能适应不断变化的逻辑,需要理解继承体系链,依赖超类实现
Ø 实现器:相比于过程式的实现模式,面向对象的实现模式分离了意图与实现,逻辑清晰且更具有灵活性
Ø 内部类:有时候需要包装一部分计算逻辑,但又不愿意创建全新的类,声明一个内部类是比较合适的选择
Ø 可插拔的选择器:利用反射机制实现可插拔的选择器
IV.状态
Ø 状态管理:把相似的状态放在一起,确保不同的状态被彼此分离
Ø 直接访问:直接访问以清晰的代价损失了灵活性,通常只在访问器方法(可以加上构造器)中使用直接存储;只在类及其子类(可以扩大到类所在的包)的内部使用直接存储
Ø 间接访问:间接访问以灵活性的代价损失了清晰,通常允许在类(及其内部类)中直接访问,其他的使用者必须间接访问
Ø 局部变量:遵循“信息最小扩散”原则,尽可能在延迟以及确实需要时才声明局部变量
Ø 字段:在类的最前面或者最后面声明
Ø 参数:比起从一个对象永久地引用另一个对象,参数带来的耦合要弱得多
Ø 参数对象:如果同一组参数被放在一起传递给很多方法,应该考虑封装成一个对象传递
Ø 常量:使用常量可以避免一大堆相同的错误且语义表达更清晰
Ø 及早初始化:当初始化开销不大时,及早初始化可以保证变量在使用前一定被初始化过
Ø 延迟初始化:当初始化开销较大时,延迟初始化是个比较好的选择
VI.方法
Ø 组合方法:组合方法由调用其他方法来而成,被调用方法均应该大致属于同一抽象层次
Ø 揭示意图的名称:从调用者的角度出发,根据调用者使用该方法的意图来给方法命名
Ø 方法可见性:谨慎地暴露方法,从最严格的可见性开始,有必要时再暴露
Ø 方法对象:假设一个方法参数很多、方法体很长,并且用了很多临时变量,考虑使用方法对象模式
Ø 覆盖方法:子类方法应该只调用超类的同名方法,且超类方法应尽可能简单
Ø 重载方法:重载方法的目的应该一致,不一致的地方应仅限于参数类型
Ø 方法返回类型:选择尽可能表达你意图的返回类型,同时在符合意图的前提下尽可能返回抽象的类型
Ø 方法注释:必要时再写注释
Ø 调试输出方法:投入精力实现高质量的调试输出方法往往能得到很好的回报
Ø 转换方法:如果需要表达类型相近的对象之间的转换,且转换数量有限,那么应该把转换表达成源对象中的一个方法
Ø 转换构造器:转换构造器适合于将一个源对象转换为多个目标对象
Ø 卫语句:卫语句适合表达其中一个控制流比其他的更重要,特别适用多个条件的情况
2. 《代码整洁之道》
I.函数
a) 短小
Ø 函数的第一规则是要短小。第二条规则是还要更短小。
Ø 单个函数的长度以20行封顶最佳。
Ø If语句、else语句、while语句等,其中的代码块应该只有一行函数调用语句。
b) 只做一件事
Ø 函数应该做一件事。
Ø 做好这件事。
Ø 只做这件事。
Ø 怎么才算“一件事”,要依靠抽象层级的概念来做判断。
c) 每个函数一个抽象层级
Ø 多个子函数是否处于同一抽象层级,是函数是否只做了一件事的判断标准。
Ø 函数中混杂不同的抽象层级,往往让人迷惑。
II.错误处理
a) 使用异常代替返回错误码(参见《代码整洁之道》,42页、96页)
Ø 函数要么做事(指令),要么回答问题(询问),二者不可兼得。返回错误码的指令式函数违反了指令与询问分离的规则。
Ø 返回错误码导致更深层次的嵌套调用
Ø 使用抛异常,错误处理代码就能从主路径代码中分离出来,得到简化
Ø try块应该只有一行调用正常处理函数的代码,catch块里也应该只有一行调用异常处理函数的代码
Ø 如果try在某个函数中存在,它就该是这个函数里的第一个单词,而且在catch/finally代码块后面也不该有其他内容。
b) 别返回null值(参见《代码整洁之道》,101页)
Ø 一个函数会返回null,就是要求调用者必须检查null,只要有一处没检查null值,程序就会失控。
Ø 建议若函数返回值是一个集合,则用空集合(如,空的List)代替null返回;若返回值是数组,则用长度为零的数组代替null。
c) 别传递null值(参见《代码整洁之道》,102页)
Ø 应该约定,禁止调用者传入null参数。因为在大多数编程语言中,没有良好的方法能对付调用者意外传入的null值。
III.边界
a) 封装Ice代码(参见《代码整洁之道》,106页)
在需要调用Ice服务的模块里,为Ice生成的代码做一层封装,有利于隔离Ice接口的变动对客户端代码的影响。
public class IxxxProxy
{
private IceServiceData m_serviceData;
private Ice.Communicator m_ic;
private xxxInterfacePrxm_proxy;
private String m_objectStr;
public boolean init(String serverRoleName, IceServiceData data)
{
// 初始化m_proxy和异常处理的代码
}
public void destroy()
{
if (m_ic !=null)
{
m_ic.destroy();
}
}
// 封装的其他Ice接口函数
}
例如,对codeice.xxx.xxxInterfacePrx类的封装如下:
codeice.xxx.xxxInterfacePrx.getQueryRequest()函数的封装如下:
public xxxRequestDTO getxxxRequest(long requestId)throws Exception
{
if (null ==m_proxy)
{
throw new Exception("m_proxy is null");
}
try
{
returnm_proxy.getxxxRequest(requestId);
}
catch (GenericError ge)
{
// 处理GenericError异常
}
catch (Ice.LocalException ex)
{
// 处理Ice.LocalException异常
}
catch (Exception e)
{
// 处理Exception异常
}
}
在做Ice接口封装时,可以只封装那些本客户端需要调用的Ice接口,以免将所有Ice服务端的接口暴露出来,增加误用的可能。
IV.类
a) 类应该短小(参见《代码整洁之道》,126页)
Ø 单一职责原则:类应该有且只有一条修改的理由。
Ø 系统应该由许多短小的类而不是少量巨大的类组成。每个小类封装一个权责,只有一个修改原因,并与少数其他类一起协同达成期望的系统行为。
Ø 类应该只有少量实体变量。
Ø 类中的每个方法都应该操作一个或多个这种变量,且方法操作的变量越多,类的内聚性越高。
Ø 拆分低内聚的大类为若干高内聚的小类。通常,将大函数切分为小函数就会诱导这种大类的拆分。
3. 《程序员修炼》
I. 不要重复
系统中每一项知识都必须具有单一、无歧义、权威的表示。说得直白点,编写的类不要重复、方法不要重复、代码尽量不要重复。如果发生重复,要尽量消重,例如提取公共方法、公共类,形成框架等。
II. 调整心态
Ø Fix the problem, not the blame!–当程序出现bug时,不要产生“这不可能发生”的情绪,要认真修复bug,不要责怪肇事者。
Ø 人不可能写出完美的程序,这是现实,必须接受。
III. 按合约设计
Ø 合约既规定了你的权利和责任,也规定了对方的权利与责任。正确的程序是不多不少,做它声明要做的事情的程序。用文档记载声明要做的事情,并进行校验
Ø 在“正交性”中,建议编写“羞怯”的代码。尽量编写“懒惰”的代码,对在开始时接受的东西要严格,而允诺返回的东西要尽可能少。
Ø 在做设计时简单地列举输入域的范围是什么、边界条件是什么、方法允诺交付什么
IV. 调用者负责参数检查
方法调用时,需要进行参数检查,如果要对参数进行任何显示的检查,就必须由调用者来完成,因为被调用者自身永远也不会看到违反了其前置条件的参数。
理解异常情况
异常很少应作为程序的正常流程的一部分使用:异常保留给意外事件
4. 《代码重构》
I. 重新组织函数
Ø 提炼函数:将这段代码放进一个独立函数中,并让函数名称解释该函数的用途
Ø 内联函数:在函数调用点插入函数本体,然后移除该函数
Ø 内联临时变量:将所有对该变量的引用动作,替换为对它赋值的那个表达式自身
Ø 以查询取代临时变量:将这个表达式提炼到一个独立函数中
Ø 引入解释性变量:将该复杂表达式的结果放进一个临时变量,用变量名解释表达式用途
Ø 分解临时变量:针对每次赋值,创造一个独立、对应的临时变量
Ø 移除对参数的赋值:以一个临时变量取代该参数的位置
Ø 以函数对象取代函数:将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数
Ø 替换算法:将函数本体替换为另一个算法
II.在对象之间搬移特性
Ø 搬移函数:在该函数最常引用的类中建立一个有着类似行为的新函数,将旧函数变成一个单纯的委托函数,或是将旧函数完全移除
Ø 搬移字段:在目标类新建一个字段,修改源字段的所有用户,令它们改用新字段
Ø 提炼类:建立一个新类,将相关的字段和函数从旧类搬移到新类
Ø 将类内联化:将这个类的所有特性搬移到另一个类中,然后移除原类
Ø 隐藏委托关系:在服务类上建立客户所需的所有函数,用以隐藏委托关系
Ø 移除中间人:让客户直接调用受托类
Ø 引入外加函数:在客户类中建立一个函数,并以第一参数形式传入一个服务类实例
Ø 引入本地扩展:建立一个新类,使它包含这些额外函数,让这个扩展品成为源类的子类或包装类
III.重新组织数据
Ø 自封装字段:为这个字段尽力取值/设值函数,并且只以这些函数来访问字段
Ø 以对象取代数据值:将数据项变成对象
Ø 将值对象改为引用对象
Ø 将引用对象改为值对象
Ø 以对象取代数组:以对象替换数组,对于数组中的每个元素以一个字段来表示
Ø 复制“被监视数据”
Ø 将单向关联改为双向关联:添加一个反向指针,并使修改函数能够同时更新两条连接
Ø 将双向关联改为单向关联:去除不必要的关联
Ø 以字面常量取代魔法数
Ø 封装字段:将它声明为private,并提供相应的访问函数
Ø 封装集合
Ø 以数据类取代记录
Ø 以类取代类型码:以一个新的类替换该数值类型码
Ø 以子类取代类型码:以子类取代这个类型码
Ø 以State/Strategy取代类型码
Ø 以字段取代子类:修改这些函数,使它们返回超类中的某个字段,然后销毁子类
IV.简化条件表达式
Ø 分解条件表达式:从if、then、else三个段落中分别提炼出独立函数
Ø 合并条件表达式:将这些测试合并为一个条件表达式,并提炼成为一个独立函数
Ø 合并重复的片段:将这段重复代码搬移到条件表达式之外
Ø 移除控制标记:以break语句或return语句取代控制标记
Ø 以卫语句取代嵌套条件表达式
Ø 以多态取代条件表达式
Ø 引入null对象:将null值替换为null对象
Ø 引入断言
V.简化函数调用
VI.处理概括关系
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- >读书笔记
- >读书笔记
- 读书笔记
- 读书笔记--
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- 读书笔记
- php使用curl远程下载微信的图片到自己的服务器
- python项目打包成可执行的exe文件
- HACM2039 三角形
- Python学习笔记:list,tuple和str
- poj 3948 迷宫问题 且行且珍惜--
- 读书笔记
- How to justify if a windows program is 32 bit or 64 bit
- CodeForces 703D Mishka and Interesting sum
- 操作系统进程与线程
- 利用搜索法求百万以内的素数
- WIN7(64bit)编译运行gh0st3.6
- Quartz使用技巧总结
- Android ExpandableListView使用指南
- 整理笔记---Hibernate二级缓存