《重构 改善既有代码的设计》 读书笔记(十)

3.2 过长函数(Long Method)

没有接触过面向对象技术,或者初学的人,往往会觉得,面向对象的程序拥有无穷无尽的委托,全然不如面向过程的好。只有在程序变得庞大,业务变得复杂时,才会知道,这种技术有着多大的价值。

拥有短函数的对象会活得比较好,因为这些小零件起到了间接层的作用。
我们回顾一下间接层的优点——允许逻辑共享易于表述(分开解释意图和实现)、隔离变化封装条件逻辑

程序愈长愈难理解,在这时我们常常需要利用提炼函数(6.1 Extract Method)来把函数变小。

当函数中存在大量参数和临时变量时,提炼函数就会变得困难,此时就要运用以查询取代临时变量(6.4 Replace Temp with Query)的重构方法来提升代码灵活度。

提炼函数(6.1 Extract Method):如果把一部分代码独立成一个方法,能让代码结构变得整洁,那么尽管去做。

以查询取代临时变量(6.4 Replace Temp with Query):把变量变成用方法取值,这样会让你在提炼函数(或者其他重构)时,能够直接在提炼的方法中调用方法(而不是将临时变量作为参数传入方法)。

引入参数对象(10.9 Introduce Parameter Object)和保持对象完整(10.7 Preserve Whole Object)能够让过长的参数列变得简洁一些。

引入参数对象(10.9 Introduce Parameter Object):当某些参数总是同时出现时,就应该考虑将这个数据泥团(Data Clumps)总结成一个类,用这个类的实例对象来代替原先参数的位置。

保持对象完整(10.7 Preserve Whole Object):这是对引入参数对象的一个扩展,或者说是一种补充。如果在一个方法的参数中,包含有从同一个对象中取出的字段值,那么就可以考虑用对象代替参数。
这种方式存在有风险——在减少参数列的同时,传递了一个对象,这会让一个类与另一个类产生依赖关系,这需要万分小心,推敲这样做会不会降低程序的可维护性。

除了以上四种重构方法外,还有一个处决的杀手锏:以函数对象取代函数(Replace Method with Method Object)。

以函数对象取代函数(Replace Method with Method Object):把一群有关联的临时变量和参数提炼成一个类的形式,此时这些变量成为了类中的字段,在类的内部就能够自由调用,这样就能减少方法引用的参数。

在确定这是一个过长函数后,我们应该找到其中可以提炼的部分,其中的一个技巧是:寻找注释。如果程序实在不怎么样,注释不存在的话,可以着重去看条件表达式和循环的地方,往往那里存在有提炼的契机。

可以使用分解条件表达式(Decompose Conditional)的重构方法来对条件表达式进行处理。

分解条件表达式(Decompose Conditional):复杂的条件逻辑是最常导致复杂度上升的地点之一,条件很多时,很轻易就会出现可读性过低的代码,这种情况,就要考虑处理分解这些条件逻辑。
此方法要做的是把判断方法提炼出来,方法的内部也要尽可能精简(多用提炼函数)。

3.3 过大的类(Large Class)

如果利用单个类做很多事情,那么它的内部往往就会出现很多实例变量,此时重复代码也会接踵而至。所以,当一个类过于庞大时,我们可以好好观察一下,里面有没有可以重构的地方。

提炼类(7.3 Extract Class):如果想要给一个类瘦身,那么可以将类内彼此相关的变量提取出来,变成一个单独的类。
这样能够将一些字段浓缩成一个类,让结构更为清晰。

当你计划使用提炼类这种重构方法时,记得观察一下,这些提炼的字段是否适合作为一个子类,这就引出了一种新的重构方法——提炼子类(11.6 Extract Subclass)

提炼子类(11.6 Extract Subclass):类中的某些特性只被某些(而非全部)实例用到。
新建一个子类,将上面所说的那一部分特性转移到子类中。

对于过大的类来说,有些时候有必要多次使用提炼类提炼子类两种重构方法。除此之外,还有一种提炼接口(11.8 Extract Interface)的重构方法。

提炼接口(11.8 Extract Interface):
当发生以下两种情况时:

  • 某一组客户只使用类责任区中的一个特定子集
  • 这个类需要与所有协助处理某些特定请求的类合作

可以依靠这种重构方法把这部分责任分离出来。

如果你的Large Class是个GUI类,你可能需要把数据和行为移到一个独立的领域对象去。你可能需要两边各保留一些重复数据,并保持两边同步。复制被监视数据(8.6 Duplicate Observed Data)可以用在这里。在这种情况下,特别是如果你使用旧式的AWT组件,你可以采用这种方式去掉GUI类并代以Swing组件。

GUI类:可以做出一个有着图形界面的壳子,让我们的程序不只显示在控制台中,而是可以作为一个小软件。
记得我在上大学的时候利用Java的GUI做了好几个程序,比如2048游戏、在线聊天室等等,但是事实上,除了在学校使用,其他时候似乎用的范围不是特别广,算是一个比较旧的东西吧,感兴趣可以上网查一下,里面有一些比较晦涩(至少是当时看来)的知识点,可以钻研一下。

复制被监视数据(8.6 Duplicate Observed Data):这里隐藏一个设计模式——观察者模式。这个东西很难说,在之后有了合适的说法再说。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NewReErWen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值