再谈《弟子规》问题

我以前就讨论过《弟子规》式的规矩:in nek:弟子规:美国军方禁止在C语言程序中使用malloc,但那个表述不太理想。

但这个问题在我和很多人讨论的时候经常遇到。我要尝试继续讨论下去,看看能否把问题说清楚。

今天在这个讨论(in nek:写程序和写小说的区别)下面,我又碰到这个问题了。所以,我想试试,这次我能否把这个问题说清楚。我说的问题在中国的工程师中经常看见,但我在不同开源社区和主线开发者讨论技术问题,从来没有遇到,我觉得不是一个两个人的问题,所以我们并不针对个人,我们针对事情,我们不把这个事情变成对某个特定个体的批判。

在上面的博文中,为了说明什么是过度式的防御编程,我举了这样一个例子:

def foo(v):
  int a = 0
  if a != 0:  #double check a 是不是初始化成功了
    raise Exception("太阳黑子运动过于强烈,请稍后再运行一次")
    raise Exception("可能硬件系统受到激烈电磁冲击,前一个raise流程没有起作用,请保存您的数据,然后念经求上帝保佑")
    print("Mayday, Mayday,we are under attack...")
    sys.exit(-1)
  a = get_a(v)
  ...

有人回应了这样一个评论:

try{}catch(){}

加上他后面的补充,我理解他认为这个地方的raise,应该加上try的保护块。

我觉得这种事情已经变成了他的一种“显然”,“禁忌”和“弟子规”——意思是:你也不要问我为什么,反正我就有这个规矩,这是我的行业经验,不能逾越。然后我再给你很多个例理由:谁谁谁不孝敬父母,后来他不是死了吗?那谁谁谁没有用try...catch把raise包起来,不是出问题了吗?那谁谁谁在高可靠系统中用了malloc,那不是没通过安全认证吗?……

我恨死了这种逻辑。因为对于架构师来说,我用尽各种办法给系统留活性,然后你用这种一刀切的规矩,在整个系统中横插一刀,这砍断多少自由度?你不用优化系统,不用进行针尖对麦芒的商业竞争,高高在上,拿你的例子程序来说明你这么砍一刀,“也没有造成很大问题啊”,但所有工程师的脑子就记住这么一个没有逻辑支撑的“规矩”,这种规矩还很多,他们怎么去面对真实的物理(细节)挑战啊?

就说这个try本身,我也不跟你多废话,我就想问一句,你调那么多系统的函数,他们会抛出异常,你觉得那些函数是怎么写出来的啊?raise Exception的设计目的就是为了可以调用跨层级的时候,让真正处理某种错误的那个层级可以统一收集那种错误啊,你凭什么给我定下规矩,说这里就要包起来,我这里包起来,我干嘛要调raise啊?脑子抽了?

这种事情经常发生,比如malloc申请一定要判断返回值是否是0。他们也说这是规矩,而我评估过的一个有名高可靠系统(忘了名字了,好像是OSE?),不检查是人家的卖点。因为对这种系统来说,如果内存不足,就说明系统已经到了不可挽回的地步了,这时应该做全系统失效处理,这有什么问题?

我们做模块设计总有很多模式和习惯,但模式和习惯不是规矩,我们不能拿这种东西直接当做规矩。《弟子规》本身没有什么害处,但变成启蒙读物就有害。你不用malloc,大部分时候不是坏处,直接要求所有安全系统不得使用malloc就是坏处。

相对来说,《三字经》虽然有很多历史局限性,但格局就完全不同。人家可没有给你定规矩,人家说“子不学,断机杼”,这是给你一个案例:你看乐羊子中途断学,她老婆用断机杼来警示他,这是教你Pattern,你自己思考怎么落地。可没有教你不动脑:“父母呼 应勿缓 父母命 行勿懒”。这是完全不同的策略,你《弟子规》学都不会学,抄都抄不好好不好?

很多人脑子还在学习阶段的时候,会犹犹豫豫地记住一些习惯,然后慢慢在更多的学习和工作经验中修正这些经验和习惯。但我们必须记住这是暂时的习惯,不是规矩,不要把这个东西当做规矩来记住,更不要拿出来当别人的规矩。你在学习阶段就没那本事来给人立规矩。

这也是为什么我觉得国内工程师更容易这样,而欧美主力开发工程师很少这样(至少我没有见过),因为我们其实很多人都是学习阶段,知其然不知其所以然。但这些年我们发展太快了,很多不成熟的软件被大规模应用(特别是互联网的兴起,很多边缘代码对构架要求很低),相关的工程师很快上到中层,甚至上层,结果他们就把这些缺乏实际支持的经验当做了真正的经验,说得振振有词,但这种缺乏事实支持的东西变成“规矩”,就会成为我们很多系统和工程师心里的毒瘤,等某个软件构架搭高了(很多特性都加进去了),这些无效的约束,就直接把系统撬翻了。

经验不足不是问题,经验不足的时候,信心十足地拒绝讨论实际的问题,得意洋洋认为这是自己的“专业经验”,这才是问题。

编辑于 2019-11-24 09:06