维护、异常、调试
1.可维护性的度量指标
圈复杂度:代码控制流执行路径的数量。
代码行数。
可维护性指数:根据循环复杂度、代码行数、注释密度等计算的一个指数。
继承的层数。
类之间的耦合度。
单元测试覆盖度。
2.内聚、耦合
内聚,指的是同一个模块之间的相互联系
耦合,指的是不同模块之间的相互联系
高内聚、低耦合,指的是各个模块之间的独立性要强,模块内部的相关性要强、尽量只负责一项任务。
3.正则语法、正则表达式
首先要注意,“\”这个字符在java里是转义字符,在正则语言里也是转义字符,这就导致了“\”是java转义字符,"\\"是java斜杠、java中正则语言的转义字符,"\\\\"才是java正则语言的斜杠。
java.util.regex 包主要包括以下三个类:
- Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
- Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
Matcher方法:
分组匹配示例
Pattern p=Pattern.compile("([a-z]+)(\\d+)"); Matcher m=p.matcher("aaa2223bb"); m.find(); //匹配aaa2223 m.groupCount(); //返回2,因为有2组 m.start(1); //返回0 返回第一组匹配到的子字符串在字符串中的索引号 m.start(2); //返回3 m.end(1); //返回3 返回第一组匹配到的子字符串的最后一个字符在字符串中的索引位置. m.end(2); //返回7 m.group(1); //返回aaa,返回第一组匹配到的子字符串 m.group(2); //返回2223,返回第二组匹配到的子字符串
找到所有的匹配串
Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("hit117mid116fit11111"); while(m.find()) { System.out.println(m.group()); }
4.健壮性、正确性
健壮性:系统在不正常输入或不正常外部条件下仍能够表现正常的程度。
要处理未期望的行为和错误终止,要准确、无歧义的向用户全面展示错误信息,这些错误信息有助于debug。
要考虑用户的各种行为、恶意攻击、极端情况,尽量封闭细节实现。
正确性:就是程序在正确输入下是正确的、严格按照spec的要求来的,是最重要的质量指标
对比:
正确性倾向于报错、健壮性倾向于容错。
对外倾向于健壮,对内倾向于正确。
5.Java的异常处理相关支持类
①Throwable(java.lang)
它是Exception和Error的父类,只有Throwable对象可以被虚拟机、throw语句抛出。
它包含线程的执行堆栈快照,以及一个用于提示更多错误消息的字符串
构造器可以接受两个参数,第一个参数是错误详细信息,第二个参数是异常发生的原因
setStackTrace()、getStackTrace()、printStackTrace()可以存储、获取、打印堆栈快照信息
initCause()、getCause()可以存储、获取异常发生的原因(也是一个Throwable对象)
getMessage、getLocalMessage可以获取错误详细信息,其中后者可以被重新,获得一些本地化处理后的错误详细信息。
②Error
Throwable的子类,表示不应该被捕获的严重错误,一般表示一些反常的情况,程序应该尽量取避免他们,而不是捕获、处理。
③Exception
Throwable的子类,暗示程序可能会需要在程序中去捕获他们,其中RuntimeException不是受查异常,其他都是受查异常。
④RuntimeException
通常是由程序员在程序中的不当处理导致的,可以避免。比如数组越界、null、除零错误、参数错误。
6.受查异常、非受查异常
受查异常:除了Error和RuntimeException的全部异常,必须要在程序中处理,要么用try_catch语句块进行捕获,要么抛出给上一级处理。可能需要进行一些恢复。
非受查异常:Error和RuntimeException异常,不需要进行捕获,应该尽量避免。知识简单打印异常信息就可以,不需要进一步处理。
7.finally
这个语句跟在catch(){}的后面,无论是否发生异常,都会执行。
finally执行的必要条件:虚拟机没有被关闭,线程没有被打断、try中的所有控制转移之前的语句全部执行完毕。
它会被插入到“控制转移语句”之前,也就是说,如果在try中返回0、在finally中返回1,最终程序返回的会是1
详见https://www.ibm.com/developerworks/cn/java/j-lo-finally/index.html
8.断言
主要用于开发阶段查错,实际上比较消耗性能,实际运行时要去掉或者禁用
不要用它检查来自于外部的错误,比如参数传的不正确等等。
如果断言所指定的条件不成立,那么立即产生一个AssertionError,程序终止
这个断言缺省条件下是关闭的,要加一个-ea参数
用法:
assert condition
assert condition message(用于弹出更多有用信息)
可以用来检查不变量、前置条件、后置条件等等。
9.测试
测试时发现问题,调试是解决问题。
白盒测试是对程序内部结构的测试,黑盒测试是对程序外部表现出来的行为的测试。
测试用例:不重不漏、简单有效。
要将输入的情况划分为若干等价类,每一个等价类里选出一个代表的测试用例即可。
比如要求n必须是正奇数
①是否是整数
②是否是正数
③是否是奇数
要考虑边界情况、边界两侧的情况、非常大或非常小的数据、上下限。
通过输入划分一些维度,然后每个维度考虑上面讨论的取值情况,然后将这些维度的情况进行组合,要保证每个维度的每个情况都要覆盖到。
测试策略要写在每个测试函数的上方,说明覆盖的情况。
ppt标准例子:
10.测试覆盖
路径覆盖:包含所有可能的控制流程,难度最大。
分支覆盖:覆盖所有分支语句的所有情况,难度中等。
语句覆盖:覆盖所有程序语句,难度最低。