用隐喻来更充分地理解软件开发
隐喻(metaphors)即比喻,在这里指用现实生活的具体事物来描述计算机世界中的虚拟事物。病毒(virus)、流(stream)、池(pool)、库(library)等都是这方面的经典例子。现实世界的构建是缓慢的,很多事物的出现都有漫长的过程,然而计算机世界则是在短短的几十年间快速构建起来的,很多新的概念、新的架构、新的范式不断涌现。这些东西很抽象,看不见也摸不着,我们该怎样更好地理解这些新事物呢?隐喻或许是一个不错的方法。一个好的隐喻可以让我们复用生活中的经验,例如,Linux中有一个概念叫管道(pile),指的是将一个程序的输出作为另一个程序的输入的指令。在使用这个指令时,我的大脑里会出现一个管道的形象,接收我前一个程序的输出,并将其原封不动地倾倒给下游的程序,而且不会弄洒一点东西。这样的一个简单的联想可以让我轻松地记住管道的功能和性质:传输数据和幂等性质。再比如并行计算模型中的生产者-消费者模型(producer-consumer),生产者负责产生数据或任务,消费者使用数据或完成任务,在使用了这个隐喻之后,代码的编写和函数、变量的命名将变得非常简单。
书中只提到了隐喻在软件工程中的作用,但我认为,我们在数学中基类的概念和经验也是可以在软件工程中复用的。例如我们在设计抽象类(abstract class)或接口(interface)的时候,可以借鉴群论中的思想;把{(1,1),(1,3),(1,5),(2,1),(2,3),(2,5),(4,1),(4,3),(4,5)}称作{1,2,4}和{1,3,5}的笛卡尔积明显比将其称为两两组合要清晰得多;向量(vector)、仿射(affine)、对偶(dual)等概念也在软件工程中起到了不可或缺的作用。
三思而后行:前期准备
书中提到,在软件工程中做好充足的前期准备是必要的。软件工程是一种工程,它需要一系列方法来克服人能力的局限,前期准备就是这些方法中极其重要的一环。
前期准备需要考虑的事情清单
-
开发模式
序列化开发:需求稳定、设计直截了当、团队非常熟悉该领域
迭代式开发:需求理解不透彻、设计很复杂、团队不熟悉该领域、需求更改不可预测
-
需求
稳定的更改需求的流程
使用能适应变更的开发方法
核对表
-
功能需求
-
输入(来源、格式、合法性)
-
输出(目的、格式、合法性)
-
软件或硬件的外部接口
-
外部通信接口(握手协议、纠错协议、通信协议等)
-
用户的需求
-
内部的数据格式和通信协议
-
-
质量需求
-
操作简洁
-
响应快
-
安全性、可靠性好
-
可维护性、可扩展性
-
-
-
架构
-
主要的类(major class)
对构成系统80%行为的20%的类进行详细描述
-
数据设计(data design)
数据应该只有一个子系统进行访问,其他模块应该通过该子系统以一种抽象的,受限制的方式进行访问。
-
业务规则(business rules)
如:某个界面30s之后失效等
-
用户界面设计(User interface design)
-
资源管理(Resource Management)
-
安全性(Security)
-
性能(Performance)
-
可伸缩性(Scalability)
-
国际化、本地化(Internationalization/Localization)
-
输入、输出(Input、Output)
-
错误处理(Error Processing)
-
买还是造的决策(Buy vs Build)
-
关于复用的决策(Reuse Decisions)
-
核对表
-
结构清晰
-
关键的模块和构造块已经描述
-
数据设计
-
业务规则
-
用户界面设计的策略,用户界面的变更不影响程序其余部分
-
处理IO的策略
-
估算了稀缺资源的使用情况,并给出管理策略
-
安全
-
其他
-
-