《重构,改善既有代码》读书笔记

一、为何要重构

1、重构让代码更易阅读和理解。

2、重构改进软件设计

我个人认为,上述两点完全可以是重构的动力。

二、什么情况需要重构

1.重复代码

2.过长函数

3.过大的类

4.过长参数列

5.违反单一职责原则(即有多个理由去修改一个类)

6.散弹式修改(如果每遇到某种变化,你都必须在许多不同的类做出许多小修改,就应该考虑提到一个类中)

7.数据泥团(如果在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数中相同的参数。就可以把他们提到单独类中)。

8.switch惊悚现身(看见switch可用多态来替换)

9.令人疑惑的临时变量(一般复杂算法中会出现不止一个的临时变量,就会产生这样的问题,书中建议提到一个单独类中去)

三、重构手法

以函数对象取代函数(Replace Method with Method Object)

场景:你有一个大型函数,其中局部变量的使用让你无法采用Extract Method。

用法:将这个函数放进一个单独的对象中,如此一来局部变量就变成了对象内部的字段。然后你可以在类里面将大型函数分解为多个小型函数。

例子:

 
  1. Class Order{

  2. double price(String parm){

  3. double primaryBasePrice;

  4. double basePrice;

  5. double price;

  6. .... //other code

  7. this.mthod();

  8. }

  9. }

我们可以给他转换成以下的样子:

 
  1. Class Order{

  2. double price(String param,Order sourceOrder){

  3. return new PriceHandle(param,sourceOrder).compute();

  4. }

  5.  
  6. }

  7.  
  8. Class PriceHandle{

  9. double primaryBasePrice;

  10. double basePrice;

  11. double price;

  12. String param;

  13. Order order;

  14.  
  15. public PriceHandle(String param,Order sourceOrder){

  16. this.param=param;

  17. this.order=sourceOrder;

  18. }

  19.  
  20.  
  21. public double compute(){

  22. otherMethod();

  23. .... //code1

  24. return order.method();

  25. }

  26.  
  27. public void otherMethod(){

  28. .... //code2

  29. }

  30. }

文中重点摘要:

替换算法(Subsittue Algorithm)

 
  1. String checkPerson(String[] people){

  2. for(int i=0;i<people.size();i++){

  3. if(people[i].equals("Don")){

  4. return "Don";

  5. }

  6. if(people[i].equals("Son")){

  7. return "Son";

  8. }

  9. if(people[i].equals("Men")){

  10. return "Men";

  11. }

  12. }

  13. return "";

  14. }

这种代码确实很常见,反正我是写过,其实我们可以替换为下面这一种:

 
  1. String checkPerson(String[] people){

  2. List candidates=Arrays.asList("Don","Son","Wen");

  3. for(int i=0;i<people.size();i++){

  4. if(candidates.contain(people[i]){

  5. reutrn people[i];

  6. }

  7. }

  8. return "";

  9. }

算法也应该清晰明确易改易读。

 

搬移函数(Move Method)

场景:在一个类中,函数使用另一个对象的次数比使用所驻对象的次数还多。就应该把函数搬移过去。本着“这个函数与哪个对象交流更多”的原则。

 

封装集合(Encapsulate Collection)

个人理解用例:

 
  1. Person person=getPerson();

  2. Set courses=person.getCourses();

  3. courses.add(new Course("体育课"));

应该改为:

 
  1. Person person=getPerson();

  2. person.addCourse(new Course("体育课"));

  3.  
  4. //然后要把person返回的课程改为不能修改的集合

  5. public Set getCourses(){

  6. return Collections.unmodifiableSet(courses);

  7. }

以函数取代参数

这个重构的意义在于,一个方法,既可以用参数传递的方式来获取参数,也可以在方法内调用方式来获取参数。那么我们就采用后者,因为过多的参数会增加方法的复杂度。

getDiscountLevel()能直接放在discountedPrice内部调用,所以我们就可以直接拿进去。这其实也是高内聚的一种表现。

 

提炼子类

类中的某些特性只被某些实例用到。意思就是说一个类中的有些方法,并不是所有实例都必须要的,那么可以创建个子类,然后把这些“非公共方法”移到子类去。然后需要用这些方法的类就用子类就行了。

 

四:代码自我释义

文中对代码结构的建议很有启发性。代码的味道一词,很好的形容了好代码和坏代码带给编辑者自身和其它阅读者的感受。

“好的代码能够表达自身的意图”,这句话很好的体现了此书的思想。

好的代码是清晰而明确的,“散发着芳香”。

 

之后在自己写代码时,增加了对代码味道的嗅觉敏锐度,就是对自己结构有了更高要求。

一旦感觉到隐隐的不满,或者不对头的迹象,就要停下来想一想,是否哪里的结构不太合理。这样的思考总是带来有益的进步,总会发现更合理的结构,有时只是简单的把一部分代码提到一个单独的类里,就会让那种不对劲的感觉变成,哇哈这就对了的快感。仿佛真的闻到芳香

可以举一个具体的例子,也是我对自己的要求。

一个类尽量不超过300行。或者最多500行,不能再多了。1000行就是极限了,我认为不应该那么多,通常可以把一部分相同意图的代码提到一个新的类里。每次这么做之后,都会有一种哇塞这太棒了的喜悦。。唯一需要克服的就是一开始的一点点惰性——“何必麻烦呢”,但每次行动后,都会庆幸自己做了尝试。

给方法或类命名时要认真思考。这一点很重要。

当想要给一段代码写注释时,可能只需要把它们放到一个独立的方法里(“哪怕这个方法这有一行代码”,书里这有说,我非常赞同),并给方法起一个恰当的名字,就不需要写注释了。而一旦这样做后,就会感觉自己的代码那么的有条理性,那就是代码的芳香。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值