在一些人眼里,今天的软件开发似乎是一件简单的事情,已有不少很好的开发工具和软件库,软件开发人员训练有素,都强烈渴望去编写很酷的软件,可以在几天的时间里编写出一个相当复杂的软件。但为什么有些软件能够得到用户的喜欢,而另一些则不能?为什么有些软件能够在市场上成功,而有些则受到冷落?由此可见,开发软件并不一定困难,而难在如何开发有用的软件。
一个有用的软件应该能帮助用户解决实际问题,应该能体现对用户的价值。因此,在设计一个软件时,首先要想的是用户是谁(Who)、要解决哪些问题(What)、为什么要解决这些问题(Why)。这就是微软3W软件设计的出发点。如果没有弄清楚这些问题,即使能很快地开发出自己的软件,也不可能获得成功。
例如,微软公司曾在1996年前后将其掌上电脑操作系统Win CE 1.0投放市场。当时,一些人预测凭借微软公司强大的市场运作能力一定能获得成功,但也有些人批评说它的用户界面并不适合掌上电脑用户,用在台式机上比较合适。事实证明Win CE在市场上并不成功,用户觉得它不好用。后来,该产品渐渐从市场上销声匿迹了。这对微软公司是一次深刻的教训。由此可见,3W这一设计的出发点是非常重要的,但也非常困难。像微软这样的软件公司,有时也不能很好地回答这3个问题。
那么,到底应该怎样做呢?这就需要从软件设计的基础说起。通过需求分析阶段的工作,大家已经清楚了软件的各种需求,较好地解决了要让开发的软件“做什么”的问题,并在软件规格需求说明书中详细和充分地阐明了这些需求。所以,下一步将着手实现软件的需求,即解决“怎么做”的软件相关问题。
从设计步骤来看,设计加工点是将需求分析阶段得到的软件规格需求说明书中所包括的信息描述、功能描述、行为描述等信息,通过设计阶段来产生系统的总体结构设计、系统的过程设计以及系统的数据设计;然后进入编码阶段,将设计转换为现实,即计算机能够执行的代码;再将所有的程序编码通过测试人员的测试,最后形成符合要求的软件产品。
软件系统是连接需求分析、硬件系统以及使系统实现的桥梁,对软件的设计应首先了解软件设计原则,要求软件具备可靠性、健壮性、可修改性、可理解性、可扩展性等。其中,软件的可理解性是可靠性和可修改性的前提。它并不仅仅是文档清晰可读的问题,更要求软件本身具有简单明了的结构。这在很大程度上取决于设计者的洞察力和创造性,以及对设计对象掌握的透彻程度,当然它还依赖于设计工具和方法的适当运用。
软件设计是软件开发阶段的重要步骤,其主要任务是在需求分析的基础上形成软件系统的设计方案。如图4.1所示,软件设计的元素包括系统总体设计、软件交互设计和模块设计与实现。
图4.1 软件设计的元素
系统总体设计是整个软件设计的关键环节,是在需求分析的基础上定义系统的设计目标,将整个系统划分成若干子系统或模块,建立整个系统的体系结构,并选择合适的系统设计策略。
系统总体设计首先需要明确系统应关注的质量属性,定义系统要满足的设计目标;然后按照高内聚、低耦合的原则把整个系统进行模块化分解,确定子系统或模块;接着选择系统部署方案,把分解的模块映射到相应的硬件上;接下来进一步定义数据存储、访问控制、全局控制等一系列的设计策略;最后通过评审活动来进一步改进设计质量,确保设计方案的正确性、完备性、一致性和可实现性。
模块设计与实现则应用良好的设计原则,进一步细化和实现所分解的模块单元,可能涉及数据结构设计、算法设计和数据库设计等。一个软件系统是由各个子系统构成的,子系统是由各个模块组成的。模块设计的原则是模块独立,即每个模块完成一个相对的特定子功能并且与其他模块之间的联系尽量简单。衡量模块独立程度的标准有两个:耦合性、内聚性。耦合性是指模块之间联系的紧密程度,模块间耦合的高低取决于模块间接口的复杂性、调用的方式及传递的信息。内聚性是指模块内部各元素之间联系的紧密程度,内聚度越低,模块独立性越差。
软件交互设计通过分析和理解用户的任务需求,对软件的人机交互、操作逻辑和用户界面进行设计。一般说来,优秀的软件交互设计具有简洁、清晰、容错、熟悉、响应、美观、一致、高效等特点。要设计一款好的软件界面,就必须遵守两个基本原则:快捷便利的实用原则和极简主义的审美原则。
系统设计的目标定义了系统应该重点考虑的质量要求,其中,性能、可靠性和最终用户准则(效用和易用性,即系统对用户工作的支持程度以及用户使用系统的难易程度)通常是从非功能需求或应用领域中推断出来的,维护和成本原则需要由用户和开发人员识别。其中,成本包括开发、部署、升级、维护和管理成本,分别是开发初始系统、安装系统和培训用户、从原有系统导出数据、修复错误和增强系统、对系统进行管理的成本。注意这些目标可能是互相牵制的,比如空间与速度、交付时间与功能、质量和人员之间都可能产生矛盾和冲突,必须进行权衡。
好的系统设计一般具有以下特征:用户友好、易于理解、可靠、可扩展、可移植、可伸缩、可重用。简而言之,在实现、使用、理解、维护上都尽可能简单。一般软件在经过多次需求变更后,可能会出现软件老化的情况,主要特征是修改难、很脆弱、移植难、重用难、对设计和环境的黏性强,各方面效率都非常低。良构的系统会让软件老化尽量晚出现。