宋代禅宗大师青原行思提出参禅的三重境界:
参禅之初,看山是山,看水是水;
禅有悟时,看山不是山,看水不是水;
禅中彻悟,看山仍然山,看水仍然是水。
它体现了人们对陌生事物的认知过程。
迷信 —— 怀疑 —— 心领神会。
回到编程技巧上来,我打算好好讨论一下程序的可扩展性,
根据我个人的经验,大致上也经历了这样的一个认知过程。
编程行业流传着这么一句话:过早优化是万恶之源。
但什么情况下才能称得上 “过早” 呢?
并不是那么好解释清楚。
且听我慢慢道来。
迷信
很多人刚入行的时候,都想写出高度可扩展的程序,
这是因为他们觉得,实现新功能时,
通过对程序进行扩展,而不是进行修改,这样的方式更加高明。
说这是 “高明” 的做法,其实并非毫无道理。
因为修改代码,可能会对现有功能产生影响,一旦疏于测试就会导致软件故障。
这是大家都不想见到的事情。
如果老程序提供了优秀的扩展方式,
那么实现新功能时,就能尽可能少的影响已有功能,有利于编写出更稳定的程序来。
就拿我个人而言,早期写出来的代码,都是以 “可扩展” 作为第一原则的。
这样写出来的代码很 “抽象”,因为所有功能都是从 “核心” 中扩展出来的。
这其实是 “微内核架构” 的一种表现形式。
但这并不是一帆风顺的,这样发展下去,事情就越发的显得不对劲了,
主要体现在两个方面。
(1)不同的扩展之间,遇到了集成问题,他们之间互相干扰,或产生了依赖。
(2)可扩展的程序内核太过抽象,提高了他人合作的门槛。
所以,自此我感受到,自己正在经历从第一阶段到第二阶段的转变。
我意识到自己对 “可扩展性” 产生了 “迷信”,对它产生了怀疑。
怀疑
从迷信演变而来的怀疑,很容易变得盲目,变得矫枉过正,
这是 “看山不是山,看水不是水” 的真实写照。
不过这个阶段也是必须的。
因为在极力怀疑 “可扩展性” 的同时,让我清晰认识到了它的反面。
其一,人们认为抽象度较高的程序,具备更广泛的适用性,所以会更稳固。
这是建立在 “正确抽象” 基础上而言的。
而在软件项目的早期,由于很多概念的沟通和理解,并没有足够深入,
开发者很把 “正确的抽象” 建立出来。
所以很多早期编写的抽象代码,到中后期还得进行调整。
一旦抽象层进行了调整,影响范围则是巨大的,
这意味着所有建立在这套抽象代码基础上的具体实现,都要进行修改。
所以,不合理的抽象,比不抽象,给软件带来的灾害更大。
其二,代码如果不是结合场景来编写的话,就容易产生假设,
或说是,假想敌太强大。
如果程序一开始就打算解决 “绝不会” 发生的问题,就会使它变得 “不必要” 之复杂。
这是一种资源的浪费,不论是心智还是人力上。
综合以上两点,我们产生了以下两个疑问:
(1)如何才能建立出 “正确” 的抽象?
(2)如何才能编写出 “恰如其分” 的代码?
这两个疑问,通通指向了一个概念 —— “适当”。
这正是第三个阶段我们所考虑的事情了。
心领神会
要想做到心领神会,就不能有所 “迷信”,还不能 “盲目的怀疑”。
我们须认识到解决方案的正反两面才能做到。
“可扩展性” 其实并非一个程序所必须具备的特征,
且要想具备这个特征,是需要投入成本的。
这恰如 “代码的整洁性” 这个特征一样,写出干净的代码,是需要花时间的。
所以,首先我们应考虑的是,当前程序要不要提供扩展功能,
以及以什么样的方式提供,如何降低其他开发者的扩展成本。
我们得带着问题出发,不要 “过早优化”。
有扩展的需求,再设计扩展功能,
而不是反之。
其次,秉持 “刚好够用” 原则,能覆盖当前遇到的所有场景就够了,
并不需要 “过度设计”。
把前瞻性放在大脑中,而不是直接写进代码里。
省得以后想错了,还要进行全局修改。
总之,做到心领神会,就得写出 “恰当” 的代码。
写的不多,没有假设太多实际不会发生的问题,
写的也不少,确实完整覆盖了现有的需求。
结语
本文介绍了一个新的编码技巧:“适当可扩展”,
什么样的代码才能成为 “适当” 的呢?文中详细的进行了解释。
值得一提,代码的各种优秀特征,都是需要花费精力来写出来的,
也就说需要成本,我们才能有收益。
所以,提供 “可扩展性”,必然得是满足了相关的需求,
不能是开发者一厢情愿而为之。
当然为了追求技术精进,高度可扩展的案例,也是非常值得学习的。
这并不冲突。
我们可以身怀绝技,但用的时候却只 “恰到好处”。
这才是行家的手笔呀。