化整为零是一种简单却不易行的软件开发策略。其关键在于,对于任何一个目标集来说,拆分的可能方案都趋向于无穷。因此我们为论证某一个拆分方案的正确性而付出的代价,往往要高于实施目标集本身。换言之,要讨论如何拆分是“最”好的,有时甚至不如不拆分。
所以事实上对于任何一个项目中的类、单元、子程序或子项目的抽取,我们在现在以及将来实施的都绝不是“最优解”,而是在所处阶段中相对“较可行”的一个方案而已。程序员在这一过程中往往是一个被动的实施者,而非这个“解”正确性如何的评估者。
总有一些规则是“较好的”或“较容易判断与实施的”,但如上所述,它们可能不是“最好的”与“最正确的”。了解这些规则,是渐进提高程序素质的方法之一,但并非某个具体项目的唯一判断标准。
①这里的空间与时间因素,是基于在架构分篇(第四篇)中对目标属性的分类方式来讨论的:所谓空间需求,是指它们可以通过组成部件的增减来解决;所谓时间需求,是指它们可以划分为多个时间阶段来实施。
展示了在稍早一些的应用开发语言中,从“代码的粒度”出发的抽象概念。
注1:语句与行的不同,通常也被称为逻辑行与物理行概念上的不同。此外,有些语言是强制要求以物理行来表达“语句”这一概念的,即一行语句必须书写于一行代码中。yipindushu.com
注2:单元与模块除了称谓的不同,很多时候其抽象概念也并不完全相同或者互相覆盖,例如一个单元可以是(或不是)一个模块。我们这里只取在某些语言中、将模块特指为“一系列函数”的这一概念。
其中,单元或模块用于组织一系列函数,而一个应用①则是由单元或模块构成。在这样的体系中,“化整为零”的问题会变得相对简单,即如何有规则或有逻辑地将一堆函数组织成单元。这里的"规则"与“逻辑”阐述了组织法则的两个方向。
其一,我们可以设定一个简单的分类依据,使得位于同一个单元中的函数表现出一定的相似性。例如开发一个图形库,我们可以将与图形设备相关的功能放在device库中,将绘制功能放在graph库中,将渲染功能放在render库中,将与图形库无关但又与计算机基础环境相关的功能放在base库中,如此等等。最后,我们将一些杂乱无章的功能放在misc库中。请注意,这一切的分类依据是“功能的归属与使用者”。类①早期的应用开发语言也直接将应用称为“程序”(program)。
似地,我们也可以依据数据的位置来建立分类依据。例如同样是这个图形库,我们可以将基础数据运算放在bits库中,并基于此建立关于图形运算的类型抽象库types。接下来我们定义在不同设备上适用的数据结构,比如在存储设备中的种种文件格式fileTypes、在内存中复制和运算的dibs(设备无关位图,Device-Independent Bitmap)以及在某种具体显示设备中适用的cudaTypes(CUDA,Compute Unified DeviceArchitecture)等。这样依据数据(所处的)位置以及需要进行的计算进行分类,也便于将数据及其副本放在不同的环境下开发。
这一类的方案或试图交付一个可以被使用甚至被共用的功能集,或通过抽取不同层次(例如面向不同设备或不同场景)的代码,使之可以“或多或少”应用于不同的环境。与这个组织原则密不可分的一个问题是:如何使一个“单元/模块”向外公布它所具有的功能集。这形成了著名的“开放细节”与“公开功能但隐藏细节”之争①,如今后者已成为应用接口设计思想的主流,前者则部分地影响并推进了开放源代码这一思想。
但总的来说,这个组织法则只解决了一个应用中能被静态规则化的部分。无论如何,它无法满足“让程序运行起来”之后可能带来的种种变化。
其二,我们可以使得一个单元或多个单元中的函数存有某种逻辑关系。著名的“自顶向下程序设计”的思想,就处于这一组织法则所代表的方向上。例如:□设有一个逻辑(X),功能是将m变换为n,
虽然向下一层的分解并不限定各步骤之间的关系,但我们注意到此前讨论过的一个事实,即所有逻辑都可以被理解为顺序逻辑中的一个步骤。也就是说,步骤2依赖于步骤1,步骤3依赖于步骤2。随后我们继续向下一层分解,
①参见《人月神话》中“关于信息隐藏,Parnas是正确的,我是错误的”小节,以及David Parnas关于信息隐蔽理论的著名论文:《论将系统分解为模块的准则》、《设计易于扩展和收缩的软件》和《复杂系统的模块化架构》。
版权声明
本站素材均来源与互联网和网友投稿,欢迎学习分享
【节应用开发的背景与成因4:http://www.yipindushu.com/xuexifangfa/16413.html
推荐文章
12-30
1 如何学习量化交易01-13
2 如何学习气功01-12
3 如何学习企业管理01-27
4 工作之余如何有效学习提升02-28
5 高二英语学习方法