重构-在实践中理解

  在老大的推荐下买了Martin Fowler的<Refactoring improving the design of existing code>,其实这本书就是作者重构的经验之谈,随便翻一下,尽管你看的多么仔细,如果你没有在实践中感受到它或者应用到它,其实你很难在需要的时候用上。

  昨天服务上线的时候,老大就给我上了一课,首先是一个同事定位到我的一个查询接口超时,于是老大就和我一起看着块超时的代码,看到了这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
B(){  // 在B中发现了代码块BlockA是冗余代码,其实是可以使用一定的方法删掉的,但是我为了省事,就没有优化,并且也没有想到怎么去掉这个冗余
 ...  // 但是这个BlockA就是查询数据库的代码,是非常耗时的,考虑到性能,就该拿掉,如果是非耗时操作,也就算了,但是这个耗时影响了性能问题。
 BlockA   // 其实我一开始想不到怎么重构,因为在我的潜意思里还是认为B应该call A,有这个前提,可以证明,是无法拿掉冗余代码BlockA的。
 ...       // 看重构的第六章,第一节就是讲把一些块抽出来,创建函数,这个BlockA已经重复调用了,所以更应该抽出一个函数来。
  A();  // 我潜意思里想B必要要调用A,是因为我先写好了A,已经把A当成了最基本的单元操作,其实不是的,还有更细的单元操作,后写B,没有将A,B放在一起看。
 ...     // haha,感觉化学工程中学习的化工反应原理中的单元操作这个概念,用在编程上,一样很6啊,这是后话
}
A(){
  ...
  BlockA;
  ...
}

  老大优化的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
B(){   // 因为在B中减少了BlockC的冗余操作,时间性能提升了约1/3,从接口看,时间性能提升还是很明显的。
   ...  // 但是,不是说这样做就没有代价,当然从理解上看,函数数量少的代码通常比函数数量多的代码好理解,并且理解了A,就可以很容易理解B。
  C();   // 我应该属于大粒度编程,在已经有A的情况下,编写B就很简单,简单也是一种优势。
  ... 
}
A(){
  ...
  C();
 ...   
}
C(){
  ... 
}

  然后再说一下代码中的坏味道,也就是<Refactoring>第三章中讲到的一些内容,一种是和语言相关的,一种是和语言无关的。 把我之前的我的一次代码检视和本次重构进行一次总结,先说和语言相关的,java

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
A(){  // 这个代码让人看了不知道代码在干啥,有点画蛇添足的味道,是不信任ProjectDao吗,ProjectDao会返回null还是返回空列表?<br>     // 绝大多数情况都是返回空列表好,这个返回什么,可以测试一下,本来一句话搞定的事,饶了这么多弯,简单事情复杂化<br>    ...
    List<String> users = ProjectDao.getUsers(String groupId);
    List<String> usersCopy = new ArrayList<String>();
    if (users == null && !users.isEmpty){
        usersCopy.addAll(users);
   }
   usersAssign.add(usersCopy);   
  ...
}   
B(){  // 这个就是重复代码,虽然不是完全重复(d条件不一样),但是,完全可以使用列表判断,然后一条执行语句搞定<br>if (a){
BlockA
}if (b){
BlockA
}if (c){
BlockB
}if (d){
BlockB
}
...
}   
class c{ // 这个是英文SimpleDageFormat是线程不安全的,在web这种天然并发的应用中使用,非常不合适。较为优雅方法有二:1在方法中使用局部变量SimpleFormatDate,
priate static final SimpleDateFormat sdf = new SimpleDateFormat(); //2.使用DateTimeFormmter和LocalDateTime并发安全类,就是有些不习惯
}
if (A && B && !C){
}esle{}  // 这个else就是对if中的条件求反,可以看到,那么多情况并不是你想要的,对于A,B默认为真,可以去掉
class Controller{  // 注意发生异常后要进行处理
}

  和语言无关的就是变量命名,注释没有更新等。所以软件工程,实践很重要,要做到理论和实践相结合,事半功倍。重构,直白来说,就是拆分之道。

  后来代码质量整改,遇到了很多问题,如重复代码,上帝类等,也是对自己代码的品味有些高。比如,尽量用效率高的代码,经历用容易理解阅读的代码

posted @   懂得了才能做一些改变  阅读(223)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示