编程匠艺_部分9.pdf
上传人:qw****27 上传时间:2024-09-12 格式:PDF 页数:48 大小:40.2MB 金币:15 举报 版权申诉
预览加载中,请您耐心等待几秒...

编程匠艺_部分9.pdf

编程匠艺_部分9.pdf

预览

免费试读已结束,剩余 38 页请下载文档后查看

15 金币

下载此文档

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

第13章崇尚设计——如何创作出优秀的软件设计本章主题:骆驼是集体炮制的马。y代码的内部设计——亚历克·伊斯戈尼斯爵士(Siry设计的内容和目的AlecIssigonis)y良好的设计是什么样的?y设计的工具和方法有些代码只会让你叹息。我曾经有一次需要为一个嵌入式产品编写设备驱动程序。这个驱动程序与操作系统的接口非常复杂。它与我所使用的硬件的接口也很复杂。为了让我自己保持头脑清醒,我将代码分成了两部分。第一部分是一个内部库,用于访问硬件,执行一些数据缓冲操作,并提供一个简单的API来访问缓冲的数据。然后我又编写第二部分,这是一个独立的层,它根据内部库实现了复杂的操作系统驱动程序接口。图13-1显示了这个设备驱动程序的结构。编程匠艺——编写卓越的代码后来,那个硬件的制造商交给我一份同一个设备驱动程序的样本例程。这个例程的编写者显然根本没有经过认真的考虑。例程中的代码简直是一团糟,它以一种让人完全不能理解的方式,将复杂的操作系统接口与硬件的逻辑紧密地掺合了在一起。图13-2显示了它的大致结构。操作系统接口硬件接口图13-1清晰的软件设计图13-2如果不进行设计,软件就会是这样现在,我不打算再自我吹嘘了(也不需要这样做了)。这两张图要表达的意思很明显。第一个设计更好一些。它理解起来比较容易,因为它非常简单明了,更容易实现,并因此也更容易维护。C.A.R.Hoare曾经写到:“构建软件设计的方式有两种:一种方式是使软件尽量简单,以至于明显没有缺陷;另一种方式是使软件尽量复杂,以至于没有明显的缺陷。第一种方式要难得多。”(见参考书目Hoare81)成熟程序员的判断标准之一就是他或她的代码的设计质量。在本章中,我们将了解构成良好设计的因素,并研究如何才能创造高质量的软件设计。13.1边设计边编程人们一般都会认为,“设计”是一个需要在开始编写代码之前完成的阶段。这个阶段的成果是某种形式的设计规范,普通的代码猴子就可以实现这种规范。事实情况却与此大相径庭。编程(编写代码的过程)本身就是一种设计活动。即便是最详细的规范也会有不完善之处,否则它就是代码了——你不能在设计文档中描述每个非常小的细节。编程的过程将检验初始的设计决策,并完成剩余的设计工作。它会揭示不完善的地方、不一致的情况和错误,并让你可以找到解决这些问题的途径。“有些程序员不认为他们在编程的同时也是在设计,但实际上,每当你编写代码的时候,你总是会有意无意地做着设计。”(见参考书目PageJones96)关键概念编程是一种设计活动。它是一项富含创造性和艺术性的工作,而不是机械呆板的代码生成过程。优秀的开发过程承认这一点,并且不会怯于在合适时编写代码。从事极端编程242第13章崇尚设计„的程序员们主张设计“就是”代码。(见参考书目Beck99)不存在单独的设计活动,也不存在专门的设计团队。通过优化和扩展代码来不断优化和扩展设计的,正是程序员。这体现在他们的测试驱动型的设计方法中:在编写任何代码之前,代码测试就已经作为一种设计验证工具被写好了。这是一种明智的做法。这是否意味着,你在开始编写代码之前不需要先进行一些思考了呢?当然不是!文本编辑器可不是你对要编写的内容做计划的地方。这就像你想开车从柏林到罗马,却没有预先确定走什么路线一样。最终,在你还没有搞清楚哪边是北之前,你就已经到莫斯科了。从定义上讲,设计是你应该首先去做的事情。关键概念在编写代码之前先进行思考,创建一种条理分明的设计。否则,你最终会得到一堆混乱的代码。13.2我们要设计什么程序员设计代码结构,这是显而易见的。但是,这在开发过程的不同阶段有着不同的含义。在每个阶段,设计都是一个将任务分解为子任务,并确定完成每个子任务的方法的过程。软件设计的层次如下。系统体系结构这里我们将系统看作一个整体,确定主要的子系统,并设计这些子系统的相互连接方式。体系结构设计对系统整体的性能和特性的影响最大,而对具体的代码行影响最小。它是最重要的设计步骤,我们将在14章对它进行详细的讨论。在本章中,我们主要关注的是代码的内部设计,即下面这几个设计层次。模块/组件体系结构的子系统一般都很大,无法直接在代码中实现,所以下一步就是要将每个子系统分解为更好理解的模块。模块层面的设计很容易会显得比较模糊。从某种程度上来讲,“模块”根本就不存在。根据设计方法的不同,模块可能具有不同的含义;它可能是一段实现了一定逻辑的代码,也可能是一种物理单元,如Java包、C++/C#命名空间或者可重用的库等。它还可能是一个类的层次结构,甚至可能是一个独立的可执行程序。设计阶段常常会产生