思维导图
点击下图,查看大图。
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/cdae1e7702a1b3f6f472eda01dd59425.png)
介绍 条件逻辑有可能十分复杂,因此本章提供一些重构的手法,专门用来简化它们。 全文简述(你可直接跳过下面的内容) 核心重构: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 状况:你有一个复杂的条件(if-else if-else)语句,那么从if、else if、else三个段落中分别提炼出函数。![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/fdc06fcf7cfe67e25368e8b21ae33403.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/792aa1becb411177dea3dc16a501b609.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/b04e91732f440e13d9ac5f3129b9d6b1.png)
Consolidate Conditional Expression 状况:你有一些条件测试,都得到相同的结果,那么将这些测试合并为一个条件式,并将这个条件提炼称为一个独立的函数。动机: 1、合并后的条件代码会告诉你“实际上只有一次条件检查,只不过有数个并列条件需要检查而已“,――使检查的用意更清晰。 2、为Extract Method做好准备。――将检查条件提炼成一个独立函数,对于理清代码意义非常有用。它把描述“做什么”的语句换成了“为什么这样做”。![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/99e2390b388b895d840f4576266c23f2.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/90d27fc11a93c5e597912a05ec809de0.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/d3a744848fbc02c072ce25b1546fb499.png)
条件语句的“合并理由”也同时指出了“不要合并”的理由:如果你认为你的这些检查的确彼此独立,的确不应该被视为同一次检查,那么就不要使用本项重构。因为在这种情况下,你的代码已经清楚表达出自己的意义。
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/9917c66511fa5d9a20e166aecc1bd1d7.png)
Consolidate Duplicate Conditional Fragments 状况:在条件式的每个分支上有着相同的一段代码,那么将这段重复代码搬移到条件之外。 ![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/08bb70829717f4bddf537c37d16e1abd.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/037bac7b96100f210334c8b0751f027d.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/9fe0471ecbe2ee8447d0daf747657e49.png)
Remove Control Flag 状况:在一系列布尔表达式中,某个变量带有“控制标记”的作用,那么以break语句或return语句取代控制标记。 ![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/41e28a0baefc57065759923fb26cd130.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/b4c5ebb548967f052ee82be44152ebb8.png)
Replace Nested Conditional with Guard Clauses 状况:函数中的条件逻辑使人很难看清正常的执行路径,那么使用卫语句(Guard Clauses)表现所有特殊情况。![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/a77c3f108f2d96ee725979bdf5c01ca0.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/55f6f6eb8e6d8aa5d09a280ab2431f80.png)
条件式的两种形式: 1、所有分支都属于正常行为:使用[if ... else..] 2、条件式极其罕见:应该单独检查该条件,并在该条件为真时,立刻从函数中返回。――这样的单独检查常常被称为”卫语句“Replace Nested Conditional with Guard Clauses精髓:给某一分支以特别重视。![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/e52c0146f68f3bdb0bf660c788f23548.png)
Replace Conditional with Polymorphism 状况:你手上有个表达式,它根据对象型别的不同而选择不同的行为,那么将这个条件式的每个分支放进一个subclass内的覆写函数中,然后将原始函数声明为抽象函数。 ![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/2baae29c7b3dc676f69a30e8462608f4.png)
此代码的坏味道:
1、它太长,当视频有新类型的时候,它会变得更长。
2、它明显做了不止一件事。
3、它违反了单一权责原则,因为它有好几个修改它的理由。
4、它违反了开放闭合原则,因为每当添加新类型时,必须修改它。不过最麻烦的可能是到处皆有类似结构(_get类型名Rank())的函数。
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/4e2db83029980b3e7328d9554a2e46ed.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/fa9d325261eab8afb4b1503274c8683e.png)
Introduce Assertion 状况:某一段代码需要对程序状态(state)做出某种假设,那么以断言(assertion)明确表现这种假设。
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/a4700e635e5b59568c810fe73550a297.png)
运行结果:
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/7edd5fee247eef339084d02e8c42a4b3.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/ba346012666a20359105a9f829587e32.png)
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/589e8a7a1865c811fb26279111d2b1e7.png)
运行结果:
![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/6ae4348900a8e29fa3029ce99953ce64.png)
采点:![](/d/file/itjie/<a href=/itjie/phpjishu/ target=_blank class=infotextkey>php</a>jishu/2014-10-22/378e8d9b8b5a1d433f5fbca5a7903f6b.png)
1、常常会有这样的代码,只有当某个条件为真时,该段代码才能正常运行。――实际上程序最后成品往往将assertion统统删除。 2、这样的假设通常并没有在代码中明确表现出来,你必须阅读整个算法才能看出。――有时候程序员会以注释写出这样的假设,而assetion是一种更好的技术。 3、assertion是一个条件式,应该总是为真。如果失败,表示程序员犯了错误。 4、assertion可以作为交流与调试的辅助。――交流:可以帮助程序员阅读理解代码所做的假设。调试:帮助程序员找到bug,可以在距离最近的地方抓住bug。 5、assertion并不改变程序的任何行为。 6、assertion价值:帮助程序员理解代码正确运行的必要条件。 7、建议最好把assertion的条件式使用Extract Method,为了将若干地方的重复码提炼到同一个函数中,也许只是为了更清楚说明条件式的用途。 总结 这一章我比较喜欢“Replace Nested Conditional with Guard Clauses “这个方式,我在平时的代码中也经常这样用,还有人给这种方式取名叫”卫从句“。 还有一个就是我经常在php开发中用的调试是var_dump()或print_r(),我也第一次发现php中还有assert这种方式,不错! 在学习和实践的过程中,我也学到了很多不错的方式。但是我觉得在团队开发中,有的时候还是”大局为重“,按照团队的习惯方式去编码,或者你可以跟团队沟通,得到大家的认可之后,在使用这里面的方法,这样大家彼此调试和阅读对方代码的时候比较方便。
php技术:PHP 杂谈《重构-改善既有代码的设计》之四 简化条件表达式,转载需保留来源!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。