为什么应该继续使用 if else

引言

大学的时候学编程对于if else,不管哪本书上,都是这样教的:(我们假想一种实际不同用户的业务逻辑)

// 产品提出会员与非会员的计算逻辑
if (isVip) {
    System.out.println("8折出售");
} else {
    System.out.println("不打折出售");
}
// 产品又提出以前的会员逻辑不变,新增VVip(最近某些视频APP推出这种制度,坊间调侃为VVip)
if (type == UserType.VIP) {
    System.out.println("8折出售");
} else if (type == UserType.VVIP) {
    System.out.println("7折出售");
} else {
    System.out.println("不打折出售");
} 
// 产品又提出以前的会员逻辑不变,新增VVVip
if (type == UserType.VIP) {
    System.out.println("8折出售");
} else if (type == UserType.VVIP) {
    System.out.println("7折出售");
} else if (type == UserType.VVVIP) {
    System.out.println("6折出售");
} else {
    System.out.println("不打折出售");
}

这些业务逻辑随着时间的增长会变得越来越多,而写之前的代码的人已经离职了,现在出现新的业务逻辑超级会员,五折出售,你接手之后是继续添加还是用各“技术”重构?我在知乎上看到过,为了逃避Sonar设置的if else的三个分支上限的报告检查,在最后一个else里面调用新函数继续if else的极品赶着下班的方案。这种方式类似于我为了应对产品急着上线,草草地写了单元测试糊弄Jenkins质量检查。(我相信很多开发者都这么干过O(∩_∩)O)用死板的程序防止工程师写出恶心的代码,这是在侮辱工程师的智商。所以分享一下我在工作中的经验,如果有不合适的地方,欢迎探讨交流。

现象

因为现在大多数公司都是业务驱动,毕竟赚钱是王道,不赚钱你都不用在这里了。所以就产生,第一个开发者,if else多简单,一看就懂,随着业务开发,再加个 if else 也能接受。第二个开发者,看到之前代码,以前都这样写,我可不能动以前的代码,多个if else 也没毛病。过两天,再加两个 if ese ,第三个人接手之后,前面的人好恶心啊,业务这么复杂,算了,不优化了,我也加个 if else。

如果在稍大点的公司工作,Sonar或者Jenkins等工具检查代码质量的时候会显示 Cyclomatic Complexity,Cyclomatic Complexity,这是一种代码复杂度的衡量标准,中文叫圈复杂度。在软件测试的概念里,圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。什么意思呢?就是你写的代码,每个公司都有自己不同的单元测试分支覆盖率的标准,这里分支越来越多,单元测试会变得很复杂,或者压根就没法测了,因为这里并没有TDD(测试驱动开发)。

解决方案与分析

方案一 switch

switch和if else是半斤八两的写法,可读性差不多,switch 显得更整齐点。但没有 if esle 好维护,if else可以更灵活。不管怎么样,这两种方法都不利于写单测。而且代码规范都会要求case后边必须跟break,switch里边必须有default。但是对 if esle没有过多要求。而且 switch 的条件只能是同一类型的不同值,比如颜色,但是现实世界中有些时候遇到的是年龄段,而不是年龄值。

if (age == 10) {
    statement;
} else if (age == 20) {
    statement;
} else if (age >30) {
    statement;
} else {
    statement;
}
···

swich是通过跳转表设置索引值效率理论上更高,但在现在编译器中 if else switch 基本没差距,这种优化对效率基本没什么影响。

方案二 策略模式

// Java实际开发中和钱有关的不能用double,要用BigDecimal,这里只作为展示作用。
public interface Strategy {
    double compute(double money);
}

public class VipStrategy implements Strategy {

    @Override
    public double compute(double money) {
        return money * 0.8;
    }
}

public class VvipStrategy implements Strategy {

    @Override
    public double compute(double money) {
        return money * 0.7;
    }
}

public class VvvipStrategy implements Strategy {

    @Override
    public double compute(double money) {
        return money * 0.6;
    }
}

public class SvipStrategy implements Strategy {

    @Override
    public double compute(double money) {
        return money * 0.1;
    }
}

public static void main(String[] args) {
    Strategy svip = new SvipStrategy();
    svip.compute(money);
    Strategy vvip = new VvipStrategy();
    vvip.compute(money);
}

这种使用涉及模式的方式写底层没问题,写框架更没问题。但是涉及到业务代码,可读性降低,入门门槛高。其实是不利于维护和交接的。

方案三 奇技淫巧

提前return,枚举,Optional,工厂等方案,这一些方案其实说白了只是在某种程度上降低了复杂度,只是转移注意力,该判断还是要判断的。

感想

if else 是面向业务逻辑编程的,switch 是面向框架编程的。开发框架为什么可以使用大量的设计模式,因为框架是被清晰定义的,有严谨逻辑的。但是大多数工程师面对的是不断增加的业务逻辑,面对复杂的现实世界,抽象出来的业务逻辑使你无法使用固定的设计模式。当第一个工程师写下 if else, 悲剧已经产生了,世界就变得复杂了,随着需求逐渐增加,又想省事,借用之前的代码,先加一个,再加一个,于是逻辑分支越来越多,据说几百个if else 或者上千的分支代码不是没有。这个时候已经没有工程师愿意重构switch或者策略模式,毕竟业务复杂度摆在那里,你重构了,所有的东西都需要重测,测试不剁了你才怪。如果系统崩了,涉及大量资金损失,可以考虑下一家了。最终就变成了 if else if else if else ···,这种局面了。你不能说第一个工程师有错,因为产品并没有告诉他以后的情况,编程嘛,最重要的是不要为难自己,继续增加 if else ,测试,提交,上线没问题,打卡下班。因为有时候大多数的情况是两头都定下来了,你夹在中间,上游给你传了枚举类型,是这种枚举类型,就走一种逻辑,如果是另一种枚举类型,就走另一种逻辑,这时候,直接加if else是最快的解决方案了。

我也想成为优秀的工程师,有时候不是我不思考,有时候不是我不想写出优秀的代码,是不能写出优秀的代码,根本没有写高质量代码的客观环境。产品催,开发经理催,需求不停的变动,什么设计模式都不顶用,最终就是怎样快,怎样方便怎样来。现实工作绝不是软件工程课程讲的那么理想,会有无数的突发情况在等着你,等你考虑好了设计模式,抽象类,接口产品通知你有个需求要加塞,或者那个需求砍掉了。重构不仅增大自己工作量,也会增大测试团队的工作量,在现有交付压力的情况下,重构对交付产品毫无帮助。出问题不仅要自己背锅,而且连累别人。然而,这锅,本来不存在的,也不需要背的,是你给自己造了个锅。

正确是相对的,一个优秀的软件开发工程师要考虑到成本和分险,重构是体现优秀程序员的时候,但是考虑过可能会带来的额外风险,这种风险是否可以接受?有的时候不需要把代码当艺术品,能够适度忍受不完美,bug率可控,异常正常,有啥问题解决啥问题。给我几年时间,我也能把一个业务项目变成高雅艺术品,有啥用?!优秀的程序员应该按点把自己的事情做了。

祖传的代码尽量不要动他,if else 没啥大问题就先放着,先把手头的任务做了。if else 比动不动滥用策略模式好太多,策略模式作者感觉爽了,但是增加了维护成本。每个项目都有代码难看的地方,这是工程的必然,工程向的代码,第一要义要快速实现,第二要义是方便维护。设计模式在技术选型阶段定下来比较好,重构还是算了吧。拿着底层码农的薪水,却操着CTO都不操的心。业务驱动技术,不要维护只有自己关心但用户不关心的特性。大量的不规范的代码的源头,都是不专业的产品或策划,它们提出的不合理的需求,或者无脑的需求变更。

说了这么多,但这不是我们不学重构,代码整洁之道,设计模式的借口。设计模式和框架绝对一个项目中非常重要的东西,但不是绝对重要的,而本来就是几个 if else 就能直观解决的问题。什么是优秀的代码?能让人一眼看懂的代码才是好代码。业务代码个人感觉还是直观能看清楚实现逻辑,而不是在代码架构里跳来跳去。最简明易懂的代码结构有着最好的可维护性和可扩展性。

结论

宋代的青原行思大禅师说过这样一段话:"老僧三十年前来参禅时,见山是山,见水是水;及至后来亲见知识,有个入处,见山不是山,见水不是水;而今得个体歇处,依然见山还是山,见水还是水。"由此得来人生三个境界:"看山是山,看水是水;看山不是山,看水不是水;看山还是山,看水还是水。"

对于 if else if else ···情况,我们在学习编程的时候是第一重境界;等我学了设计模式,学了重构,学了代码整洁之道,感觉 if else if else太low了,设计模式多高大上,进入第二重境界;等我真正面对大量变动的业务逻辑的时候,我觉得还是第三重境界才是真。

所以,具体环境具体做法,通常情况下,可读性,逻辑清晰度永远是第一。能让读者一眼看懂的代码才是好代码。if else if else ··· 该加的时候毫不手软!而且还是最快的方式!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335