《重构》读书笔记(十)——第十章 简化函数调用

第十章 简化函数调用

1、重命名函数(Rename Method)P273

        一个好的函数名称很重要,比你想象的还要重要得多。为函数起一个”见名知意“的名字并不容易,需要经验;要想成为一个真正的编程高手,起名的水平是至关重要的,因此需要你的重视。如果你所在的领域比较特殊(专业性比较强),你可以从专业人员那里得到帮助。千万不要以为名字只是小事,不值得去咨询专业人士,一个好的名字将让你的程序质量迅速提升。

       ”就这样将就着吧“是恶魔的召唤,是通向混乱之路,也是一种极不负责任的态度。记住,你的代码首先是为人写的,其次才是为计算机写的。

2、添加参数(Add Parameter)P275

        Add Parameter是一项很常用的重构手法。使用这项重构的动机很简单:你必须修改一个函数,而修改后的函数需要一些过去没有的信息,因此你需要给该函数添加一个参数。但通常来说,过长的参数列是一种坏味道(Data Clumps)。因此,在进行本项重构之前,我们有必要先思考以下一些问题:

1)除了添加参数外,是否还有别的更好选择?

2)可能通过某个函数得到所需信息吗?

3)看看现有参数,是否需要 Introduce Parameter Object?

3、移除参数(Remove Parameter)P277

       本项重构没有什么好说的。有一点值得注意:很多程序员不愿意去除多余的参数。理由是:它们没有带来什么问题,而且留着它,说不准以后要用上呢(代码坏味道:夸夸其谈未来型)。这也是恶魔的诱惑,一定要把它从脑子里赶出去! 不要让你的代码腐坏。

      另外,对于多态函数,使用本项重构时需要小心。这种情况下,可能多态函数的另一份(或多份)实现会使用这个参数,此时你就不要去除它。 

4、 将查询函数与修改函数分离(Separate Query from Modifier)P279

        这是一项很重要的重构。

        如果某个函数既返回对象的状态值,又修改对象状态,那么这是一个很不好的信号。我们称之为“既有返回值又有副作用”的函数。有一条很好的编程规则:任何有返回值的函数,都不应该有看得到的副作用。

       完成本项重构之后,还有两件事值得注意:

1)如果有必要的话,为原函数改个名字(Rename Method)会更易于理解。

2)重构之后,在查询函数和修改函数中可能会出现大量重复代码。如果有必要的话,采用”Substitute Algorithm“ 去除重复代码。而且,我们会对重构后代码的效率产生质疑,还是那句老话,效率问题是性能优化阶段的任务。

5、令函数携带参数(Parameterize Method)P283

        “参数化函数”,是指对于一段只因某个(或某些)参数而不同的重复代码,通过提炼函数进行重构的手法。因此,本项重构的要点在于:以“可将少量数值视为参数”为依据,找出带有重复性的代码。

6、 以明确函数取代参数(Replace Parameter With Explicit Methods)P285

      Replace Parameter With Explicit Methods恰恰相反于Parameterize Method。

      这是一项很有意义的重构。重构之后能够使接口更清晰,更易于使用----这是非常有价值的代码。

7、保持对象完整(Preserve Whole Object)P288

        如果你从某个对象中取出若干个值,将它们作为某一次函数调用的参数,那么你应该改为传递整个对象。

       这样做的好处是:

1)万一(??呵呵??)将来被调用的函数需要新的数据项,而这些新的数据项可以从这个对象中获得,那么你就不用修改函数接口,可以直接从那个参数对象那里获取到所需的信息。

2)Preserve Whole Object往往还能提高代码的可读性。过长的参数列总是很难使用。

3)更重要的是,如果你实施Preserve Whole Object这样重构之后,你也许会发现某个函数大量的使用了来自另一个对象的参数,那么是不是这个函数放置的地方有问题?考虑使用 Move Method 将该函数搬移到另一个更合适放置它的类是水到渠成的。

      当然,很多时候我发现我不太愿意使用这项重构,因为

1)“传递整个对象会导致对象之间的依赖关系加重”。

2)传递整个对象会使接口看起来更加模糊,增加更多的调用限制。

8、以函数取代参数(Replace Parameter With Methods)P292

     对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数本身也能够调用前一个函数。那么就应该运用本项重构,让参数接受者去除该项参数,并直接调用前一个函数。

9、引入参数对象(Introduce Parameter Object)P295

       使用场合:某些参数总是很自然地同时出现。这时应该以一个对象取代这些参数。本项重用于处理代码坏味道“数据泥团(Data Clumps)”和“过长参数列(Long Parameter List)”。

        现在,我们可以总结一下缩短参数列的重构手法有哪些?

1).  保持对象完整(Preserve Whole Object);

2).  以函数取代参数(Replace Parameter With Methods);

3).  引入参数对象(Introduce Parameter Object)。

     不过,说实话,我觉得“过长参数列”的坏味道并不是特别的难闻或难以忍受。因此,我通常较少使用以上重构手法,因为在我看来,以上重构手法都会导致这样或那样的小问题,例如:

1).  保持对象完整(Preserve Whole Object): 导致接口调用困难;增加类之间的关联、耦合。

2).  以函数取代参数(Replace Parameter With Methods):降低了接口的灵活性和独立性;致使后续的重构工作(例如搬移接口)变得困难。

3).  引入参数对象(Introduce Parameter Object):会导致纯稚的数据类(Data Class)坏味道。

       过长的参数列确实带有浓厚的过程式代码的缺点。而且,在面向对象程序设计中,函数所需的参数多半可以在其宿主类中找到。如果某个函数需要的很多信息在其宿主类中找不到,那就开始散发出“依恋情结(Feature Envy)”的坏味道了,这时请考虑搬移方法(Move Method)重构之。

10、移除设值函数(Remove Setting Method)P300

        如果类中的某个字段应该在对象创建时被赋值,然后就不再改变,那么应该去掉该字段的所有设值函数。

        代码必须要能表达你的意图。如果你为某个字段提供了设置函数,这就暗示这个字段的值可以被改变。如果你不希望这个字段值在对象创建之后还有机会改变,那就不要为它提供设值函数(可能的话,尽量将这个字段声明为const)。这样你的意图就很清晰,并且可以排除其值被修改的可能。

        请避免在构造函数中调用诸如“setXxx()”之类的函数,如果实在必要(例如需要经过一定的运算或有多个构造函数调用相同的代码),也应该使用 "initializeXxx()",它更能表达你的意图。

11、 隐藏函数(Hide Method)P303

          尽可能降低所有函数的可见度。尽可能频繁的检查有没有可能降低某个函数的可见度。public ——》protected ——》private

          我们也许会觉得这样的重构价值不大,但这样的重构确实不会占用大多的时间,而且从长期来看,是有意义的。

12、以工厂函数取代构造函数(Replace Constructor With Factory Method)

          以工厂函数取代构造函数最明显的动机,就是在使用派生子类的过程中以工厂函数取代类型码。如果是这种情况,通常应该将构造函数声明为private 。

          此外,工厂函数也是将值对象改变为引用对象(Change Value to Reference)的基础。

13、封装向下转型(Encapsulate Downcast)

         在C++中,向上转型(Upcast)是安全的;向下转型(Downcast)总意味着设计不够优雅。我们编写供客户代码使用的接口时,应该尽量将转型动作封装在本地接口中,即避免要求客户代码做转型动作。

14、用异常取代错误码(Replace Error With Exception)

         积极的使用断言。

15、 以测试取代异常(Replace Exception With Test)

        对一些正常的或可以修正的错误,应该使用条件语句进行判断检查。但我发现,我们在很多本应该使用断言的情况下,滥用了“判断检查”功能。本应该使用断言的地方,却使用了if() return;  恰到好处的使用断言需要经验!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值