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

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

总览


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


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


  • 结构化编程

结构化编程对程序控制权的直接转移进行了限制和规范。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 语句。更重要的是,这也是为什么在架构设计领域,功能性降解拆分仍然是最佳实践之一。


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


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

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

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

相关文章
|
Go
终极对决:Go语言make和new完整比较
终极对决:Go语言make和new完整比较
1504 0
|
编解码 物联网 API
"揭秘SD文生图的神秘面纱:从选择模型到生成图像,一键解锁你的创意图像世界,你敢来挑战吗?"
【10月更文挑战第14天】Stable Diffusion(SD)文生图功能让用户通过文字描述生成复杂图像。过程包括:选择合适的SD模型(如二次元、2.5D、写实等),编写精准的提示词(正向和反向提示词),设置参数(迭代步数、采样方法、分辨率等),并调用API生成图像。示例代码展示了如何使用Python实现这一过程。
584 4
|
人工智能 Cloud Native 安全
从云原生到 AI 原生,网关的发展趋势和最佳实践
本文整理自阿里云智能集团资深技术专家,云原生产品线中间件负责人谢吉宝(唐三)在云栖大会的精彩分享。讲师深入浅出的分享了软件架构演进过程中,网关所扮演的各类角色,AI 应用的流量新特征对软件架构和网关所提出的新诉求,以及基于阿里自身实践所带来的开源贡献和商业能力。
907 100
|
12月前
【HarmonyOS Next开发】实现矩形上下拖动、动态拖拽修改高度
实现一个矩形块上下拖动,并且可以拖动边缘定位点改变矩形块高度。
274 6
【HarmonyOS Next开发】实现矩形上下拖动、动态拖拽修改高度
|
Java Linux Go
一文带你速通Go语言基础语法
本文是关于Go语言的入门介绍,作者因其简洁高效的特性对Go语言情有独钟。文章首先概述了Go语言的优势,包括快速上手、并发编程简单、设计简洁且功能强大,以及丰富的标准库。接着,文章通过示例展示了如何编写和运行Go代码,包括声明包、导入包和输出语句。此外,还介绍了Go的语法基础,如变量类型(数字、字符串、布尔和复数)、变量赋值、类型转换和默认值。文章还涉及条件分支(if和switch)和循环结构(for)。最后,简要提到了Go函数的定义和多返回值特性,以及一些常见的Go命令。作者计划在后续文章中进一步探讨Go语言的其他方面。
498 0
|
关系型数据库 MySQL 应用服务中间件
502 Bad Gateway错误分析与解决方案
502 Bad Gateway错误通常发生在客户端与服务器通信时,表示网关或代理未能从上游服务器获取有效响应。本文分析了该错误的可能原因,包括LNMP安装包问题、加速器配置错误、PHP-CGI进程不足等,并提供了详细的解决方案,如手动安装PHP、调整配置参数、清理磁盘空间等。针对Nginx,还介绍了关键参数调整方法和实施步骤。通过这些方法,可有效解决502错误,提高服务器稳定性。注意备份数据并谨慎操作。
3726 2
|
机器学习/深度学习 人工智能
【AI大模型】深入Transformer架构:编码器部分的实现与解析(下)
【AI大模型】深入Transformer架构:编码器部分的实现与解析(下)
|
消息中间件 缓存 Java
Java 最常见的面试题:怎么保证缓存和数据库数据的一致性?
Java 最常见的面试题:怎么保证缓存和数据库数据的一致性?
|
机器学习/深度学习 算法 Python
使用Python实现强化学习算法
使用Python实现强化学习算法
351 1
使用Python实现强化学习算法
Mac 打开/关闭 iCloud 后导致桌面文件夹、文档删除,恢复步骤!
Mac 打开/关闭 iCloud 后导致桌面文件夹、文档删除,恢复步骤!
665 0