编程范式(一):结构化编程

简介: 编程范式(一):结构化编程

总览


上一篇文章: 寒草与《架构整洁之道》|树叶飞舞,故事开始🌟简要介绍了什么是设计与架构,以及架构的价值所在,本篇文章将介绍编程范式。


编程范式指的是程序的编写模式,与具体的编程语言关系相对较小。这些范式会告诉你应该在什么时候采用什么样的代码结构。直到今天,我们也一共只有三个编程范式:


  • 结构化编程

结构化编程对程序控制权的直接转移进行了限制和规范。Dijkstra 论证了使用 goto 这样的无限制跳转语句将会损害程序的整体结构,也是这位 Dijkstra 最先主张用我们现在熟知的 if/then/else 语句和 do/while/until 语句来代替跳转语句的。

  • 面向对象编程

面向对象编程对程序控制权的间接转移进行了限制和规范

  • 函数式编程

函数式编程对程序中的赋值进行了限制和规范


这三个编程范式都从某一方面限制和规范了程序员的能力。没有一个范式是增加新能力的。也就是说,每个编程范式的目的都是设置限制。这些范式主要是为了告诉我们不能做什么,而不是可以做什么。


另外,我们应该认识到,这三个编程范式分别限制了 goto 语句、函数指针和赋值语句的使用。


结构化编程


可推导性


编程是一项难度很大的活动。一段程序无论复杂与否,都包含了很多的细节信息。如果没有工具的帮助,这些细节的信息是远远超过一个程序员的认知能力范围的。而在一段程序中,哪怕仅仅是一个小细节的错误, 也会造成整个程序出错。

对于上面的问题,Dijkstra 提出的解决方案是采用数学推导方法。即:程序员可以用代码将一些己证明可用的结构串联起来,只要自行证明这些额外代码是正确的,就可以推导出整个程序的正确性。


Dijkstra 在研究过程中发现了一个问题: goto 语句的某些用法会导致某个模块无法被递归拆分成更小的、可证明的单元,这会导致无法采用分解法来将大型问题进一步拆分成更小的、可证明的部分。


goto 语句的其他用法虽然不会导致这种问题,但是 Dijkstra 意识到它们的实际 效果其实和更简单的分支结构 if-then-else 以及循环结构 do-while 是一致的 。 如果代码中只采用了这两类控制结构,则一定可以将程序分解成更小的、可证明的单元。


Bohm 和 Jocopini 证明了人们可以用顺序结构分支结构循环结构这三种结构构造出任何程序。这个发现非常重要: 因为它证明了我们构建可推导模块所需要的控制结构集与构建所有程序所需的控制结构集的最小集是等同的。 这样一来,结构化编程就诞生了。


科普一下顺序结构和分支结构的正确性可以用枚举法证明,但是循环结构需要采用**数学归纳法**:具体来说就是,首先要用枚举法证明循环 1 次的正确性,接下来再证明如果循环 N 次是正确的,那么循环 N+1 次也同样也是正确的。


GOTO 是有害的


这是一段有趣的故事:


1968 年,Dijkstra 曾经给 CACM 的编辑写过一封信 。 这封信后来发表于 CACM 3 月刊,标题是 Go To Statement Considered Harmfu/1, Dijkstra 在信中具体描绘了他对三种控制结构的看法。

由于当时还没有互联网,大家还不能直接上网发帖来对 Dijkstra 进行冷嘲热讽,他们唯一能做的,也是大部分人的选择,就是不停地给各种公开发表的报刊的编辑们写信。

有的信件的措辞并不那么友善,甚至是非常负面的。但是,也不乏强烈支持者。总之,这场火热的争论持续了超过 10 年 。


中间吐槽一句这一幕像极了现在网上的各种骂战,哈哈哈


这场辩论最终还是逐渐停止了。原因很简单: Dijkstra是对的。随着编程语言的演进,goto 语句的重要性越来越小,最终甚至消失了。如今大部分的现代编程语言中都己经没有了 goto 语句。


现如今,无论是否自愿,我们都是结构化编程范式的践行者了,因为我们用的编程语言基本上都己经禁止了不受限制的直接控制转移语句。


功能性降解拆分


既然结构化编程范式可将模块递归降解拆分为可推导的单元,这就意味着模块也可以按功能进行降解拆分。这样一来,我们就可以将一个大型问题拆分为一系列高级函数的组合,而这些高级函数各自又可以继续被拆分为一系列低级函数,如此无限递归。更重要的是,每个被拆分出来的函数也都可以用结构化编程范式来书写


通过采用这些技巧,程序员可以将大型系统设计拆分成模块和组件,而这些模块和组件最终可以拆分为更小的、可证明的函数。


网络异常,图片无法展示
|


其中思想至今仍被沿用🌟


结束语


网络异常,图片无法展示
|


结构化编程范式中最有价值的地方就是,它赋予了我们创造可证伪程序单元的能力。这就是为什么现代编程语言一般不支持无限制的 goto 语句。更重要的是,这也是为什么在架构设计领域,功能性降解拆分仍然是最佳实践之一。


最后还有一句话印象深刻:一段程序可以由一个测试来证明其错误性,但是却不能被证明是正确的。


✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

少年向来不识天高地厚
放眼处皆自负才高八斗
虽是自命风流
倒也坦诚无忧
我爱这样的少年
谦和而狂妄
骄傲又坦然☀️

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

相关文章
|
7月前
|
算法 测试技术 开发者
编程范式之争:面向对象与函数式的较量
在当今软件开发领域,面向对象编程(OOP)和函数式编程(FP)是两种备受瞩目的主流编程范式。本文将比较这两种范式的特点和优势,并探讨如何在实际项目中进行选择。
|
7月前
|
设计模式
编程范式之争:面向对象编程与函数式编程的对决
在软件开发领域,面向对象编程(OOP)和函数式编程(FP)一直是两种主要的编程范式。本文将探讨这两种编程风格的优缺点,比较它们在不同场景下的适用性,并提供选择合适编程范式的指导原则。
61 0
|
2月前
|
算法 JavaScript 前端开发
程序员需要掌握的 5种编程范式!
本文介绍了编程范式的基本概念及其重要性,详细解析了命令式编程与声明式编程两种主要范式。命令式编程包括面向过程与面向对象编程,强调逐步执行与模块化;声明式编程涵盖函数式、逻辑及响应式编程,注重描述目标而非具体步骤。通过对比各种范式的优缺点及示例代码,帮助读者理解不同场景下的适用性。
63 2
|
7月前
|
Rust 并行计算 JavaScript
函数式编程:革命性的编程范式
函数式编程:革命性的编程范式
|
7月前
|
大数据 开发者
探索编程范式:面向对象与函数式的抉择
在当今快速发展的软件开发领域,面向对象编程(OOP)和函数式编程(FP)是两种重要的编程范式。本文将深入比较这两种范式的特点、应用场景和优劣势,为读者提供选择时的参考,并探讨如何在实际项目中灵活运用它们。
|
7月前
|
并行计算 数据处理 开发者
Python函数式编程:探索优雅的编程范式
传统的编程范式中,命令式编程和面向对象编程占据主导地位。然而,Python函数式编程作为一种新颖而强大的范式,通过引入函数作为一等公民和不可变性等特性,为开发者提供了更加优雅和灵活的编码方式。本文将深入探讨Python函数式编程的概念与应用,包括高阶函数、纯函数、惰性计算以及函数式编程在并行处理和数据处理方面的实际应用。
|
7月前
|
Java 程序员 数据处理
探索编程范式:面向对象编程与函数式编程的比较与取舍
本文将探讨面向对象编程(OOP)和函数式编程(FP)两种主流的编程范式,并比较它们在代码组织、可复用性、并发性和代码风格等方面的特点。通过深入了解它们的优势和不足,读者可以更好地选择适合自己项目需求的编程范式。
274 1
|
7月前
|
并行计算 数据处理 开发者
编程范式的抉择:面向对象编程与函数式编程的对决
在当今的软件开发领域,面向对象编程(Object-Oriented Programming,OOP)和函数式编程(Functional Programming,FP)是两种重要的编程范式。本文将比较并探讨这两种编程范式的特点、优势和适用场景,以帮助开发者在编程选择上做出明智的决策。
|
SQL 存储 安全
程序员必须要知道的编程范式,你掌握了吗?
本文给大家介绍了什么是"编程范式",选择合适的编程范式可以提高代码的可读性、可维护性和可扩展性。
33418 42
|
设计模式 分布式计算 算法
聊聊编程范式
聊聊编程范式
聊聊编程范式