今天想查查if...else...和switch相互嵌套怎么写,不是通常的嵌套,就是if...的大括号嵌入case分支(其中if自己在switch以外)、交错起来那种。关键字把我引上了很久没来过的博客园,进入了某个技术很不错的老伙计的博客。javascript
呃,结果我不但没找到想要的东西,又看到了if...else...或switch如何如何很差,应该进行面向对象封装和重构的文章。简而言之,就是switch的case块中含有了不少分枝的if...else..。做者毫无例外地给重构为了工厂模式,先case某种状况,而后用工厂返回一个command执行(多说一句该做者的例子是javascript,要是过去的我会用高阶函数而不是面向对象方法)。我想说的是,通常状况下把case里面直接换成一个最普通的函数调用不行嘛....java
固然,若是真的会面对可控的变化,很显然封装能够帮助咱们再从此面对它们时更轻松的处理。但拿这样一个例子来*通常性的*吐槽分支语句们,等于说由于坦克能开炮而汽车不能,因此咱们都应该去买坦克。linux
不管封装出来的多态也好仍是“硬编码”的分支也好,这些形态其核心在于存在前提和后续之间一一对应的关系;可是不是全部一一对应的关系,都应该使用某种高大上的方式实现呢?很多人都知道把程序逻辑“数据化”变为可配置的东西,但什么叫作“硬编码”?程序员
代码即数据。这不是不少高级人士广泛在讲的代码和数据是一回事、是一个问题的两种表达,而是说代码自己就是数据。用户操做的数据被咱们的程序吃掉;吃进中高级语言这个数据的是编译器;吃进二进制机器码这个数据的是CPU及其配套的执行机制。不管是CPU、编译器仍是咱们本身的程序,当它处理的数据一旦黑纸白字的写在那里,就成为了硬编码,并不由于这数据是XML或者机器码而有任何不一样;区别只是咱们会在项目生命周期的哪一个阶段对这些“硬编码”进行改动?显然在外围改动的能力须要内部提供更多的支持,这是须要成本的。数据库
因此考虑这个问题的时候,关键在于需求:咱们须要在什么场景下变化?在将会部署的目标环境中,要求运行时改变程序行为,咱们确定要多态+装载器+用户界面;不容许从新编译、或者从新编译的代价太高,咱们就使用多态+配置文件;有些部分的程序代码能够从新编译、或者做为动态语言且客观容许在目标环境中修改,那么咱们也许只是独立出一个配置模块,由于这种方式成本最低且最灵活;产品能够直接在目标环境中不断迭代且没有什么因素让修改代码成本太高,那咱们也许根本不用费那个心思,不少互联网公司发布新版本就是这种状况。异步
归根结底,进行配置和写程序代码,都是提供一种对任务的描述;这没有什么本质区别,除了后者有编译器给你把关避免一些低级错误。澄清了这个事实就能够把精力集中在剩下的方面:在没有什么特别需求或限制的时候,程序设计和实现的关键在于可读性。函数
做者的博客里明确地说道,重构的目的是“将复杂逻辑运算打散并分布到不一样的类里面”;最让我担忧的,是文章后面的留言你们里也倾向于该做者的思路是正确的。关于可读性,上述文章的做者也提到了:他还说else是排除了全部其它分支的条件大杂烩因此“难以阅读和管理”。工具
这种说法更像是欲加之罪何患无辞:当咱们用面向对象手法使用默认策略对象时,这个默认策略不也排除了其它针对性策略的前提条件了吗?那么凭什么封装了以后就好懂,不封装就很差懂呢?从根本上讲,若是一堆if...else...的代码中若不包含无效的废话,那么咱们是不可能消除它们背后的内涵的;重构仅仅是把分支换个地方或者换个形式;在程序在知足需求和限制的基础上,问题是什么样子阅读门槛最低?布局
现在每一个程序员都被告知面向对象的可读性高,但这种声明是极其可疑的。我过去参与内核移植的工做时,读了很多linux代码;弄Android中间层时,又读了很多中间件的代码。能够说Linux代码大部分都很是易懂,而那些到处封装的中间件代码,有些不挂着调试器走一遍,就如同进入迷宫通常,根本不知道哪是哪。你觉得该吃饭了,结果对着一个茅坑,这不是什么新鲜事。编码
说实话,上述文章的做者做为一个工做在某个过去并不过重视方法论的领域,在程序设计方面缺少经验能够理解。问题是在这种状况下,他甚至在原文中说出“分支超过两个”就不该该以“硬编码”的形式出现,也太武断了。
若是只是嫌代码太乱,那么把分支以后都改成一个函数调用,天然而然能避免嵌套、缩短行数,让代码从“乱花渐欲迷人眼”,变成“浅草才能没马蹄”。再进一步把if后面括号中的判断,放进有明显意义的函数里,就变成了和excel表格同样易懂的东西。在表达一组对应关系的描述中,把全部细节在当前层次隐藏,每一个条目不管在字面意思上仍是排列形态上也同时具备了明确性。
咱们处理的不少逻辑,只有写在一块儿才能一目了然;现在不少语言提供异步操做关键字以免完成时回调的两段式写法,就很好地说明了对完整性的需求是普遍存在的,且已经重要到在一些状况下最好由语言直接提供支持的地步。具体到分支语句则能够很是好的把一一对应关系展示在眼前:只要A->B的形式没变,任何其它一样完整的表格都不会有什么哪怕表面上的差别,最可能是换几个不一样形式所要求的不一样字符罢了。
在实践中若不存在运行时改变行为的需求或没法从新编译的限制,保证一一对应的关系每一个占据一行、可以自我说明且不包含冗余信息,分支即使再多(好比一万个)也不会比配置性代码或者XML文件难懂;而对比拆的七零八落的精巧设计,具备完整性的直接描述显然更具备优点。
事实上我倾向于,对于比明显的对应关系更复杂得多的状况,咱们也无需使用那些臆想中的“让程序更易读”的方式把一件事拆成不少片断以管理每一次的阅读量。只要咱们没有运行时改变行为的需求或者没法从新编译的限制,咱们就没有必要使用多态等面向对象方法并承受它们额外的trade-off,甚至连拆出函数都不用。
像复杂数据的解析,将这部分工做抽取出来以后(可用面向对象或C++模板式的泛化甚至宏实现,仍是看需求和限制),具体的代码彻底能够生成。好比能够用javascript写一个页面,直观的把要处理的单位表示为方块,经过图形界面安排次序,经过form输入相关信息,而后生成C/C++或任何语言代码;为了反向生成图,还可使用中间文件记录布局信息,或直接从生成的代码获取信息,仍旧用javascript展现出来。这些并不难,其成果(在这个例子是图)比代码直观得多,并且这样一个工具它的可复用性也要比各类代码级别的抽象来的普遍得多。
这里面关键在于,臆想中“更易读”的方式,只是对正在设计和实现程序的咱们本身而言。当咱们一点一点的分析问题,并绞尽脑汁完成一个“完美”设计的时候,咱们完全的理解了眼前的一切,并让东西和咱们的思路保持一致,这时候咱们天然以为本身的做品很易读。可是由于其它人没有走过这个思惟路径,甚至可能一时走不出十分类似的思惟路径,咱们怎么能指望他们快速理解、而且能够严格按照做者设定的方式去继续维护呢?
实践中,这些Linus所谓的“漂亮的坚固堡垒”也一点很差读,哪怕对于面向对象重度中毒者也同样;这些发烧友只会一遍又一遍的揣摩做者的心思,等终于明白了感叹一声“真TM精妙”,而彻底不在意他本身被做者折磨的好似滚了五十遍床单。相似这种自从面向对象培训业火了之后愈来愈多出现的状况,只能是Linus所谓的心智包袱之一。过的时间越久,我就越体会Linus说的,“哪怕只为了把这些人排斥在Linux核心小组以外这样一个理由,就决不能使用C++”。
相反,if...else...也好switch也好,只要咱们有心把它们安排得漂漂亮亮,它们就会像只有两个字段(条件,动做)的数据库那样简洁;因为对应关系获得明确的展示,它对任何人哪怕程序外行都是可读的。除此之外,咱们还有好多直观展示信息的方式,好比上面讲的数据解析“网页”,听起来彷佛多了一道手续,但写这样一个东西绝对不会比直接上方法论神油折腾复杂逻辑更加费时,却得到了彻底贴合问题的模型及操做工具,可读性和可维护性成倍提升。
固然,咱们须要封装时,不可避免的必须封装。此乃一句废话,也是真理。那么什么时候须要封装、多态或者任何其它方式方法?最后重复一遍:当需求或者限制明确的指出这一点、而不是咱们自身的心智包袱暗示咱们这么作的时候。做为从面向对象走过的人,我深入的知道这种暗示有时会多么强烈,咱们真正要作的就是暂时拒绝诱惑、缓一缓、再缓一缓。
对了,上面有“可控的”三字加粗换颜色了,那也是一个重点;对于不可控的变化,任何设计都是盲人骑瞎马,全部的精力投入连个响都听不到。很久不来,向全部的老伙计问声好,不知有几个还在?貌似很多人事业都蒸蒸日上,恭喜了 :)