编程语言

与成百种编程语言(Programming Language)相比,编程范式(Programming Paradigm、范式)要少得多。

如图所示,共有27种范式。多数范式之间仅相差一个或几个概念。

主要的范式

最常用的范式有三个:过程试编程,面向对象编程(OOP),函数式编程(FP)。然后我们介绍一下新兴的第四种范式也就是面向切面编程(AOP)。

过程试编程

过程式编程(Procedural programming)的核心在于模块化,在实现过程中使用了状态,依赖了外部变量,导致很容易影响附近的代码,可读性较低,后期的维护成本也较高。

过程试编程经历了发展的两个阶段,非结构化到结构化

非机构化编程(Unstructured programming):机器语言和汇编语言的编程范式被认为是非结构化编程,没有封装函数的概念,代码中goto语句满天飞的状态。

结构化编程(Structured programming):抽象了机器的行为,屏蔽了部分计算机的硬件细节。代表语言就是我们常用的C语言。

有时结构化编程,也称作过程式编程,或面向过程编程。

面向对象编程

面向对象编程(Object-oriented programming)的核心在于抽象,提供清晰的对象边界。结合封装、集成、多态特性,降低了代码的耦合度,提升了系统的可维护性。C++ 和 之后的 Java 成为主流。

人们将领域问题又开始映射成实体及关系(程序 = 实体 + 关系),而不再是数据结构和算法(过程)了,这就是面向对象编程,核心特点是封装、继承和多态。

函数式编程

函数式编程(Functional Programming)的核心在于“避免副作用”,不改变也不依赖当前函数外的数据。结合不可变数据、函数是第一等公民等特性,使函数带有自描述性,可读性较高。

首先,函数式编程的主要理论基础是 Lambda 演算,它是图灵完备的;其次,函数式编程是抽象代数思维,更加接近现代自然科学,使用一种形式化的方式来解释世界,通过公式来推导世界,极度抽象(比如 F=ma)。在这条路上,很多人都是偏学术风格的,他们关注解决方案是否优雅,如何一层层构建抽象。他们也探索更多的可能,垃圾回收机制就是从这里率先出来的。

面向切面编程

面向切面编程(Aspect Oriented Programming、AOP)为开发人员提供了一种描写叙述横切关注点的机制,并可以自己主动将横切关注点织入到面向对象的软件系统中。从而实现了横切关注点的模块化。

AOP可以将那些与业务无关,却为业务模块所共同调用的逻辑或责任。比如事务处理、日志管理、权限控制等。封装起来,便于降低系统的反复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

python 可以使用装饰器实现AOP。

参考/补充

主要三种范式的对比

ProgParaSum

领域驱动设计

不难看出,编程语言的发展就是一个逐步远离计算机硬件,向着待解决的领域问题靠近的过程。所以,编程语言后续的发展方向就是探索怎么更好的解决领域问题,也就是领域驱动设计(Domain-driven Design、DDD)。

DDD 的精髓是对边界的划分和控制,共有四重边界:

  • 第一重边界是在问题空间分离子域,包括核心域,支撑域和通用域。
  • 第二重边界是在解决方案空间拆分 BC(限界上下文,Bounded Context),BC 之间的协作关系通过 Context Mapping(上下文映射) 来表达。
  • 第三重边界是在 BC 内部分离业务复杂度和技术复杂度,形成分层架构,包括用户界面层,应用层,领域层和基础设施层。
  • 第四重边界是在领域层引入聚合这一最小的设计单元,它从完整性与一致性对领域模型进行了有效的隔离,聚合内部包括实体、值对象、领域服务、工厂和仓储等设计元素。

设计原则与模式

设计原则很多,程序员最常使用的是 SOLID 原则,它是一套比较成体系的设计原则。它不仅可以指导我们设计模块(类),还可以被当作一把尺子,来衡量我们设计的有效性。
SOLID 原则是五个设计原则首字母的缩写,它们分别是:

单一职责原则(Single responsibility principle,SRP):一个类应该有且仅有一个变化的原因
开放封闭原则(Open–closed principle,OCP):软件实体(类、模块、函数)应该对扩展开放,对修改封闭
里氏替换原则(Liskov substitution principle,LSP):子类型(subtype)必须能够替换其父类型(base type)
接口隔离原则(Interface segregation principle,ISP):不应强迫使用者依赖于它们不用的方法
依赖倒置原则(Dependency inversion principle,DIP):高层模块不应依赖于低层模块,二者应依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象

前面我们提到,对于面向对象来说,核心是多态的设计,我们看看 SOLID 原则如何指导多态设计:

单一职责原则:通过接口分离变与不变,隔离变化
开放封闭原则:多态的目标是系统对于变化的扩展而非修改
里氏替换原则:接口设计要达到细节隐藏的圆满效果
接口隔离原则:面向不同客户的接口要分离开
依赖倒置原则:接口的设计和规定者应该是接口的使用方

除过设计原则,我们还要掌握常用的设计模式。设计模式是针对一些普遍存在的问题给出的特定解决方案,使面向对象的设计更加灵活和优雅,从而复用性更好。学习设计模式不仅仅要学习代码怎么写,更重要的是要了解模式的应用场景。不论那种设计模式,其背后都隐藏着一些“永恒的真理”,这个真理就是设计原则。的确,还有什么比原则更重要呢?就像人的世界观和人生观一样,那才是支配你一切行为的根本。可以说,设计原则是设计模式的灵魂。

守破离是武术中一种渐进的学习方法:

第一步——守,遵守规则直到充分理解规则并将其视为习惯性的事
第二步——破,对规则进行反思,寻找规则的例外并“打破”规则
第三步——离,在精通规则之后就会基本脱离规则,抓住其精髓和深层能量

设计模式的学习也是一个守破离的过程:

第一步——守,在设计和应用中模仿既有设计模式,在模仿中要学会思考
第二步——破,熟练使用基本设计模式后,创造新的设计模式
第三步——离,忘记所有设计模式,在设计中潜移默化的使用