《程序设计实践》读书笔记第三至四章
第3章 设计与实现
数据结构设计是程序构造过程的中心环节。一旦数据结构安排好了,算法就像是瓜熟蒂落,编码也比较容易。
程序设计语言的选择在整个设计过程中,相对而言,并不是那么重要。程序的设计当然可以通过语言来装饰,但是通常不会为语言所左右。
3.1 马尔可夫链算法
3.2 数据结构的选择
3.3 在C中构造数据结构
3.4 生成输出
3.5 Java
3.6 C++
我们在这里希望更前进一步,使用C++的Standard Template Library(标准模板库),即STL。因为STL提供了许多内部机制,能完成我们需要做的许多事情。ISO的C++标准已经把STL作为语言定义的一部分。
3.7 Awk和Perl
3.8 性能
3.9 经验教训
第4章 界面
在进行设计的时候,必须考虑的问题包括:
l 界面:应提供哪些服务和访问?界面在效能上实际成为服务的提供者和使用者之间的一个约定。在这里要做的是提供一种统一而方便的服务,使用方便,有足够丰富的功能,而又不过多过滥以至无法控制。
l 信息隐藏:哪些信息应该是可见的,哪些应该是私有的?一个界面必须提供对有关部件的方便访问方式,而同时又隐蔽其实现的细节。这样,部件的修改才不会影响到使用者。
l 资源管理:谁负责管理内存或者其他有限的资源?这里的主要问题是存储的分配和释放,以及管理共享信息的拷贝等。
l 错误处理:谁检查错误?谁报告?如何报告?如果检查中发现了错误,那么应该设法做哪些恢复性操作?
4.1 逗号分隔的值
逗号分隔的值(comma-separated value),或CSV,是个术语,指的是一种用于表示表格数据的自然形式,使用很广泛。这里表格的每行是个正文行,行中不同的数据域由逗号分隔。
在下面几节里,我们要写出这个库的三个版本,其功能是读CSV数据,将它转换为内部表示。
4.2 一个原型库
4.3 为别人用的库
要建立一个其他人能用的界面,我们必须考虑在本章开始处列出的那些问题:界面、信息隐藏、资源管理和错误处理。它们的相互作用对设计有极强的影响。我们把这些问题分割开是有点太随意了,实际上它们是密切相关的。
新库的大小超过第一个原型的四倍,而且包含一些很复杂的代码。在从原型转换到产品时,程序在大小和复杂性方面有所扩张是很典型的情况。
4.4 C++实现
4.5 界面原则
一个界面要想成功,它就必须特别适合有关的工作—必须简单、通用、规范、其行为可以预料及坚固等等,它还必须能很好地适应用户或者实现方式的变化。好的界面总是遵循着一组原则,这些原则不是互相独立的,互相之间甚至可能并不很协调,但它们能帮助我们刻画那些位于界限两边的两部分软件之间的问题。
1) 隐藏实现细节。对于程序的其他部分而言,界面后面的实现应该是隐藏的,这样才能使它的修改不影响或破坏别的东西。人们用了许多术语来描述这种组织原则:信息隐蔽、封装、抽象和模块化,它们谈论的都是类似的思想。一个界面应该隐藏那些与界面的客户或者用户无关的实现细节。这些看不到的细节可以在不影响客户的情况下做修改。
2) 选择一小组正交的基本操作。一个界面应该提供外界所需要的全部功能,但是绝不要更多;函数在功能方面不应该有过度的重叠。虽然提供大量函数可能使库变得更容易使用,你需要什么就有什么。但是大的界面既难写又难维护,太大的规模也使它难以学习、难以被用好。
3) 在各处都用同样方式做同样的事。一致性和规范性是非常重要的。相关的事物应该具有相关的意义。
4.6 资源管理
释放资源与分配资源应该在同一个层次进行。控制资源分配和回收有一种基本方式,那就是令完成资源分配的同一个库、程序包或界面也负责完成它的释放工作。这种处理原则的另一种说法是:资源的分配状态在跨过界面时不应该改变。例如,我们的CSV库从一个已经打开的文件读数据,那么它在完成工作时还应该使文件保持在打开状态,由库的调用程序关闭文件。
4.7 终止、重试或失败
在低层检查错误,在高层处理它们。作为一条具有普遍意义的规则,错误应该在尽可能低的层次上检测和发现,但应该在某个高一些的层次上处理。一般情况下,应该由调用程序决定对错误的处理方式,而不该由被调用程序决定。库函数应该以某种得体的失败方式在这方面起作用。
只把异常用在异常的情况。有些语言提供了异常机制,以帮助捕捉不正常状态并设法做恢复,这种机制实际上是提供了在某些坏事情发生时的另一条控制流。异常机制不应该用于处理可预期的返回值。

浙公网安备 33010602011771号