1.树状遍历式寻找问题
每个问题都不是单一存在的,它都有相关问题,犹如一棵树一样,主问题就是主树杆,主问题伴随的其他问题,就是支树杆,以次类推。首先不要怕麻烦,每当一个问题提出,必须提出尽量多的相关新问题。提出问题的方法:顺藤摸瓜。
比如:写一个通用编辑器程序,此程序为自己或别人开发其他专业编辑器打下可靠稳定的基础。
1)问题:什么是通用编辑器。编辑器面向的对象应该是不确定的。
2)如果数据类型不确定,我们如何确定程序编写的对象。可以举出一些可能的假设。假设我们将此通用编辑器用作程序源代码编辑,那么就应该有中断、单步执行等设置,这导致数据不能封装在编辑器内部,应该由后期开发指定数据结构。
3)如果是程序编辑器,关键字的特显必不可少,所以显示的属性应该给出接口。
4)诸如关键字此类的是否还有其他需要特显的,那么,应该注意到特显类不仅仅是一种,程序设计时,最好抽象出特显的方法与数据结构(不管以后有多少不可预知的特显内容)。可以深入考虑特显接口应该如何给出,才能支持任意特显方式,它还需要哪些信息。
5)抽象特显类时,应该举出尽量多的可能性,综合考虑。
6)问题:哪些内容需要特显。编辑器很难知道,数据类应该自己了解。所以,特显内容的定义必须有一个机制让后期开发时使用。
7)问题:源代码编辑器有自动缩排、词法、语法分析,这些操作如何在编辑器中体现。考虑语法类接口。是否有收缩与展开操作,接口又如何。
8)又假设:后期要扩展成字处理程序。数据有文本、图象、特殊公式编辑、段落概念、表格等。
9)送进编辑器的数据可能是一组含有控制字的数据,问题:如何获得让编辑器知道不同数据的不同显示操作。编辑器肯定无法全知,所以,干脆交给后期开发需求处理。
10)未知数据应该有:显示方法、光标定位处理等
11)光标定位需要当前坐标,所以,必须有接口让编辑器知道数据宽高。
12)综合结论:应该有一个接口机制。凡特殊操作的内容,交给后期处理,但通用编辑器应该做好数据管理和传送的工作,而这些工作,不管哪种编辑器都需要。
首先任其深入提问,虽然问题可能多得十分复杂或凌乱,但它对即将做的系统设计绝对有帮助,最好把每个问题都有一个清楚的了解,千万不要急于设计系统。通过这些提问和假设,就可清楚地分析我们所作的软件应该实现哪些内容,哪些内容实现有难度,实现这些内容的大体方法,通用编辑器能作什么。通过上列系列提问和解答,我们可以认为,通用编辑器仅仅是一个以行为基本编辑单位的编辑器摸板。编辑器不仅自己有编辑操作,同时允许外部提供特殊数据对象的编辑操作,最终实现文本编辑、图形编辑、表格编辑、公式编辑一体化。数据外部实现,将允许后期确定内容属性。
上述方法基本上确保了软件有好的可靠性、扩展能力、性能、重用性和系统化。想高效率生产系列软件,确实应该考虑的更多。
2.直接切入目标问题
直接提出软件要完成的系列任务,通过考虑任务的实现,罗列问题,在问题的解答过程中反思任务的需求。这样的方法可以快速设计出软件开发方案。
仍然以通用编辑器为例:
1)编辑对象有:文本、图形、图象、表格等。
2)操作有:焦点移动、增加、删除、存取盘、选择块、粘贴拷贝、缩进、展开收缩、书签、中断设置、单步执行标记等。操作有分文本、图形图象、表格等的操作编辑。
3)显示:文本的不同字体风格显示、图形的显示、图象的显示、表格等的显示。
4)状态设置:改写插入、段落格式设置、标题控制、编辑器专业化的设置等
5)考虑各项功能的实现方案,发现问题。
6)如果有没有考虑到的,增加进去。
7)经过许多的方案设计,综合考虑和优化方案,提出最后的设计方案
8)综合结论:程序考虑了诸多功能,通用编辑器是众多功能的集合体,内部详细规划了各种类型数据的操作、显示和排版分析。
经过一系列的方案定义,将问题逐步减少,最后获得一个规模较大的系统设计早期方案。我们可以较早地进入系统设计,并且提前进入程序代码级开发工作,同时逐步实现各项内容。
此方法分析需求,有助于我们尽早实现想法,同时较好地控制住程序开发方向和基本功能完成的进度。但遗憾的是提高开发速度的代价是降低程序的可靠性、扩展性和重用性。过去,我们往往觉得所作的程序基本上不能再次使用,原因就在于没有抽象问题,寻找问题的根本解决方案。就问题实现问题的方法,忽略了深入分析问题的过程。对于针对开发某专业的应用软件采用此方法分析需求比较合适,但对系统性强的软件,最好采用树状遍历式寻找问题的方法。
二、分析问题和需求
在没有分析清楚问题和需求的来由就匆匆下定论是非常危险的。忽略问题和需求就可能埋下了潜在的程序或系统设计问题。我们也常常犯这样的错误:由于没有分析清楚问题和需求,结果到头来更改系统设计。能够提出的问题和需求,就一定要扎扎实实分析它,否则后果难料。
分析问题和需求的能力大小与思路和经验有关。好的思路来源于严谨、逻辑和跳跃的思考习惯。严谨要求不要放过任何一个小问题,逻辑要求思考的过程应该是一种符合规则的推导过程,跳跃思维要求思考的路子不是一走到底而是多条路子并行着走。经验来自于编写调试大量程序和善于总结,要求程序员不断地开发新程序和创造新思路,并且敢于尝试和接受失败,当然还有一条重要的方面:跟踪最新技术。
如何正确分析问题,有以下几个要素值得注意:
1.所有问题和需求都有发生的根源。
问题和需求的表面现象总是与开发者思路切入点相关,如果切入点是狭隘的,那么围绕着问题和需求的分析往往局限于自身的思路范围,问题和需求产生的原因就很难发觉。所以当不能理解分析问题和需求时,不妨先找一找为什么存在这样的问题和需求,它的存在是否合理,然后再分析理解它就不难了。思路一定要跳出惯例。
2.交替反复分析多个问题和需求,寻找问题间的共性和特性
看似问题和需求间没有联系,而且分析不清各自意义,那么建议交替反复分析考虑这些问题。勤能补拙,不要担心它将花费开发者多少时间,只有开发者仔细分析问题需求,以后的工作越来越简单明了。
3.复杂化问题,
问题复杂化,是一个抽象问题或需求的逆过程,提出问题需求的许多可能的假设,丰富了问题需求的形式。能够复杂化问题,本身就体现了分析问题和需求的能力。比如:做一个加法程序,两个数相加,返回结果。简单的问题,但,我们一般都按两整数加法,有时考虑了浮点加法。为什么不是两个复数相加,或者是两个字符串相加等。这是一个使用操作符重载或类模板解决的简单例子,在这里我的意图是许多问题应该从更多的方面去验证问题是否同样存在。
4.问一问自己:问题是否能够抽象化,继而简化问题。
众多的问题和需求变成程序代码的过程,就是公式化问题和需求。如果象上例加法一样,不管三七二十一,什么样的数据就写一段什么的代码,不同类型数据间的加法同样又要写一段代码,这样下去就写不完了。抽象问题,简化问题,类模板就是一个抽象问题很好的例子。在分析问题和需求的过程中,同样采用面向对象的思维方式去求解,会获得一个非常满意的需求报告。
5.问题和需求分类分主次考虑
1)软件产品的性能指标:可靠、功能全、速度、易扩展。
易扩展:一种是产品升级换代快、系列化产品丰富。另一种是用户的二次开发扩展产品的再生功能。
速度:表示软件执行速度不仅要快,同时操作中的速度要均衡。
功能全:大而全不一定是不好,有能力和实力,最好做到功能尽量全。功能全直接体现软件开发商的实力。
可靠:这是最为重要的一点,软件首要考虑的应该是可靠。测试时,极限、异常操作都应该考虑进去。
2)问题和需求根据软件产品的性能指标和实现难度分类:核心需求,基本功能需求,高级功能需求、组合功能需求。
核心需求:直接影响速度、可靠、易扩展指标的好坏。比如:CAD刷屏要求速度、CAD命令行机制提高了易扩展性能、CAD内部数据结构的管理机制直接影响软件的可靠性。核心需求将定义出软件的本质内容,它主要以程序设计原理为基础,结合软件任务需求定义数据结构和管理机制。核心需求是首先要确定下来的,是最主要的工作。
基本功能需求:完成任务的最基本的操作功能集合,这些基本功能是软件产品的底层处理功能,是众多问题和需求中抽象出的共性部分,它是其他功能的基础。基本功能需求也是非常重要的,它的好坏直接影响到后面高级功能的质量和能力。
高级功能:是众多问题和需求中的特性部分,这些功能对某个应用是非常有用,但在另一个应用中可能没有用。比如:CAD中的图形计算:求面积或体积,在建筑施工图设计中没有使用,但在计算路基方面则非常有用。高级功能的需求应该放在较次要的位置,
组合功能:通过基本功能和高级功能组合操作后的功能。例如:CAD中的LISP语言,CAD的批命令输入,CAD的图块功能等。这些借助于基本功能和高级功能的组合功能是一种后期行为,没有这些功能,软件一样可以使用,所以,这些需求开发并不需要急于实现,但一定要在核心中考虑组合机制。
总之,需求分析是导致软件产品好坏的关键工作,导致软件开发难易程度大小的绝对因数。宁可将需求分析的时间给充足一些,也不愿以后在编程阶段补充修改需求(虽然修改需求是不可避免的事实)。