软件开发检查表课案.docx
《软件开发检查表课案.docx》由会员分享,可在线阅读,更多相关《软件开发检查表课案.docx(39页珍藏版)》请在冰点文库上搜索。
软件开发检查表课案
代码大全——检查表
1.欢迎进入软件创建世界
1.1.l.3小结
●创建活动是总体设计和系统测试之间承上启下的工作。
●创建活动主要包括:
详细设计、编码、调试和单元测试。
●关于创建活动的其它称谓有:
实现、编程等。
●创建活动质量对软件质量有潜在影响。
2.利用隐喻对编程进行更深刻的理解
2.1.2.4小结
●隐喻仅仅是启发,而不是公式,因此,它们更倾向于比较随便,无拘无束。
●隐喻通过把软件开发与你所熟知的事情联系在一起,从而使你对其有更深刻的理解。
●一些隐喻要好于其它隐喻。
●把软件创建与建造建筑物类比,表明开发软件前要精心准备,并表明了大规模项目与小规模项目之间的差别。
●认为软件开发实践是智能工具箱中的工具进一步表明,每个程序员都有许多自己的工具,没有任何一种工具是万能的。
为每件工作选择合适的工具,是成为一个优秀程序员的首要素质之一。
3.软件创建的先决条件
3.1.需求
3.1.1.需求内容
●系统的所有输入都定义了吗?
包括它们的来源、精度、取值范围和频率?
●系统所有的输出都定义了吗?
包括它们的目标、精度、取值范围、频率和格式?
●所有的报告格式都定义了吗?
●所有的硬件与软件接口都定义了吗?
●所有的通信交界面都定义了吗?
包括握手、错误检查以及通信约定?
●是否从用户的观点出发,定义了所有必要操作的反应时间?
●是否定义了时间问题,如处理时间、数据传输率以及系统吞吐能力?
●是否对用户所要求完成的任务部作出了规定?
●每项任务所需用到和产生的数据都规定了吗?
●规定保密级别了吗?
●规定可靠性了吗?
包括软件出错的后果、在出错时要保护的至关重要的信息、以及错误测试和恢复策略。
●规定所需最大内存了吗?
●所需最大存储容量规定了吗?
●对系统的维护性是否作出了规定?
包括系统对运行环境、精度、性能以其与其它软件的接口等方面变化的适应能力规定了吗?
●是否规定了相互冲突的设计之间的折衷原则,例如,在坚固性与准确性之间如何进行折衷?
●是否制定了系统成败的标准?
3.1.2.关于需求的完善性
●在开发开始前暂时得不到的信息是什么?
是否规定了不够完善的区域?
●需求定义是否已经完善到了可以成为软件标准的地步?
●需求中是否有哪一部分令你感到不安?
有没有根本不可能实现,而仅仅为了取悦老板和用户才加进来的内容?
3.1.3.关于需求的质量
●需求是否是用户的语言制定的?
用户也这样认为吗?
●需求中是否每一条之间都尽量避免冲突?
●需求中是否注意了避免规定设计工作?
●需求在详细程度方面是否保持了一致性;有没有应该更详细些的要求?
有没有应该更简略些的?
●需求是否明确得可以分为一些独立的可执行部分,而每一部分又都很明了?
●是否每一条都与问题和答案相关?
是否每一条都可以追溯到产生它的环境中?
●是否每一条需求都可以作为测试依据?
是否可以针对每一条进行独立测试以确定是否满足需求?
●是否对可能的改动作出了规定?
包括每一改动的可能性?
3.2.结构设计
●一个好的结构设计应该阐明所有问题。
这个表并不是用于指导结构设计的,而只是想提供一种方法,通过它,你可以估计处于软件食物链顶层的程序员可以从食物中获得多少营养。
它可以作为建立自己的检查表的起点。
同要求定义检查表的使用一样,如果你正在从事一个非正式的项目,那么其中有些条款是不必考虑的。
但如果你正在开发一个较大的系统,那绝大部分内容都是非常有用的。
●软件的总体组织形式是否清晰明了?
包括对于结构设计的总体评论与描述。
●模块定义是否清楚?
包括它们的功能及其与其它模块的接口。
●要求定义中所提出的所有功能,是否有恰当数量的模块覆盖?
●结构设计是否考虑了可能的更改?
●是否包括了必要的购买?
●是否阐明了如何改进重新启用的代码来满足现在的结构设计要求?
●是否描述并验证了所有主要的数据结构?
●主要数据结构是否隐含在存取子程序中?
●规定数据库组织形式和其它内容了吗?
●是否说明并验证所有关键算法?
●是否说明验证所有主要目标?
●说明处理用户输入的策略了吗?
●说明并验证处理输入/输出的策略了吗?
●是否定义了用户界面的关键方面?
●用户界面是否进行了模块化,以使对它所作的改动不会影响程序其它部分
●是否描述并验证了内存使用估算和内存管理?
●是否对每一模块给出了存储空间和速度限制?
●是否说明了字符串处理策略?
是否提供了对字符串占用空间的估计?
●所提供的错误处理策略是不是一致的?
●是否对错误信息进行了成套化管理以提供一个整洁的用户界面?
●是否指定了坚固性级别?
●有没有哪一部分结构设计被过分定义或缺少定义了?
它是否明确说明了;
●是否明确提出了系统目标?
●整个结构在概念上是否是一致的?
●机器和使用实现的语言是否顶层设计依赖?
●给出做出每个重要决定的动机了吗?
●你作为系统实现者的程序员,对结构设计满意吗?
3.3.3.9小结
●如果想开发一个高质量的软件,必须自始至终重视质量问题。
在开始阶段强调质量往往比在最后强调质量更为有效。
●程序员的份内工作之一便是向老板和同事宣传软件的开发过程,包括在编程开始前从事先决条件准备工作的重要性。
●如果问题定义工作做得不好,那么在创建阶段,所解决的问题可能并不是用户真正要解决的问题。
●如果需求分析工作做得不好,很可能因此而漏掉要解决问题中的重要细节。
在创建工作后更改要求,要比在需求分析阶段进行更改的成本高20到100倍。
所以,在开始编程前一定要确认要求定义工作一切正常。
●在编程前规定好约定,在创建工作结束后再改变代码来满足约定几乎是不可能的。
●在创建活动开始之前如果无法完成准备工作,可以尝试在不太稳固的基础上进行创建活动。
4.建立子程序的步骤
4.1.创建子程序
●是否检查过先决条件已经满足了?
●定义子程序将要解决的问题了吗?
●结构设计是否足够清楚,使得你可以给子程序起个好名字?
●考虑过如何测试子程序了吗?
●是否从模块化水平或者满足时间和内存要求角度考虑过效率问题?
●是否查阅过参考书;以寻找有帮助的算法?
●是否用详尽的PDL设计子程序?
●在必要时,是否在逻辑设计步骤前考虑了数据?
●是否检查过PDL,它很容易理解吗?
●是否注意到了足以使你返回到结构设计阶段的警告(使用了全局数据,更适合其它子程序的操作,等等)。
●是否使用了PDL到代码流程,是否把PDL作为编码基础并把原有的PDL转为注释?
●是否精确地把PDL翻译成了代码?
●在作出假设时,验证它们了吗?
●是从几个设计方案中选择了最好的,还是随意选择了一个方案?
●是否彻底理解你的代码?
它容易理解吗?
4.2.4.6小结
●要想写好PDL,首先要用易懂的自然语言,避免拘泥于某种程序语言,其次要在意向层次上写PDL,描述设计作什么而不是如何作。
●PDL到代码流程方法是详细设计的有力工具,而且使得编码非常容易。
可以把PDL直接翻译成注释,但要注意保证注释是精确而有用的。
●应该在工作的每一步中都检查子程序,并鼓励同事们检查。
这样,可以在投入的资金和工作努力最少时便发现错误,从而极大降低改错成本。
5.高质量子程序特点
5.1.总体问题
●创建子程序的理由充分吗?
●如果把一个子程序中的某些部分独立成另一个子程序会更好的话,你这样做了吗?
●是否用了明显而清楚的动宾词组对过程进行命名?
是否是用返回值的描述来命名函数?
●子程序的名称是否描述了它做的所有工作?
●子程序的内聚性是不是很强的功能内聚性?
它只做一件工作并做得很好吗?
●子程序的耦合是不是松散的?
两个子程序之间的联系是不是小规模、密切、可见和灵活的?
●子程序的长度是不是它的功能和逻辑自然地决定的:
而不是由人为标准决定的?
5.2.防错性编程
●断言是否用于验证假设?
●子程序对于非法输入数据进行防护了吗?
●子程序是否能很好地进行程序终止?
●子程序是否能很好地处理修改情况?
●是否不用很麻烦地启用或去掉调试帮助?
●是否信息隐蔽、松散耦合,以及使用“防火墙”数据检查,以使得它不影响子程序之
●外的代码?
●子程序是否检查返回值?
●产品代码中的防错性代码是否帮助用户,而不是程序员?
5.3.参数传递问题
●形式参数与实际参数匹配吗?
●子程序中参数的排列合理吗?
与相似子程序中的参数排列顺序匹配吗?
●接口假设说明了吗?
●子程序中参数个数是不是7个或者更少,
●是否只传递了结构化变量中另一个子程序用得到的部分?
●是否用到了每一个输入参数?
●是否用到了每一个输出参数?
●如果子程序是一函数,是否在所有情况下它都会返回一个值?
5.4.5.10小结
●建立子程序的最重要原因是加强可管理性(即降低复杂性),其它原因还有节省空间、
●改进正确性、可靠性、可修改性等等。
●强调强内聚性和松散耦合的首要原因是它们提供了较高层次的抽象性,你可以认为一个具备这种特性的子程序运行是独立的,这可以使你集中精力完成其它任务。
●有些情况下,放入子程序而带来巨大收益的操作可能是非常简单的。
●子程序的名称表明了它的质量,如果名称不好但却是精确的,那么说明它的设计也是非常令人遗憾的。
如果一个子程序的名称既不好又不精确,那它根本就无法告诉你程序作了些什么。
无论哪种情况,都说明程序需要改进。
●防错性编程可以使错误更容易被发现和修复,对最终软件的危害性显著减小。
6.模块化设计
6.1.模块的质量
●模块是否有一个中心目的?
●模块是否是围绕着一组公用数据进行组织的?
●模块是否提供了一套相互联系的功能?
●模块功能是否足够完备,从而使得其它模块不必干预其内部数据?
●一个模块相对其它模块是否是独立的?
它们之间是松散耦合的吗?
●一个模块的实现细节,对其它模块来说,是隐含的吗?
●模块的接口是否抽象到了不必关心其功能实现方式的地步?
它是作为一个黑盒子来设计的吗?
●是否考虑过把模块再划分为单元模块?
是否对其进行了充分的再划分工作?
●如果用不完全支持模块的语言编程,你是否制定了编程约定以使这种语言支持模块?
6.2.6.5小结
●不管调用哪一个,子程序与模块的不同是很重要的,要认真考虑子程序与模块的设计。
●从模块数据是被几个子程序使用的这一角度来说,它与全局数据是相同的,但从可以使用它的子程序是有限的,而且清楚地知道是哪些子程序可以使用它这一角度来说,模块数据与全局数据又是不同的。
因此,可以使用模块数据而没有全局数据的危险。
7.高级结构设计
7.1.高层次设计
●本表给出了在评估设计质量时,通常要考虑一些问题。
本表是3.4节中结构设计检查表的补充,这个表所考虑的主要是设计质量。
3.4节中的检查表则侧重于结构设计和设计内容。
这个表中的某些内容是相互重合的。
●是否使用了往返设计方法,应从几个方案中选择最好的,而不是首次尝试就确定方案。
●每个子程序的设计是否都和与其相关的子程序设计一致?
●设计中是否对在结构设计层次上发现但并未解决的问题作了充分说明?
●是否对把程序分解成目标或模块的方法感到满意?
●是否对把模块分解成子程序的方法感到满意?
●是否明确定义了子程序的边界?
●是否是按照相互作用最小的原则定义子程序的?
●设计是否充分利用了自顶向下和自底向上法?
●设计是否对问题域要素、用户接口要素、任务管理要素和数据管理要素进行了区分?
●设计是智力上可管理的吗?
●设计是低复杂性吗?
●程序是很容易维护的吗?
●设计是否将子程序之间的联系保持在最低限度?
●设计是否为将来程序可能扩展作了准备?
●子程序是否是设计成可以在其它系统中再使用的?
●低层次子程序是高扇入的吗?
●是否绝大多数子程序都是低或中等程度扇出的?
●设计易于移植到其它环境吗?
●设计是简练的吗?
是不是所有部分都是必要的?
●设计是成层的吗?
●设计中是否尽量采用了标准化技术以避免奇特的、难以理解的要素?
7.2.7.6小结
●设计是一个启发的过程。
固执地坚持某一种方法只会抑制创造力,从而产生低质量的程。
坚持设计方法上有一些不屈不挠的精神是有益的,因为这可以迫使你对这种方法进行充分理解。
但是,一定要确信你是在不屈不挠而不是顽固不化。
●好的设计是通过迭代逼近得到的:
你尝试过的设计方案越多,你最终所确定的设计方案也越好。
●结构化设计比较适合于小规模的子程序组合,同时,它对于功能变化可能性比数据大的问题也是较适用的。
●面向对象设计更适于子程序与数据的组合,通常在比结构化设计抽象程度更高些的层次上适用。
它尤其适合于数据变动可能性大于功能变动可能性的问题。
●设计方法仅是一种工具,你对工具运用得好坏决定了你所设计的程序的质量。
利用不好的设计方法,也可能设计出高质量的程序。
而即使是好的方法,如果运用不当的话,也只能设计出拙劣的程序。
但不管怎样,选择正确的工具更容易设计出高质量的软件。
●许多关于设计的丰富而有用的信息都是在本书之外的。
在这里所论述的,不过是冰山的一角而已。
8.数据生成
8.1.生成类型
●程序中是否对每种可能变动的数据都使用了不同的类型?
●类型名称是面向客观世界中的实体类型而不是面向程序语言中的类型吗?
●类型名称是否有足够的表现力来帮助说明数据?
●避免重新定义已定义的类型了吗?
8.2.说明数据
●是否使用了模框为简化数据说明工作?
并用其来统一说明形式?
●如果所用的语言支持隐式说明,是否采取了补救措施?
8.3.初始化
●是否每个子程序都对输入参数进行了检查以保证其有效性?
●是否在使用变量的位置附近对其进行初始化的?
●是否恰当地对计数器和指针进行了初始化?
是否在必要时对其进行了重新初始化?
●在反复执行的代码段中,是否对变量进行了恰当地重新初始化?
●用编译程序编译代码时是否是无警告的
8.4.8.6小结
●在你的工具箱中需要一张全部数据结构的清单,以便用最合适的方法处理每一种问题。
●建立自己的数据类型,以增加程序的可变动性,并使其成为自说明的。
●数据初始化很容易产生错误,因此应采用本章推荐的技术来避免由意外初始值所产生的错误。
9.数据名称
9.1.通用命名约定
●变量名称是否完全准确地描述了变量代表的是什么?
●变量名是否指向是客观世界中的问题,而不是关于这问题的用程序语言表达解决方案?
●变量名称是否是够长,使得你不必破译它?
●变量名中如果含有计算限定词的话,是否将其放在最后?
●是否在名称中用Count或Index来代替了Num?
●对特殊类型数据的命名
●循环变量的名称是有意义的吗?
(如果循环体较长是嵌套循环的话,应用有含义的名称来代替i、j、k之类的名称)
●是否用更富于含义的名称来代替了被叫作"tempotarg"的临时变量?
●当逻辑变量的值是"True"时,它的名称是否充分表达了其含义?
●是否用前缀或后缀来表明了某些枚举类型是一类的?
如用Color来作ColorRed,ColorGreen,ColorBlue等枚举类型的前缀。
●命名常量的名称是否是指向它们代表的实体而不是它们所代表的数值的?
9.2.命名约定
●命名约定是否区分了局部、模块和全局数据?
●命名约定是否对类型名称、命名常量、枚举类型和变量进行了区分?
●在不支持强化仅供子程序输入参数的语言中,命名约定是否对这类参数进行了标识?
●命名约定是不是与程序语言的标准约定尽可能地相容?
●对于语言中没有强制的子程序中仅做输入的参数,是否约定将它标识了?
●是否对名称进行了格式化以增强程序的可读性?
9.3.短名称
●代码是否使用了长名称?
(除非有必要使用短名称)
●是否避免了只省略一个字母的缩写?
●所有单词保持缩写的连续性了吗?
●所有的名称都是容易发音的吗?
●是否避免了会引起错误发音的名称?
●是否在注释表中对短变量名进行了注释?
●避免如下这些常见的命名错误了吗
⏹易引起误会的名称
⏹含义相似的名称
⏹仅有一或两个字母不同的名称
⏹发音相似的名称
⏹使用数字的名称
⏹对单词作改写以使其比较短的名称
⏹英语中常拼写错的名称
⏹标准库子程序或已定义的变量名又定义了
⏹完全是随意的名称
⏹含有难以辨识字母的名称
⏹使用数据时通常要考虑的一些问题
9.4.9.8小结
●恰当的变量名是可读性好的必要条件之一。
特殊的变量如循环变量和状态变量要予以特殊考虑。
●命名约定可以区分局部、模块和全局变量。
同时它还可以区分类型名称,比如可以对命名常量、枚举类型和变量加以区分。
●不管你从事的是哪种项目,都应该采用命名约定。
所采用的命名约定取决于程序的规
●模和从事这一程序的程序员的人数。
●匈牙利约定是一种非常有效的命名约定,比较适于大规模项目和程序。
●在现代编程语言中几乎不需要采用缩写技术。
10.变量
10.1.一般数据
●是否已经使变量的作用域尽可能地小?
●是否把对变量的使用集中到了一起?
●控制结构与数据结构是相对应的吗?
●每个变量是否有且仅有一个功能?
●每个变量的含义都是明确的吗?
是否保证了每个变量都没有隐含的意义?
●每一个说明过的变量都被用到了吗?
10.2.全局变量
●是否是在迫不得已的情况下,才使某些变量成为全局的?
●命名约定是否对局部、模块和全局变量进行了区分?
●是否说明了所有全局变量?
●程序中是否不含有伪全局变量——传往各个子程序的庞大而臃肿的数据结构?
●是否用存取子程序来代替了全局数据?
●是把存取子程序和数据组织成模块而不是随意归成一堆的吗?
●存取子程序的抽象层次是否超过了程序语言实现细节?
●所有相互有联系的存取子程序,其抽象程度都是一致的吗?
10.3.10.7小结
●尽量减小变量的作用域。
把对变量引用集中到一起,应尽量使变量成为局部或模块的,避免使用全局变量。
●使每个变量有且仅有一个功能。
●并不是因为全局数据危险才避免使用它们,之所以避免用它是因为可以用更好的技术来代替它。
●如果全局数据确实不可避免的话,应通过存取子程序来对其进行存取操作。
存取子程序不仅具备全局变量和全部功能,而且可以提供更多的功能。
11.基本数据类型
11.1.1.常数
●代码中是否避免了?
奇异数?
(常数?
)
●程序中是否采取了措施来防止出现被“0”除错误?
●类型转换是显式进行的吗?
●如果在同一个表达式中出现了两种不同类型的变量,是否对表达式按照你的意愿进行求值?
●程序中是否避免了混合类型比较?
●在编译过程中是没有警告的吗?
11.1.2.整型数
●使用整型数相除表达式的结果是否与预期的一致?
●整型数表达式中是否避免了整型数溢出问题?
11.1.3.浮点数
●是否避免了数量级相差过大的数之间加减运算?
●程序中是否系统地采取措施来防止舍入误差问题?
●程序中是否避免了对浮点数进行相等比较?
11.1.4.字符和字符串
●程序中是否避免了常数型字符和字符串?
●对字符串的引用是否避免了边界错误?
●若是用c写成的程序,是否是把字符数组和字符串指针区别对待的?
●若程序是用C写成的,是否遵守了把字符串长度说明为CONSTANT+1这一约定?
●是否用字符数组代替指针?
●在C语言程序中,是否把字符由初始化成了NULL以避免出现无限长字符串?
●在C语言程序中,是否用strncpy()代替了strcpy()?
并且用了strncat()和strncmp()?
11.1.5.逻辑变量
●程序中是否使用了附加的逻辑变量来说明条件判断?
●程序中是否使用了附加的逻辑变量来简化条件判断?
11.1.6.枚举类型
●程序中是否用枚举类型代替了命名常量来改善可读性、可靠性和易改动性?
●是否用了枚举类型代替逻辑变量以改进可读性和灵活性?
●在使用了枚举类型的判断中是否检查了无效值?
●枚举类型的第一个入口是否是保留为无效的?
11.1.7.命名常量
●在数据说明中使用的是命名常量吗?
●是否一致地使用了命名常量,而不是一会儿使用命名常量,一会儿使用数值?
11.1.8.数组
●是否所有的下标都在数组界限之内?
●是否对数组所有的引用都没有发生越界错误?
●多维数组的下标排列顺序正确吗?
●在嵌套循环中,作为循环变量的数组下标是正确的吗?
是否出现了交叉错误?
11.1.9.指针
●是否把指针操作独立在函数中?
●指针引用是有效的吗?
是否误用了悬挂指针?
●程序中在使用指针之前,是否对它进行了检查;
●在使用由指针指向的变量之前,是否对其有效性进行了检查?
●在释放指针之后,是否把它们的值赋成了NULL或NIL?
●为了提高可读性,程序中是否使用了所有需要用的指针变量?
●链表中的指针是否是按正确的顺序释放的?
●程序中是否分配了备用内存空间以作为内存溢出时拯救数据和工作努力的降落伞?
●是否是在万不得已时才使用指针的?
11.2.11.10小结
●使用各种特定的数据类型意味着需要记住许多种规则。
因此要用上面的检查表来确认你已考虑过了所有常见问题
12.复杂数据类型
12.1.12.4小结
●l恰当地对数据进行结构化,可以使程序更简单、更容易理解也更容易维护。
●可以用表来代替复杂的逻辑结构。
当你被程序的复杂逻辑迷惑时,应考虑是否可用查寻表来简化程序。
●抽象数据类型是降低复杂性的有力武器。
它使你可以分层编写程序,而且是从问题域而不是程序语言细节来编写顶层的程序。
13.顺序程序语句
13.1.组织顺序式程序代码
●把语句间的依赖关系表示得很清楚吗?
●子程序名是否把依赖关系表示得很清楚?
●子程序的参数是否把依赖关系表示得很清楚?
●若代码的依赖关系不清楚,用注释注明了吗?
●代码能从上读到下吗?
●变量的出现靠得很近吗?
——从跨度和存活时间来考虑。
●是否把相关语句组织在一起?
●是否把相对独立的各相关语句写成子程序了?
13.2.13.3小结
●组织顺序式代码最好的原则是整理出依赖关系。
●用合适的子程序名、参数表、注释来标明依赖关系。
●如果代码没有明显依赖关系,把相关语句组织在一起,特别是使用同一参数的那些语句。
14.条件语句
14.1.if-then语句
●正常情况路径在代码中流向是否很分明?
●if-then语句在出现等号时流向是否正确?
●else语句是否有必要?
●else语句正确吗?
●if语句和else语句正确吗?
它们是否弄反了?
●正常情况是否跟在if后而非else后?
●if-then-else
●复杂的条件是否封装成布尔函数调用了?
●最常见情况放在前面吗?
●全部情况都覆盖住了吗?
●if-then-else语句是最好的选择吗?