编程范式的演进:增加约束(读之二)

    目前为止只存在三种编程范式(可能也不会有第四种了),结构化编程、面向对象编程 和 函数式编程。

图片发自App


    结构化编程基于严格的数学证明,只需要顺序、分支和循环三种结构就可以制造出任何程序(图灵完备)。Dijkstra 指出goto语句不必要而且是有害的,进而希望给出程序的形式化证明,即对功能进行降解拆分到最基本的结构,再证明每个结构的正确性就可以证明整个程序的正确性,这里证明的复杂度实际上是被大大降低的,并不需要遍历所有可能的组合。实际上没有人这么做。结构化编程留下的重要思想是不是goto有害,而是对功能进行降解和拆分,将功能拆分到一个个可以被验证的小函数。思想有两种伟大,第一种打到了当时不可一世的巨人(贵族或者谬误),被打倒的巨人再也站不起来进而这个打倒成为一个历史事件,比如被弃用的goto;另一种是,创造一种思想的工具,被收入在工具箱,时时派上用场,比如功能性降解拆分。可惜这种降解拆分还没有成为本科编程教学的一部分,否则我们就不会需要就某些基本常识反复给新入行者纠正(比如别写大函数)。

    面向对象,是三种范式中唯一没有数学证明作为基础的范式,这也就决定了它的模糊性,不容易给一个一般的定义。bob大叔看来,面向对象思想编程方法中最珍贵的不是封装和继承,而是多态。从架构角度看依赖倒置是非常重要的,即应该面向接口(抽象)来做设计。要实现对抽象的依赖,c语言中提供的手段是函数指针。但函数指针的危险性是众所周知的,而oo提供了多态,可以用接口类来轻松的实现依赖倒置,进而实现插件式的架构,即核心业务逻辑用抽象接口来说明自己的需求,而外围服务(界面、数据库等)实现这些接口。这样业务逻辑就对外围服务没有了依赖,并且容易插拔不同的服务插件(只要它们满足业务逻辑的抽象接口即可)。这种设计并不一定要oo才可以实现,只是oo提供了一种机制,大大降低了实现的难度。注意,oo并没有降低设计的难度。

    函数式编程,取消了变量。如果不考虑巨大的物理资源开销,这是更安全更可靠的方法。需要强调的是,这并没有降低设计的难度,你获得了一个新的拆分维度,即将可变性模块和不变性模块分离。

图片发自App


    站在架构设计角度,重新看结构化编程和面向对象编程: 前者强调功能性降解拆分(functional  decomposition)的可能性和必要性,分治是降低问题复杂度的不二法门,但需要面对以抽象接口为锚点的组合问题。OO提供了一种组合的便利性(多态)。没有方便的工具,再理想的设计理念都难以普及。也只有在一种职业有相当的规模后,一般性的工具才会涌现出来。

    BOB大叔告诉我们,三个编程范式实际上并没有给编程(程序员)提供新的能力,而是分别提出了约束,结构化编程约束了程序控制权的直接转移(禁止goto),面向对象约束了程序控制权的间接转移(用多态替代函数指针),函数式编程禁止了赋值操作! 50年来,我们只是学会了什么不应该做。这个洞见非常深刻。三个范式的提出和普及伴随着编程规模的大规模增长。Dijkstra时代"程序员”还不是一个被认可的职业,今天"写程序"某种程度上也不是一种职业而是一种基本工具。程序员没来得及专业化,就已经被去专业化了,这是人类历史中比较罕见的一种情况!如是,关于编程基本的方法论和纪律都没有完全形成或者在“专业人士”内部普及。再想一下敏捷软件开发这件事,精英化(专业化)的考虑团队能力建设和定义工作方式是有困难的。道和术要分开,牧羊犬和羊群要分开。一般的团队需要制定明确的降解拆分的方法和组合手段,然后用技术手段增加约束(比如提供白名单,禁止使用范围之外的方法),最终约束羊群不会跑到危险之地。

你可能感兴趣的:(编程范式的演进:增加约束(读之二))