指令式编程和声明式编程

指令式编程,Imperative Programming,是一种编程泛型,通过编程指令,告诉计算机,每个步骤执行的命令,计算机按照代码的指令,逐行执行,就能得到最终结果。

指令式编程的优点是非常符合直觉,代码发出命令,计算机执行。所以,这种编程泛型也非常容易学习,我们入门学习的 C 语言,Java 语言等等,都是支持指令式编程的,也是这类语言的主要编程泛型。

面向对象编程,也是一种编程泛型,同时,面向对象编程泛型,也是一种指令式编程泛型的特例。所以,指令式编程,是一个更抽象的概念。

声明式编程,Declarative Programming,顾名思义,这种编程泛型,更倾向于告诉计算机,“是什么”,由计算机自行决定如何操作。

声明式编程是很不好理解的,因为有不少无法不言自明的东西。程序,只需要告诉计算机,两个不同的状态,怎么从一个状态,切换到另一个状态,计算机自动就可以完成补充。

比如我正在学习的 Flutter,这个框架在构建一个应用的界面的时候,比如要做一个功能是这样的,界面是一个按钮,点击后,可以隐藏界面的上的数字,切换成星号。

如果用指令式编程,我们可能会这样写(伪代码):

1
button.onClick(function() { label.text.hide(); })

如果是声明式编程,我们可能是这样写:

1
2
3
4
5
6
7
8
9
10
Panel(
Label(
text: hide ? "***" : "12345"
)
Button(
onClick: function() {
hide = !hide
}
)
)

在指令式编程泛型里,我们给 label 下达了一个命令,让其对内容进行隐藏。而在声明式编程里,我们告诉界面,根据 hide 这个标志决定,是显示星号,还是显示数字。而点击事件里,我们只是重新指定了 hide 的值。那么,界面上本来是 12345,是怎么变成 *** 的呢?代码里没有提及,你也不能期待,代码执行到某一行,界面上的数字就会变成星号。这些都是框架自行决定和调度的。

其实,我们不难想象,框架或者系统底层,肯定会有一个指令,在某个时间,告诉图形引擎,要把数字擦掉,重新绘制上星号,不过这些都跟写上层业务的程序员无关。所以,指令式编程泛型是根本,毕竟 CPU 终究机器代码,或者汇编指令来驱动的,不可能不回归到指令式编程泛型里。

声明式编程泛型,是比指令式编程泛型更高层级的方法论抽象。就好像,一个公司只描述公司的愿景是什么,至于怎么实现,就要从总裁到基层员工每个人努力工作,朝着目标努力,经过漫长时间才能做到。

使用声明式编程泛型,程序员的生产力可以更多地释放,编程效率也更高,但是显然,底层框架或者引擎,都会承担更多的工作,才能做到智能地在程序员声明的界面或者状态中间完成变化。

-完-