企业建站找哪家,网站在当地做宣传,用手机做网站的软件,做网站的模板本书的原著为#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》#xff0c;讲解的是嵌入式系统设计模式#xff0c;是一本不可多得的好书。
本系列描述我对书中内容的理解。 结构化编程将软件组织成两个截然不同的…本书的原著为《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》讲解的是嵌入式系统设计模式是一本不可多得的好书。
本系列描述我对书中内容的理解。 结构化编程将软件组织成两个截然不同的方面数据和行为。面向对象的方法将两者结合起来让紧密耦合的元素更内聚并提高内容的封装。C 是结构化语言但它可以用于开发面向对象的嵌入式系统。 这里提到了 结构化编程 和 面向对象编程 C 语言支持结构化编程 C 则支持面向对象编程。其实到目前为止还有第 3 种编程范式那就是 函数式编程 。这三种编程范式至今都在广泛使用它们诞生至今已经有相当长的时间了。正如我在《关于编程》中提到的
1958 年 John Mccarthy 发明了 LISP 语言函数式编程 范式诞生1966 年 Ole Johan Dahl 和 Kriste 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 语句那么再多的测试也不能证明其正确性。
结构化编程范式促使我们将功能递归的分解为一系列可证明的小函数然后再编写相关的测试来试图证明这些函数是错的。如果这些测试无法证伪这些函数那么我们就可以认为这些函数是足够正确的进而推导整个程序是正确的。
作者说“结构化编程将软件组织成两个截然不同的方面数据和行为。面向对象的方法将两者结合起来让紧密耦合的元素更内聚并提高内容的封装。”这句话我并不是很理解在我的认识里无论结构化编程还是面向对象编程优秀的程序员们总是首先关注数据结构不仅要考虑如何表示数据还要考虑如何使用数据。因此无论用什么编程范式数据和行为都是天然结合起来的不存在结构化编程将软件组织成两个截然不同的方面。不同的是结构化编程语言在 文件 中实现数据和行为的结合面向对象编程在 类 中实现数据和行为的结合从本质上讲这不过是形式上的不同思想上它们是一致的。
然后是关于封装。封装就是隐藏不必要的细节包括数据结构和实现细节。一个最好的例子是文件系统。文件系统的实现非常复杂有一个很大的数据结构但这些都被精心隐藏起来了你只需要操作几个简单的函数 open 、read、 write就可以完成大部分文件操作。模块的头文件就是模块的接口这里面可以只有 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这就是复杂。
什么是设备无关的代码不依赖具体硬件、不依赖底层实现就像在应用层存储数据不必知道存哪种介质只有这样你才能更方便的更换存储介质。与之相反的应用层中的函数一路调用下去可以看到寄存器那么应用层就跟硬件深度绑定了任何硬件的改动都要更改大量的代码。