当前位置: 首页 > news >正文

书摘:C 嵌入式系统设计模式 02

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。

本系列描述我对书中内容的理解。

结构化编程将软件组织成两个截然不同的方面:数据和行为。面向对象的方法将两者结合起来,让紧密耦合的元素更内聚,并提高内容的封装。C 是结构化语言,但它可以用于开发面向对象的嵌入式系统。

这里提到了 结构化编程面向对象编程 ,C 语言支持结构化编程, C++ 则支持面向对象编程。其实到目前为止,还有第 3 种编程范式,那就是 函数式编程 。这三种编程范式至今都在广泛使用,它们诞生至今已经有相当长的时间了。正如我在《关于编程》中提到的:

  • 1958 年 John Mccarthy 发明了 LISP 语言,函数式编程 范式诞生
  • 1966 年 Ole Johan DahlKriste Nygaard 的论文开创了 面向对象编程 范式
  • 1968 年 Edsger Wybe Dijkstra 论证了 goto 语句的危害,结构化编程 范式诞生

经过了几十年的发展,今天的编程范式与过去完全一样,也是结构化编程 范式、 面向对象编程 范式和 函数式编程 范式,再没有出现新的编程范式。

结构化编程 的核心理念是将复杂的程序问题分解为更小、更容易管理的子问题。“结构化”在这里意味着用只用有限的几种结构(顺序、分支、循环)来构建程序,避免使用 goto 等可能导致程序流程难以跟踪和控制的结构。

结构化编程是由 Edsger Wybe Dijkstra 于 1968 年提出的。Dijkstra 于1930 年出生于荷兰,他很早就发现编程是一件难度很大的工作。一段程序无论复杂与否,都包含了很多细节信息,这远超一个程序员的认知能力范围。而即便是一个小细节的错误,也会造成整个程序出错。他想用数学来证明程序是正确的,而且他也成功了。

Dijkstra 在研究的过程中发现了一个问题:不加限制的 goto 语句导致模块无法拆分成更小的、可被证明的单元,如果禁用 goto,只使用顺序结构、分支结构(if-then-else)和循环结构(do–while)编程,那么程序就可以被数学所证明。于是,结构化编程诞生了。

1968 年,Dijkstra 写了那封著名的,后来发表于 CACM ,标题为《Go To Statement Considered Harmful》的文章。“goto 是有害的”这个观点,这在当时引起了很多程序员的不满。在当时,使用汇编跳转是家常便饭,因此 Dijkstra 的观点掀起了一场长达 10 年的辩论。然而,最后辩论还是平息了,因为事实证明, Dijkstra 是对的。

Dijkstra 的工作是证明一段程序在数学上是正确的,这在实际操作中可太难了。工程界采用的是方法是证明这个程序是错误的,证伪可比证实简单多了,只要能找到一个 BUG,证明就结束了。如果这段程序经过一定的努力无法证伪,我们则认为它在当下是足够正确的。值得注意的是,只有在可证明的程序上,才可以使用这种方法证伪。如果某段程序采用了不加限制的 goto 语句,那么再多的测试也不能证明其正确性。

结构化编程范式促使我们将功能递归的分解为一系列可证明的小函数,然后再编写相关的测试来试图证明这些函数是错的。如果这些测试无法证伪这些函数,那么我们就可以认为这些函数是足够正确的,进而推导整个程序是正确的。

作者说“结构化编程将软件组织成两个截然不同的方面:数据和行为。面向对象的方法将两者结合起来,让紧密耦合的元素更内聚,并提高内容的封装。”这句话我并不是很理解,在我的认识里,无论结构化编程还是面向对象编程,优秀的程序员们总是首先关注数据结构,不仅要考虑如何表示数据,还要考虑如何使用数据。因此无论用什么编程范式,数据和行为都是天然结合起来的,不存在结构化编程将软件组织成两个截然不同的方面。不同的是,结构化编程语言在 文件 中实现数据和行为的结合,面向对象编程在 中实现数据和行为的结合,从本质上讲,这不过是形式上的不同,思想上,它们是一致的。

然后是关于封装。封装就是隐藏不必要的细节,包括数据结构和实现细节。一个最好的例子是文件系统。文件系统的实现非常复杂,有一个很大的数据结构,但这些都被精心隐藏起来了,你只需要操作几个简单的函数 openreadwrite,就可以完成大部分文件操作。模块的头文件就是模块的接口,这里面可以只有 API 函数声明,没有任何数据结构的声明,但 C++ 就办不到,因为技术的限制,C++ 的头文件中必须包含类的声明,这样类中的所有元素都暴露在外了。如果只是谈封装,C 语言是要好于 C++ 的。

“C 可以用于开发面向对象的嵌入式系统”,这是书中的一个结论。我认同这个结论,不是说要使用复杂的宏定义封装 C 语言,模仿 C++ 的语法,而是要深刻理解面向对象的思想,站在更高的层次上编程,首先要理解的,也是最重要的,是 多态

多态 是指多种形态,就是指同一个方法的行为随上下文而异。归根结底,多态不过是函数指针的一种应用。举一个例子:某设备具有多种运行模式:普通模式、访客模式、特权模式…,对于每种模式,显示方式不同、控制逻辑不同、上传的数据也不同。遇到这样的情况,你会下意识用 switch - case 语句解决吗?如果你使用 switch - case 语句解决,那么在显示、控制、上传这些地方,都会有一个 switch - case 语句,不断地重复各种模式。这还没完,当你新增一个模式时,还需要在所有关于模式的 switch 语句处增加 case 语句,来处理新的模式。可以用函数指针代替 switch - case 语句。

首先,我们抽象出一个接口,接口就是一系列函数指针,这些指针规定了每种模式都需要操作的函数原型。然后每种模式都自己实现这些函数。最后将实现的函数动态的绑定到函数指针上,对使用接口的代码而言,它们再也不需要 switch - case 语句区分模式了,它们甚至无需关注模式,因为接口对此做了隐藏。就像在你的电脑上,文件系统是一个接口,我们只管用 write 函数存储参数,而不用理会存储介质,电脑上装的是硬盘就存硬盘上,装的是刻录机就存光盘上。

当理解了面向对象编程思想,理解了 SOLID 设计模式,我写代码的原则变成了只有以下 2 条:

  • 用测试驱动开发编写最简洁的代码。
  • 编写设备无关的代码

怎么算简洁?一个函数,你看上一遍,能拍着胸脯对自己说,它绝不会有 BUG ,这就是简洁。与之相反的,有一个函数,你看上半天,最后只能说,没有看到明显的 BUG,这就是复杂。

什么是设备无关的代码?不依赖具体硬件、不依赖底层实现,就像在应用层存储数据不必知道存哪种介质,只有这样,你才能更方便的更换存储介质。与之相反的,应用层中的函数一路调用下去,可以看到寄存器,那么应用层就跟硬件深度绑定了,任何硬件的改动,都要更改大量的代码。

相关文章:

书摘:C 嵌入式系统设计模式 02

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。 本系列描述我对书中内容的理解。 结构化编程将软件组织成两个截然不同的…...

排序算法基本原理及实现1

📑打牌 : da pai ge的个人主页 🌤️个人专栏 : da pai ge的博客专栏 ☁️宝剑锋从磨砺出,梅花香自苦寒来 📑插入排序 &#x1f4…...

Unity 轨道展示系统(DollyMotion)

DollyMotion 🍱功能展示🥙使用💡设置路径点💡触发点位切换💡动态更新路径点💡事件触发💡设置路径💡设置移动方案固定速度方向最近路径方向 💡设置移动速度曲线 传送门 &a…...

优维低代码实践:搜索功能

优维低代码技术专栏,是一个全新的、技术为主的专栏,由优维技术委员会成员执笔,基于优维7年低代码技术研发及运维成果,主要介绍低代码相关的技术原理及架构逻辑,目的是给广大运维人提供一个技术交流与学习的平台。 优维…...

C# ReadOnlyRef Out

C# ReadOnly ReadOnly先看两种情况1.值类型2.引用类型 结论 Ref Out ReadOnly官方文档 ReadOnly 先看两种情况 1.值类型 当数据是值类型时,标记为Readonly时,如果再次设置值,会提示报错,无法分配到只读字段 public class A {pri…...

linux 服务 下 redis 安装和 启动

官网下载 https://redis.io/download/ 安装步骤: 1.安装redis 所需要的依赖 yum install -y gcc tcl2.上传安装包并解压,下载安装包,上传到/usr/local/src目录,解压 tar -zxvf redis-7.2.3.tat.gz进入安装目录,运行…...

ECharts与Excel的结合实战

引言&#xff1a;本文是一篇ECharts和Excel实战的记录。将Excel与ECharts产生火花&#xff0c;从Excel读取数据然后在ECharts上展示。 1.柱状图前端代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title…...

UDP的特点及应用场景

目录 UDP特点 应用场景 总结 User Datagram Protocol&#xff08;UDP&#xff0c;用户数据报协议&#xff09;是互联网协议套件中的一种传输层协议。与TCP不同&#xff0c;UDP是一种无连接的、不可靠的协议。 UDP特点 要知道UDP可以用来做什么&#xff0c;首先我们要知道它…...

Python开发——工具篇 Pycharm的相关配置,Python相关操作 持续更新

前言 本篇博客是python开发的工具篇相关&#xff0c;介绍pycharm的使用和相关配置&#xff0c;收录python的相关操作&#xff0c;比如如何启动jupyter。 目录 前言引出Pycharmpycharm如何不同等级日志显示不同颜色设置不同pycharm的python环境 Python操作如何启动Jupyter 总结…...

【深度学习】卷积神经网络结构组成与解释

卷积神经网络是以卷积层为主的深度网路结构&#xff0c;网络结构包括有卷积层、激活层、BN层、池化层、FC层、损失层等。卷积操作是对图像和滤波矩阵做内积&#xff08;元素相乘再求和&#xff09;的操作。 1. 卷积层 常见的卷积操作如下&#xff1a; 卷积操作解释图解标准卷…...

从源码解析Containerd容器启动流程

从源码解析Containerd容器启动流程 本文从源码的角度分析containerd容器启动流程以及相关功能的实现。 本篇containerd版本为v1.7.9。 更多文章访问 https://www.cyisme.top 本文从ctr run命令出发&#xff0c;分析containerd的容器启动流程。 ctr命令 查看文件cmd/ctr/comman…...

引迈-JNPF低代码项目技术栈介绍

从 2014 开始研发低代码前端渲染&#xff0c;到 2018 年开始研发后端低代码数据模型&#xff0c;发布了JNPF开发平台。 谨以此文针对 JNPF-JAVA-Cloud微服务 进行相关技术栈展示&#xff1a; 1. 项目前后端分离 前端采用Vue.js&#xff0c;这是一种流行的前端JavaScript框架&a…...

如何处理枚举类型(下)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 上一篇我们通过编写MyB…...

wsj0数据集原始文件.wv1.wv2转换成wav文件

文章目录 准备一、获取WSJO数据集二、安装sph2pipe三、转换代码四、结果展示 ​ 最近做语音分离实验需要用到wsj0-2mix数据集&#xff0c;但是从李宏毅语音分离教程里面获取的wsj0-2mix只有一部分。从网上获取到了完整的WSJO数据集后&#xff0c;由于原始的语音文件后缀是wv1或…...

Flask Session 登录认证模块

Flask 框架提供了强大的 Session 模块组件&#xff0c;为 Web 应用实现用户注册与登录系统提供了方便的机制。结合 Flask-WTF 表单组件&#xff0c;我们能够轻松地设计出用户友好且具备美观界面的注册和登录页面&#xff0c;使这一功能能够直接应用到我们的项目中。本文将深入探…...

【运维】hive 高可用详解: Hive MetaStore HA、hive server HA原理详解;hive高可用实现

文章目录 一. hive高可用原理说明1. Hive MetaStore HA2. hive server HA 二. hive高可用实现1. 配置2. beeline链接测试3. zookeeper相关操作 一. hive高可用原理说明 1. Hive MetaStore HA Hive元数据存储在MetaStore中&#xff0c;包括表的定义、分区、表的属性等信息。 hi…...

C#开发的OpenRA游戏之属性SelectionDecorations(13)

C#开发的OpenRA游戏之属性SelectionDecorations(13) 在前面分析SelectionDecorations属性类时,会发现它有下面这个属性: public class SelectionDecorations : SelectionDecorationsBase, IRender { readonly Interactable interactable; 它是定义了一个Interactabl…...

接手了一个外包开发的项目,我感觉我的头快要裂开了~

嗨&#xff0c;大家好&#xff0c;我是飘渺。 最近&#xff0c;我和小伙伴一起接手了一个由外包团队开发的微服务项目&#xff0c;这个项目采用了当前流行的Spring Cloud Alibaba微服务架构&#xff0c;并且是基于一个“大名鼎鼎”的微服务开源脚手架&#xff08;附带着模块代…...

git常规使用方法,常规命令

Git是一种分布式版本控制系统&#xff0c;它可以记录软件的历史版本&#xff0c;并提供了多人协作开发、版本回退等功能。以下是Git的基本使用方法&#xff1a; 安装Git&#xff1a;下载安装包并进行安装&#xff0c;安装完成后在命令行中输入 git --version 进行验证。 初始化…...

【JavaScript】3.3 JavaScript工具和库

文章目录 1. 包管理器2. 构建工具3. 测试框架4. JavaScript 库总结 在你的 JavaScript 开发之旅中&#xff0c;会遇到许多工具和库。这些工具和库可以帮助你更有效地编写和管理代码&#xff0c;提高工作效率。在本章节中&#xff0c;我们将探讨一些常见的 JavaScript 工具和库&…...

基于XGBoost与SHAP的分子气味预测:从特征工程到可解释性分析

1. 项目概述与核心价值在香水设计、食品风味工业乃至环境监测领域&#xff0c;一个核心且持久的挑战是&#xff1a;如何从分子的化学结构出发&#xff0c;准确预测其气味&#xff1f;这不仅仅是化学家或调香师的直觉游戏&#xff0c;更是一个复杂的、高维度的模式识别问题。传统…...

开发转兼职DBA(二):执行计划教我做事

开发转兼职DBA&#xff08;二&#xff09;&#xff1a;执行计划教我做事 查询慢了不知道为什么&#xff0c;加了索引还是慢&#xff0c;复合索引怎么建&#xff0c;执行计划怎么看——这些不是DBA的专利&#xff0c;是每个写SQL的开发者迟早要面对的事。 文章目录 开发转兼职DB…...

终极Chrome画中画扩展:如何在浏览器中实现高效视频多任务处理

终极Chrome画中画扩展&#xff1a;如何在浏览器中实现高效视频多任务处理 【免费下载链接】picture-in-picture-chrome-extension 项目地址: https://gitcode.com/gh_mirrors/pi/picture-in-picture-chrome-extension 想要在浏览网页、处理文档的同时继续观看视频内容吗…...

别再只用递归了!用C语言栈实现非递归快速排序,内存效率提升实战

从递归到迭代&#xff1a;C语言栈实现非递归快速排序的工程实践 在嵌入式开发和大规模数据处理场景中&#xff0c;递归实现的快速排序常常面临栈溢出风险。当排序10万个元素的数组时&#xff0c;递归深度可能达到log₂100000≈17层&#xff0c;在仅有2KB栈空间的STM32F103上极易…...

通用物联网开发板设计:基于ESP8266的硬件集成与开发实践

1. 项目概述&#xff1a;为什么我们需要一块“通用”的物联网开发板&#xff1f;在捣鼓了几年物联网项目之后&#xff0c;我发现自己桌面上堆满了各种开发板&#xff1a;ESP8266、ESP32、Arduino Uno、STM32 Nucleo……每个项目都要重新连线、配置电源、焊接传感器接口&#xf…...

render_async嵌套渲染:构建复杂异步界面的完整解决方案

render_async嵌套渲染&#xff1a;构建复杂异步界面的完整解决方案 【免费下载链接】render_async render_async lets you include pages asynchronously with AJAX 项目地址: https://gitcode.com/gh_mirrors/re/render_async 在现代Web开发中&#xff0c;页面加载速度…...

微信聊天图片丢了别慌!保姆级教程:找回并解密DAT文件(支持新旧版微信路径)

微信DAT图片恢复实战&#xff1a;从文件定位到批量解密的完整指南 微信聊天记录中的图片突然消失&#xff1f;别急着放弃&#xff01;那些看似无法打开的DAT文件里&#xff0c;可能藏着您的重要回忆或工作资料。本文将带您深入微信存储机制&#xff0c;手把手完成从文件定位到…...

从科研图表到商业报表:如何用Matplotlib的legend()提升你的图表专业度?

从科研图表到商业报表&#xff1a;如何用Matplotlib的legend()提升你的图表专业度&#xff1f; 在数据驱动的决策时代&#xff0c;图表不仅是科研论文中的证据载体&#xff0c;更是商业汇报中的说服工具。我曾见证一位生物统计学家将同一组临床试验数据呈现给三种不同受众&…...

Noto字体终极指南:告别“豆腐块“,让全球文字清晰显示

Noto字体终极指南&#xff1a;告别"豆腐块"&#xff0c;让全球文字清晰显示 【免费下载链接】noto-fonts Noto fonts, except for CJK and emoji 项目地址: https://gitcode.com/gh_mirrors/no/noto-fonts 在数字世界中&#xff0c;你是否经常看到那些令人困…...

告别手动标注!用SAM(Segment Anything)和Python脚本,5分钟批量生成你的分割数据集

5分钟批量生成分割数据集&#xff1a;SAM自动化标注全流程实战 在计算机视觉领域&#xff0c;数据标注一直是制约模型开发效率的瓶颈。传统手工标注不仅耗时费力&#xff0c;还容易引入人为误差。Meta开源的Segment Anything Model&#xff08;SAM&#xff09;彻底改变了这一局…...