1976 年,瑞士计算机科学家,Algol W,Modula,Oberon 和 Pascal 语言的设计师 Niklaus Emil Wirth写了一本非常经典的书《Algorithms + Data Structures = Programs》 ,即算法 + 数据结构 = 程序。这本书主要写了算法和数据结构的关系,这本书对计算机科学的影响深远,尤其在计算机科学的教育中。
1979 年,英国逻辑学家和计算机科学家 Robert Kowalski 发表论文 Algorithm = Logic + Control并且主要开发“逻辑编程”相关的工作。Robert Kowalski 是一位逻辑学家和计算机科学家,从 20 世纪 70 年代末到整个 80 年代致力于数据库的研究,并在用计算机证明数学定理等当年的重要应用上颇有建树,尤其是在逻辑、控制和算法等方面提出了革命性的理论,极大地影响了数据库、编程语言,直至今日的人工智能。
Robert Kowalski 在这篇论文里提到:
An algorithm can be regarded as consisting of a logic component, which specifies the knowledge to be used in solving problems, and a control component, which determines the problem-solving strategies by means of which that knowledge is used. The logic component determines the meaning of the algorithm whereas the control component only affects its efficiency. The efficiency of an algorithm can often be improved by improving the control component without changing the logic of the algorithm. We argue that computer programs would be more often correct and more easily improved and modified if their logic and control aspects were identified and separated in the program text.
翻译过来的意思大概就是:任何算法都会有两个部分, 一个是 Logic 部分,这是用来解决实际问题的。另一个是 Control 部分,这是用来决定用什么策略来解决问题。Logic 部分是真正意义上的解决问题的算法,而 Control 部分只是影响解决这个问题的效率。程序运行的效率问题和程序的逻辑其实是没有关系的。我们认为,如果将 Logic 和 Control 部分有效地分开,那么代码就会变得更容易改进和维护。
编程的本质
两位老先生的两个表达式:
Programs = Algorithms + Data Structures
Algorithm = Logic + Control
我们可以得出:Program = Logic + Control + Data Structure
本文着重说一下算法
我们的算法由两个逻辑组成,一个是真正的业务逻辑,另外一种是控制逻辑。程序中有两种代码,一种是真正的业务逻辑代码,另一种代码是控制我们程序的代码,叫控制代码,这根本不是业务逻辑,业务逻辑不关心这个事情
逻辑是指业务逻辑,逻辑过程的抽象,加上一个由术语表示的数据结构的定义,控制逻辑跟业务逻辑是没关系的,你控制,它执行。控制一个程序流转的方式,即程序执行的方式,并行还是串行,同步还是异步,以及调度不同执行路径或模块,数据之间的存储关系,这些和业务逻辑没有关系。
控制部分用来描述如何使用逻辑。最粗略的看法可以认为“控制”是解决问题的策略。对同一个逻辑,使用不同控制,所得到的算法,本质是等价的,因为它们解决同样的问题,并得到同样的结果。
Logic,它是程序复杂度的的下限,然后,我们为了控制程序,需要再搞出很多控制代码,于是 Logic+Control 的相互交织成为了最终的程序复杂度。
如果你看过那些混乱不堪的代码,你会发现其中最大的问题是我们把这 Logic 和 Control 纠缠在一起了,所以会导致代码很混乱,难以维护,Bug 很多。绝大多数程序复杂的原因就是这个问题,就如同下面这幅图中表现的情况一样。
有效地分离 Logic、Control 和 Data 是写出好程序的关键所在!
我们在写代码当中,就会看到好多这种代码,会把控制逻辑和业务逻辑放在一块。里面有些变量和流程是跟业务相关的,有些是不相关的。业务逻辑决定了程序的复杂度,业务逻辑本身就复杂,你的代码就不可能写得简单。
代码复杂度的原因:
业务逻辑的复杂度决定了代码的复杂度;
控制逻辑的复杂度 + 业务逻辑的复杂度 ==> 程序代码的混乱不堪;
绝大多数程序复杂混乱的根本原因:业务逻辑与控制逻辑的耦合。
如何分离 control 和 logic 呢?我们可以使用下面的这些技术来解耦。
State Machine
状态定义
状态变迁
条件状态的 action
DSL – Domain Specific Language
HTML,SQL,Unix Shell Script,AWK,正则表达式……
编程范式
面向对象:委托、策略、桥接、修饰、IoC/DIP、MVC……
函数式编程:修饰、管道、拼装逻辑推导式编程:Prolog
这就是编程的本质:Logic 部分才是真正有意义的(What)
Control 部分只是影响 Logic 部分的效率(How)