代码里的生活哲学

花火田丁 花火田丁 2021-02-21 12:23:34 +0000

题图来自于NextDay


写代码的时候,用到 if...else... 一般会有两种写法。

# 伪代码 A
if 满足条件 X :
do_something()
else:
return
# 伪代码 B
if 不满足条件 X:
return
do_something()

两段代码都能实现 —— 如果满足条件 X 就执行 do something。X 是我们设置的条件,do something 是在这种条件下需要做的事情。两段代码的区别是,代码 A 直截了当地处理该条件发生的情况,如果 XXX 就 YYY;代码 B 则是反其道而行,先把「不是 XXX」的情况排除掉,然后直接执行 YYY。

在多数情况下,代码 A 和代码 B 的实现并没有区别,只是某些情况下,可能会存在效率问题。比如数据量很大,而满足条件的数据比较少的情况下,代码 B 可能更合适。

而这两种方式的思维模式其实大有区别,代码 A 是正向判断,更符合我们通常的逻辑 —— 在预设的条件下做出预设的动作。而代码 B 呢?把预设条件以外的情况排除掉,然后再执行预设的动作。

这两种方式让我想到了「谈判」。代码 A 即是:如果我们可以在某些情况下达成共识,那么谈判继续进行下去。代码 B 则是:如果不接受某些条件,那么对不起,您请回。A 尝试在条件允许的情况下开始做点什么,B 则是先阻断一切风险再来看接下来能做些什么。

我们无法直截了当地指出哪种方式更佳,需根据具体情况而定。比如,金融机构的风控政策,既要考虑到业务利益最大化,又不能轻易放过可能会演变成坏账的风险,所以通常的情况是将 B+A 组合起来,比如在黑名单内的走 B 直接拒掉,接下来再根据个体的情况,按照 A 设定的规则将其逐级归类,最终得出一个评级。

单从效率上来讲,B 的情况更直接,不符合基本条件,一律快刀斩乱麻地筛掉,然后再来具体情况具体对待。A 呢,似乎宽容度更高,先把符合条件的做起来,其他的待会儿再说。这里就有一个问题了,do something 通常是很长的一段代码,包含了很多业务逻辑和步骤,满足 X 的自然没问题,进到 if 的逻辑里去执行就可以了,但是对于「不满足 X」的情况,从代码流程上来说,它需要跳过 if 这段代码去看后面会发生什么,也是等来的就是一个 return 或者什么都没有。

再举一个比较具像化的例子,一个邮件通知的功能,每天早上10点查看是否有数据更新,有的话就发邮件通知。很自然地就用了模式 A,监测到有新数据,就发邮件通知。

# 伪代码
if is_new_data :
send_email("新数据")

那么问题来了,早上10点如果没有收到邮件,就表示没有新数据吗?

仔细一想,还真不是,也可能是:数据有更新,但邮件没发。邮件没发,可能是发邮件的程序出故障了,也可能是邮件服务器本身有问题。后者不在我们可控范围内,暂且不考虑。前者,我们用什么办法去避免呢?关键点不在程序故障上,而是,我们在设计这个功能的时候,忽略了 else 的情况,即:忽略了「如果没有数据更新,我们需要做点什么?」

这个设计上的忽略,进而影响到了「排查故障」,因为,在原有的功能里,发邮件的情况只属于「有新数据」的情况,于是,在没有收到邮件的情况下,我们需要去排查究竟是「不需要发邮件」,还是「需要但没有发出」。简单粗暴地来解决这个设计上的问题,只需要让程序在「没有新数据」的时候也发一封邮件,只不过内容是「没有新数据」。

改造后的代码,就变成了这个样子:

# 伪代码
content = "没有新数据"
if is_new_data :
content = "新数据"
send_email(content)

这样一来,当我们10点没有收到邮件,基本就可以判断出是发送邮件这块出现了问题,问题就变得简单了。send_email() 方法就负责发邮件,发什么内容不是它应该操心的事儿,「数据是否更新」重担也不应该压在它身上,所以设计的时候,它的职责就是「到点发邮件」,而不是「有数据了就发邮件」。

在设计功能的时候,很多时候我们不得不去做一些“无用功”,看起来似乎跟核心功能没有关系,甚至会让核心功能变得“累赘”,或者看上去影响了执行效率,但其实是在「让程序保持一个平稳且独立的状态」,或者说「补齐某种状态」。

「有新数据」属于「核心状态」,「没有新数据」是「不重要的状态」。生活中也是,我们通常会把注意力集中在「核心状态」的考虑上,比如,我们特别担心一件事情做不好,于是,大部分的精力可能会集中在「如果这件事做不好,我该怎么办」上,忐忑不安,却反而当「事情做成了」这个状态砸过来的时候,被杀了一个措手不及,怎么做呢?反之亦然,如果注意力只放在一侧的状态上,很容易就失衡了。

凡事多想一个 else,可以补齐我们的判断逻辑,以不变应万变。但过犹不及,如果一味地去枚举 else,自行制造出各种假想敌,就会让整个逻辑变得臃肿且可读性很差,放到生活中,就会让思路变得异常混乱,抓不住主要脉络。

写代码也可以找到生活哲学,又找到了一个「人人都应该学一学编程」的理由哈哈(与创作类似,参见 Apple 说,人人能创造


撒欢吧
谈理想
聊人生
讲故事
相对论
花火田丁
微信号:huahuoding
花火田丁
不折腾不人生