源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

PHP 杂谈《重构-改善既有代码的设计》之四 简化条件表达式

  • 时间:2022-01-19 03:57 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:PHP 杂谈《重构-改善既有代码的设计》之四 简化条件表达式
思维导图 点击下图,查看大图。 [url=http://www.1sucai.cn/upload/201204/20120409223358429.png][img]http://files.jb51.net/upload/201204/20120409223358429.png[/img] [/url]
 介绍
 
 条件逻辑有可能十分复杂,因此本章提供一些重构的手法,专门用来简化它们。
 
[b]全文简述[/b](你可直接跳过下面的内容)
  核心重构:Decompose Conditional——分离”转辙逻辑“(switching logic)和”操作细节“(details)分离。
  多处测试有相同结果:Consolidate Conditional Expresssion
  条件代码中去掉重复成分:Consolidate Duplicate
  标识特殊情况:Replace Nested Conditional with Guard Clauses
  去除讨厌的控制标记:Remove Control Flag
 
 
 专业术语
 
decompose:分解,分离
consolidate:合并
eligible:合适的,合格的
fragment:碎片,片段
nest:嵌套
guard:保卫
clause:从句
polymorphism:多态
assertion:断言
unchecked exception:不可控异常
 
 Decompose Conditional
 
[b]状况:[/b]你有一个复杂的条件(if-else if-else)语句,那么[b]从if、else if、else三个段落中分别提炼出函数。[/b]
[img]http://files.jb51.net/upload/201204/20120409223358665.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358176.png[/img]     [img]http://files.jb51.net/upload/201204/20120409223358260.png[/img]  
 Consolidate Conditional Expression
 
[b]状况:[/b]你有一些条件测试,都得到相同的结果,那么[b]将这些测试合并为一个条件式,并将这个条件提炼称为一个独立的函数。[/b]
[b]动机:[/b] 1、合并后的条件代码会告诉你“实际上只有一次条件检查,只不过有数个并列条件需要检查而已“,——使检查的用意更清晰。
     2、为Extract Method做好准备。——将检查条件提炼成一个独立函数,对于理清代码意义非常有用。它把描述“做什么”的语句换成了“为什么这样做”。
[img]http://files.jb51.net/upload/201204/20120409223358410.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358116.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358236.png[/img]   [b]条件语句的“合并理由”也同时指出了“不要合并”的理由:[/b]如果你认为你的这些检查的确彼此独立,的确不应该被视为同一次检查,那么就不要使用本项重构。因为在这种情况下,你的代码已经清楚表达出自己的意义。   [img]http://files.jb51.net/upload/201204/20120409223358248.png[/img]  
 Consolidate Duplicate Conditional Fragments
 
[b]状况:[/b]在条件式的每个分支上有着相同的一段代码,那么[b]将这段重复代码搬移到条件之外。[/b]
 
[img]http://files.jb51.net/upload/201204/20120409223358918.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358160.png[/img]
[img]http://files.jb51.net/upload/201204/20120409223358345.png[/img]
 
 Remove Control Flag
 
[b]状况:[/b]在一系列布尔表达式中,某个变量带有“控制标记”的作用,那么[b]以break语句或return语句取代控制标记。[/b]
 
[img]http://files.jb51.net/upload/201204/20120409223358648.png[/img] [img]http://files.jb51.net/upload/201204/20120409223358720.png[/img]
 [img]http://files.jb51.net/upload/201204/20120409223358979.png[/img]
 
[img]http://files.jb51.net/upload/201204/20120409223358240.png[/img]
 
 Replace Nested Conditional with Guard Clauses
 
[b]状况:[/b]函数中的条件逻辑使人很难看清正常的执行路径,那么[b]使用卫语句(Guard Clauses)表现所有特殊情况。[/b]
[img]http://files.jb51.net/upload/201204/20120409223359693.png[/img]
[img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223359794.png[/img]
条件式的两种形式:
  1、所有分支都属于正常行为:使用[if ... else..]
  2、条件式极其罕见:应该单独检查该条件,并在该条件为真时,立刻从函数中返回。——这样的单独检查常常被称为”卫语句“
Replace Nested Conditional with Guard Clauses精髓:给某一分支以特别重视。
[img]http://files.jb51.net/upload/201204/20120409223359140.png[/img]
 
 Replace Conditional with Polymorphism
 
[b]状况:[/b]你手上有个表达式,它根据对象型别的不同而选择不同的行为,那么[b]将这个条件式的每个分支放进一个subclass内的覆写函数中,然后将原始函数声明为抽象函数。[/b]
[b][/b] 
[img]http://files.jb51.net/upload/201204/20120409223359684.png[/img] [b]此代码的坏味道:[/b]   1、它太长,当视频有新类型的时候,它会变得更长。   2、它明显做了不止一件事。   3、它违反了单一权责原则,因为它有好几个修改它的理由。   4、它违反了开放闭合原则,因为每当添加新类型时,必须修改它。不过最麻烦的可能是到处皆有类似结构(_get类型名Rank())的函数。 [img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223359415.png[/img]   [img]http://files.jb51.net/upload/201204/20120409223359468.png[/img]
 Introduce Assertion
 
[b]状况:[/b]某一段代码需要对程序状态(state)做出某种假设,那么[b]以断言(assertion)明确表现这种假设。[/b]
 
 
 
[img]http://files.jb51.net/upload/201204/20120409223359768.png[/img] 运行结果: [img]http://files.jb51.net/upload/201204/20120409223359977.png[/img]
[img]http://files.jb51.net/upload/201204/20120409223358720.png[/img] [img]http://files.jb51.net/upload/201204/20120409223359393.png[/img] 运行结果: [img]http://files.jb51.net/upload/201204/20120409223400494.png[/img]
 
[b]采点:[/b]
[img]http://files.jb51.net/upload/201204/20120409223400386.png[/img]
  1、常常会有这样的代码,只有当某个条件为真时,该段代码才能正常运行。——实际上程序最后成品往往将assertion统统删除。
  2、这样的假设通常并没有在代码中明确表现出来,你必须阅读整个算法才能看出。——有时候程序员会以注释写出这样的假设,而assetion是一种更好的技术。
  3、assertion是一个条件式,应该总是为真。如果失败,表示[b]程序员犯了错误[/b]。
  4、assertion可以作为[b]交流与调试[/b]的辅助。——交流:可以帮助程序员阅读理解代码所做的假设。调试:帮助程序员找到bug,可以在距离最近的地方抓住bug。
  5、[b]assertion并不改变程序的任何行为。[/b]
  6、[b]assertion价值:帮助程序员理解代码正确运行的必要条件。[/b]
  7、建议最好把assertion的条件式使用Extract Method,为了将若干地方的重复码提炼到同一个函数中,也许只是为了更清楚说明条件式的用途。
 
 总结
 
       这一章我比较喜欢“Replace Nested Conditional with Guard Clauses “这个方式,我在平时的代码中也经常这样用,还有人给这种方式取名叫”卫从句“。
      还有一个就是我经常在php开发中用的调试是var_dump()或print_r(),我也第一次发现php中还有assert这种方式,不错!
 
        在学习和实践的过程中,我也学到了很多不错的方式。但是我觉得在团队开发中,有的时候还是”大局为重“,按照团队的习惯方式去编码,或者你可以跟团队沟通,得到大家的认可之后,在使用这里面的方法,这样大家彼此调试和阅读对方代码的时候比较方便。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部