文档章节

if....else....使用思考

 泊竹
发布于 2014/05/09 10:06
字数 1858
阅读 122
收藏 0
点赞 0
评论 0

if…else…是一个伟大的发明

if…else…就像当年的AK47,成本低廉,足够简单,简单到连小孩子都轻易理解;同时if…else…足够强大,就像AK47,一梭子扫过来,打得人抱头鼠窜。if…else…确实很强大,强大到你稍不留意,就能使一段代码被众多的if…else…搞得复杂无比。。。

如何正确使用if…else…是门艺术

if…else…本质来说是条件控制语句,它可以用来实现强大的流程处理,这一点无可厚非。然而,很多时候,我们把if…else…作为一种实现技巧,为提高减少代码量,提高所谓的“复用率”,或者说为了使程序更“精练”。

 

例如,A、B功能模块具有类似的业务流程,但输入数据不同,某一个字段的处理不同,于是聪明的程序员很自然的在A模块的业务方法中增加了一段if…else…,根据传入参数,来控制那个特殊字段的处理。这样实现是正确的,至少在当时的业务需求前提下可以很好的提高编码较率。但这么做的本质,实际上是把不同业务实体之间的条件控制,转移到了业务实体之中,把原本互相独立的模块,紧密地结合在了一起。很明显在我们写这样的自以为很精练、妙不可言的代码时,我们把天天挂在嘴边的“高内聚,低耦合”抛到九霄云外了。。。

好景不长,第一版华丽的收尾了,第二版接踵而至,第二版增加了C模块,C模块的输入和A、B一致,但逻辑处理和输出与A、B差异较大。需求人员乐呵呵地描述了需求,心想C和A、B其实复杂度差不多,之前做A、B也没遇到什么问题,这次能有什么问题呢?可是实现人员对此愤愤不平:这乍改,谁说复杂度差不多了,C和A、B明显不一样啊?!但他的话很明显是没有说服力的。他无奈地接受了这个纠结的命运——在之前A、B的那个if…else…后面再加了一个else,即使A、B、C真正共同复用的只有if前面那两行代码。。。

再后来的情况或许大家都猜到了,A、B、C、D……,终于加到了第十个模块,这个时候if…else…已经盘根错节。同一个字段承担了好几个模块场景下的不同业务意义的数据,只因为这些数据都是date类型。。一个整型数据,在一个模块处理中是业务数据,在另一个场景则变成了逻辑控制的一部分。。在无所不能的if…else…里,一切皆有可能,这个时候,程序员以经无法完全按照自己的意愿去改这坨代码了,他们往往按照测试时的运行结果来调整各处代码。。客观的说,此时的代码,已经不按人类的意志来运行了!愚蠢的人类啊,他们一手创造了这一切,确发现他们无法掌控这一切,而当这些自以为是的人类意识到问题的严重性时,结局已经难以挽回了。。

积极重构,合理使用设计模式破除if…else…

再回过头来看看,最开始时把A、B模块做如此高的复用,对还是不对呢?当然是正确的,至少在当时是正确的:开发经理眉开眼笑,效率很高啊,来个效率之星表彰一下吧~复用是必需的,只是复用的方法不对而已。两个模块,我们很容易发现其共性,三个或三个以上呢?其实也很简单,设计模式啊~比如大量相似的表单,可以用装饰模式、建造者模式,取表单数据可以和责任链、命令模式等。我们一遍又一遍的学习设计模式,但不少人还是对此不以为意,认为我们平常实现过程没机会用设计模式,导致各种模式看多少遍忘多少遍。其实不需要特意套用某个设计模式,可以借助其思想,我们要用设计模式来实现业务,没有哪个业务是为了某个设计模式而存在的。值得注意的是,没有哪一个设计模式将条件控制语句作为其实现的凭仗。设计模式是为了解耦,而if…else…其实就是一种耦合。

功能点与功能点估算的准确性

功能点估算是比较先进的估算方法,功能点估算把各个功能当做互相独立的操作和文件来处理,因此才能达到不同的人作出估算得出相近结果的效果。如果在实现过程中利用功能模块内部的条件控制来实现不同模块的复用,这样肯定会使工作量小于估算,于是功能点估算时引入了“复用程度”的概念。但问题是,“复用程度”还比较好估计,“不复用程度”呢,估算的时候,谁能预测之前的代码会对如今的需求产生什么影响呢?因为这本身就是个笑话,之前代码怎么会影响未来的需求,本末倒置啊。但事实的情况是,它还真影响了,或者说是阻碍了新功能的引入。功能点具有不可控的工期,功能点估算就不准了。在功能模块内部使用if…else…是极不合理的复用方法,等若饮鸩止渴。

功能点估算法,客观上要求我们不去糅合两个不同模块,这与复用并不矛盾。正确的方法其实很简单,只要注意条件控制语句如果不可必免一定只能加在功能外部,把复用的部分抽取出来即可。引入其他功能时,也要极力避免在已抽取的方法内添加if…else…,随着复用的方法抽取越来越多,我们就会慢慢意识到,这里有点像XX设计模式耶。所以说,好的代码、好的设计、好的架构,都是改出来的。

总结

没有人刻意去写烂代码,往往我们嗤之以鼻的烂代码,每一坨都不是天然形成的。一坨烂代码的形成,是日积月累的结果,项目团队人员更迭,甚至是几批、几代程序员共同奋斗的结果。if…else…有一种神奇的魔力,它依靠else if这种神奇的特性,把一坨坨代码串在一起。正如破窗效应,程序员们往往情不自禁地在if…else…后继续添加if…else…。作为优秀的程序员,我们一定要有足够的定力,出淤泥而不染,拒绝if…else…的诱惑。一时爽一下,但终究还是要还的。

记住,珍惜生命,预防猝死,远离if…else…


本文转载自:http://www.xuding.info/index.php/logs/533#more-533

共有 人打赏支持
粉丝 90
博文 67
码字总数 13285
作品 0
徐汇
1 Linux shell 编程(七):流程控制语句

流程控制语句 在shell中如果在终端输入多个命令,如果以&分隔则将命令放入后台执行,如果以;分隔,则表示一个命令集合。shell允许使用逻辑操作符&&和||来作为命令分隔符,他们分别时AND和OR....

乌龟漫步 ⋅ 04/28 ⋅ 0

Python学习系列 ( 第二章):Python 的基础语法的使用

一:Python的用户输入: 1.1 Python的输入 #!/usr/bin/env python -- coding: utf-8 -- Author:FlyFish import getpass _username = "zhangyy"_password = "abc123" username = input("user......

flyfish225 ⋅ 2017/06/27 ⋅ 0

策略模式

在开发中,有时候实现一个功能有多种方法或者说是策略,在实现的过程中可以根据条件来进行选择不同的方法或者策略,比如对一个集合进行排序,可以根据客户端传进来的条件来选择不同的排序算法...

tsmyk0715 ⋅ 01/14 ⋅ 0

#if..#else..#endif-------if...else区分

#if..#else..#endif #是在编译时处理的,属于预处理阶段,只会把符合条件的编译到可执行文件中; 例如: #if 1 printf("11111n"); #else printf("else else n"); #endif //结束#if 在编译时,...

李东委 ⋅ 2014/11/29 ⋅ 0

JavaScript强化教程——语句

本文为 H5EDU 机构官方 HTML5培训 教程,主要介绍:JavaScript强化教程 —— 语句 条件语句 通常在写代码时,您总是需要为不同的决定来执行不同的动作。您可以在代码中使用条件语句来完成该任...

zhanyingwang ⋅ 2016/09/02 ⋅ 0

从0到1学习网络安全 【PHP基础-If...Else】

PHP If...Else 语句 条件语句用于根据不同条件执行不同动作。 PHP 条件语句 在您编写代码时,经常会希望为不同的决定执行不同的动作。您可以在代码中使用条件语句来实现这一点。 在 PHP 中,...

AddictionsBoy ⋅ 01/13 ⋅ 0

JSP编写的简单留言版

最近粗劣接触了点JSP,刚好java老师要求我们编写一个JSP留言板,在编写程序的过程中,了解到如果你想要很好的运用JSP的话,在次之前必须好好学习Javasript和servlet,所以这次编程的过程,因...

24_hours ⋅ 2014/05/10 ⋅ 0

PL/SQL控制结构

PL/SQL是面向过程的语言,存在针对逻辑的控制语言。主要的逻辑控制语句有IF、IF....ELSE...、IF....ELIF.....、嵌套IF、CASE、LOOP、WHILE...LOOP、FOR...LOOP、CURSOR FOR LOOP。 一、IF条件...

duhaizhang ⋅ 2012/09/18 ⋅ 0

Javascript基础了解(12月3日)

一、什么是Javascript语言: JavaScript 是脚本语言 JavaScript 是一种轻量级的编程语言。 JavaScript 是可插入 HTML 页面的编程代码。 JavaScript 插入 HTML 页面后,可由所有的现代浏览器执...

TroubleMakerLi ⋅ 2017/12/05 ⋅ 0

Num58 Oracle总结

表空间: 安装一个oracle,只有一个数据库。 ORACLE数据库的逻辑单元。 数据库---表空间 一个表空间可以与多个数据文件(物理结构)关联 一个数据库下可以建立多个表空间,一个表空间可以建立...

萧小蚁 ⋅ 2016/06/24 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

用SQL命令查看Mysql数据库大小

要想知道每个数据库的大小的话,步骤如下: 1、进入information_schema 数据库(存放了其他的数据库的信息) use information_schema; 2、查询所有数据的大小: select concat(round(sum(da...

源哥L ⋅ 38分钟前 ⋅ 0

两个小实验简单介绍@Scope("prototype")

实验一 首先有如下代码(其中@RestController的作用相当于@Controller+@Responsebody,可忽略) @RestController//@Scope("prototype")public class TestController { @RequestMap...

kalnkaya ⋅ 43分钟前 ⋅ 0

php-fpm的pool&php-fpm慢执行日志&open_basedir&php-fpm进程管理

12.21 php-fpm的pool pool是PHP-fpm的资源池,如果多个站点共用一个pool,则可能造成资源池中的资源耗尽,最终访问网站时出现502。 为了解决上述问题,我们可以配置多个pool,不同的站点使用...

影夜Linux ⋅ 52分钟前 ⋅ 0

微服务 WildFly Swarm 管理

Expose Application Metrics and Information 要公开关于我们的微服务的有用信息,我们需要做的就是将监视器模块添加到我们的pom.xml中: 这将使在管理和监视功能得到实现。从监控角度来看,...

woshixin ⋅ 52分钟前 ⋅ 0

java连接 mongo伪集群部署遇到的坑

部署mongo伪集群 #创建mongo数据存放文件地址mkdir -p /usr/local/config1/datamkdir -p /usr/local/config2/data mkdir -p /usr/local/config3/data mkdir -p /usr/local/config1/l......

努力爬坑人 ⋅ 53分钟前 ⋅ 0

React Native & Weex 区别

JS引擎 Weex使用V8, React native使用JSCore JS开发框架 ( Js Framework ) Weex基于vue.js(2W+ star)。小巧轻量的前端开发框架,组件化,数据绑定,2.0引入virtual dom。 ReactNative使用...

东东笔记 ⋅ 今天 ⋅ 1

UIkit 分页组件动态加载简单实现

1. 问题描述 使用过UIkit分页组件的都清楚,UIkit的分页不能动态刷新数据,也就是不能在点击下一页的时候,动态从后台加载数据,并且刷新页数以及该页数上的数据,下面是一个简单实现,没有做...

影狼 ⋅ 今天 ⋅ 0

Mobx入门之三:Provider && inject

上一节中<App/>组件传递状态temperatures给children -- <TemperatureInput />,如果组建是一个tree, 那么属性的传递则会非常繁琐。redux使用Provider给子组件提供store, connect将子组件和s...

pengqinmm ⋅ 今天 ⋅ 0

魔兽世界 7.0版本 S23/S24/S25全职业普通+精锐套

  死亡骑士   (联盟)   (部落)   (精锐)   恶魔猎手   (联盟)   (部落)   (精锐)   德鲁伊   (联盟)   (部落)   (精锐)   猎人   (联盟) ...

wangchen1999 ⋅ 今天 ⋅ 0

maven顶级pom和子pom的版本号批量修改

当一个版本发布,新起一个版本时,我们只需要手动修改一下项目中pom.xml的版本号就可以了。但是如果这个maven项目有很多的子模块项目,那么一个个手动的去改就显得费时费力又繁琐了。还好,m...

ArlenXu ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部