chapter-1
- 例子1:
- 方法a(){根据不同类型电影,租期长短,计算价格,并输出}
- 可能变化:增加/改变输出样式,电影类型分类可能会变,计费标准会变。
- 只有优秀的人才能写出人易读的代码。机器永远会理解。
- 方法/变量名称,是代码清晰的关键。
方法应该放在,它使用的数据所属对象内,这样依赖低
例子2:
- 一个电影可以在生命周期内修改分类,一个对象却不能修复所属类。
- 不能创建电影子类,但可以创建价格子类。replace type with state/strategy,
- 把type相关行为移到state/strategy内部。
- 模式取决于:state:代表电影的某个状态,strategy代表计费策略。反映对结构的想法。
面向对象:思考对象的职责。
- 重构可以取代预先设计(不要过度设计,简单即美),重构随时随地。
- 重复是万恶之源。事不过三,三则重构。switch意味着重复,少用
chapter-6
- extract method的判断标准:以它“做什么”命名,不是怎么做。
- replace temp with query :以查询方法代替临时变量,临时变量时局部的,为了使用它,它会驱使你写更长的方法
double getPrice(){ //两个临时变量
const int basePrice = m_quanity * m_itemPrice;
double discountFactor;
if (basePrice > 1000){
discountFactor = 0.95
}else{
discountFactor = 0.98
}
return basePrice * discountFactor;
}
//用方法替换临时变量
double getPrice(){
return basePrice() * discountFactor();
}
int basePrice(){
return m_quanity * m_itemPrice;
}
double discountFactor(){
if (basePrice() > 1000){
return 0.95
}else{
return 0.98
}
}
- introduce explaining variable 解释性变量
if( (platform.indexOf("MAC") > -1) && isIEBrower){...}
//替换成
boolean isMacOs = platform.indexOf("MAC") > -1;
if( isMacOs && isIEBrower){...}
chapter-7
- 如果一个类承担太多责任,考虑extract class,如果只有这个类使用新类,考虑inline class
chapter-8
- 状态码
- 不变、且行为相同,不用抽取。比如性别男女。
- 不变、行为不同,抽取子类。
- 可变,生命周期内可变、或其他原因不能继承,使用state/stratege模式
chapter-9 简化方法调用
- 查询、修改方法分离。getTotalAndSetSum()–>getTotal(),setSum();
- 参数超过4个时,使用对象封装参数。
- 一个业务类,查询对象可以有多个类,不要包含无用的属性,那会带来理解困难。
- netty的网络配置项,有很多属性,但是提供了默认值,即使不设置也没问题。
- 工厂方法:根据类型码,提供一组类的,对象构造方式。接口简单统一。
- 如果有向下转型的代码,首先考虑是否可以用模板类代替。
- 不恰当的继承,改用组合:
- 超类中许多方法并不真正适用于子类,子类通过父类获得的接口并未真正反映出子类的功能,意图混淆
- 从超类中继承了一大堆子类并不需要的数据
- 你可能发现超类中的某些protected函数对子类并没有什么意义。
- 不恰当的组合,改用继承
- 需要使用受delegation的类的所有方法时,改为继承。
- 类内部field自我封装:直接使用变量,直到它带来麻烦为止,自我封装是方便子类覆盖。
- replace data value with object 把电话号码抽取成对象,因为有格式化,抽取区号,等方法