将近一个月的面向对象学习,做为一个JAVA新晋选手,针对把“面向过程式封装”思惟逐步过渡为“基于数据管理与分工交互的面向对象”思惟的努力从未止步,回首前三次做业的学习痕迹,看到的不仅是本身进步的过程,更是提升的空间。java
设计技巧总结 正则表达式
增强设计鲁棒性的基础——基于正则的错误输入的准确识别与反馈数组
一个程序想要正确运行的重要前提是对异常输入的识别和拦截。关于正则表达式的语法学习再也不赘述。安全
经过三次练习,结合本身和被测程序的设计思路能够发现,使用正则表达式识别错误主要有两种思路——总体匹配和局部位置匹配,在实践过程当中发现使用二者各有优缺点。 网络
当不须要很是准确的定位输入的错误位置时,咱们更倾向于总体匹配。总体匹配是一种正向思路,对完整正确的输入模式进行格式归纳,设计出匹配表达式,当输入与表达式不能无缝匹配时,说明输入不符合要求。优势是不用分类穷举全部的错误情形,减小了穷举不全的失误,非黑即白的有限衡量标准使得在各种非法测试中表现的很是稳。当正确输入的标准能够适当放宽时易修改,同时避免纳新后的误判。缺点是不易定位出不合规定的错误输入位置,稍显不友好,若是总体匹配代码设计不佳长度过长在大规模输入中可能爆栈。并发
咱们以电梯类的总体匹配输入检测为例,能够发现全部合法输入经过这四个表达式便可彻底描述,简洁清晰。框架
1 private String checkpattern_1="^\\(FR\\,(\\+)?0{0,}1\\,UP\\,(\\+)?0{0,}(\\d+)\\)$"; 2 private String checkpattern_2="^\\(FR\\,(\\+)?0{0,}10\\,DOWN\\,(\\+)?0{0,}(\\d+)\\)$"; 3 private String checkpattern_3="^\\(FR\\,(\\+)?0{0,}[2-9]\\,(UP|DOWN)\\,(\\+)?0{0,}(\\d+)\\)$"; 4 private String checkpattern_4="^\\(ER\\,(\\+)?0{0,}([1-9]|10)\\,(\\+)?0{0,}(\\d+)\\)$";
若是修改楼层范围、上下行命令限制、前导0的个数和符号限制等,很是少的改动便可实现。注意此处^....$的正则组合用于限制正确输入的开头结尾符号,避免匹配到一个非法表达式的正确子串,致使判断错误。eclipse
若是想将错误定位细化到返回错误字符周围环境,且字符种类比较少、字符搭配限定较局限时,位置匹配是一种比较好的策略。它列举每一种字符先后的合法搭配,巧用^,使得若是有匹配结果说明存在非法搭配,必要时返回匹配到的字符串便可。优势是定位准确便于输入者修改,缺点却比较明显,当字符串种类多且搭配普遍时,不免存在列举遗漏,BUG也就被挂在树上了。ide
咱们以多项式计算程序输入为例,一种识别“(”的位置检查设计和实验结果以下:函数
2 String pattern ="\\([^\\d\\+\\-]"; 再配合数字的位置合法性判断,当输入为{1,(1,2)}时,输出为 #1,(
重用代码封装,简化信息传递,营造类的专属“内部生态”
重用代码封装——修改少,逻辑清
咱们对不一样的信息类型处理虽然不尽相同,但模式上是大同小异的。多项式对多项式的信息抽取、结果记录过程是同样的,运算过程只有一个‘+’、‘-’之别,彻底能够将相同操做合并。电梯的FR、ER请求信息虽然不一样,但均可以抽象为请求类,使用一套相同的属性设计去刻画。捎带电梯处理一条主请求和一条捎带请求虽然对一些状态的修改不彻底一致,但运行一条指令并删除其同质指令的流程是一致的,若是彻底割裂直接分两类,那么给电梯解析请求并发送指令以及删除同质指令的代码就会被重复书写,一旦设计存在漏洞,须要修改多处,代码量大就很容易疏忽掉一处,在少许测试下不易发现,埋下了隐患。
简化信息传递——交互智能,安全性强
有些信息没必要暴露在其余类面前,由于类的内部对自身变量的分析能够给出传达给外部的内部状态,而其余类只要获知这种状态就知道本身的行动目标了,解析的过程是一种冗余,对数据存储也不安全,不便于调试。例如调度类和电梯类的交互,电梯没必要获知调度类目前正在解析的指令是FR仍是ER等详细信息,不须要记录本身执行过的指令历史,只须要遵从调度类有限输出信息的指挥,知道本身要去几楼便可,而调度类也只须要知道电梯的当前时间、上下状态、预计到达各个楼层的时间便可为电梯准备下一个command,至于记录下上一调指令的信息便于筛选下一条是调度类的“分内之事”,不须要和别人商量,尽量少的变量共享也就意味着减小误修改、下降分析复杂度,由于分工明确,变量私有,内部运营,DEBUG调试也轻松许多。
营造类的专属“内部生态”——测试完备,定位轻松
若是一个类能够“自给自足的”提供启动信息、输出运营结果,那么测试类的功能性就变得很简单。测试技巧是在类的内部设计一个main函数,每写完一个就进行功能测试,把BUG消灭在底层,防止整个工程build后漏洞百出在总体的视角分段debug。
给方法买人身保险——try-catch维持程序稳定性
设计时把每一个方法都放到try-catch里面并进行必定的容错处理,输出本身设定的报错信息并使程序正常退出实是明智之举。一方面完全排除crash的可能性,加强程序运行的稳定性可靠性,一方面运行后若是出现异常,会输出本身预先设计好的信息,直接能够定位到出错的方法,给猜测错误缘由环节和调试修改环节带来了不少方便。使用格式举例:
1 · try{ 2 .....代码.......... 3 }catch(Exception e) { 4 System.out.println("# calculate函数出现异常"); 5 System.exit(0);//容错机制能够根据须要设计 6 }catch(Error e) { 7 System.out.println("# calculate函数出现错误"); 8 System.exit(0); 9 }
统一基础上的个性化——继承
以课上公司员工和课下电梯调度类为例,这种调用父类的有层次感的方式很是易于创造出统一性和个性化兼备的代码逻辑,便于修改,同时能够实现父类和子类的切换。应该注意的是继承关系中构造函数的使用。
(1)子类的构造过程当中必须调用其父类的构造方法。 (2)子类能够在本身的构造方法中使用 super(argument_list)调用父类的构造方法,也使用 this(argument_list)调用本类的另外构造方法。若是调用 super,必须写在子类构造方法的第一行。 (3)若是子类的构造方法中没有显式调用父类的构造方法,则系统默认调用父类的无参数构造方法。 (4)若是子类构造方法中既没有显式调用父类的构造方法,而父类又没有无参数的构造方法,则编译出错。
其余设计技巧——变量名设计有讲究。天然语言记录设计灵感,施工按照图纸。使用PMD等工具对本身的代码进行评估。
变量名设计不能随意,不然极可能形成写代码过程当中变量名误写,尤为是当错误变量名也存在时,BUG就在不知不觉中产生了。能够巧用'_'链接,缩写易于识别,名称表达变量的特色、用途。
有些逻辑比较复杂的工程好比说电梯设计不建议直接上手写代码,一个可参考的方法是在文档中用天然语言或图表写明设计框架,大概包括类的分工、一个类管理的属性和各个方法接收的信息、主要内部运营逻辑、传达出的信息效果以及方法间、对象之间信息交互的机制检查后再开始写码,这种方式对间断完成工程、逻辑debug提升效率很是有效。
根据PMD反馈的查重复结果,能够提示咱们将重复的部分进行封装。他提示的if-else switch缺失等信息,也能够帮助咱们尽快消灭潜在却很难注意到的BUG。
【关于DEBUG...】
关于if-else:可使用断点调试对可疑处单步运行,也能够设计标记变量测试是否进入该条件若是没有就要查看哪一个变量错误致使条件不知足。
关于跟踪变量:重点跟踪定位其在多个方法调用先后的区别,对比查看到异常变化。
关于类的数组不易查看的属性内容:能够先跟踪某一个存入数组前变量的值,如发现没有异常再使用数组下标遍历对象法查看实际存储值。
做业自检改进与BUG修复
做业1——多项式运算
做业重难点总结:
主要是初学者对正则表达式的学习使用,尤为是屡次匹配一个字符等正则表达方案,正则表达式表达漏洞颇有可能致使意想不到的BUG。正则表达式匹配函数的使用,经常使用匹配函数以下。
一个Matcher对象是一个状态机器,它依据Pattern对象作为匹配模式对字符串展开匹配检查。首先一个Pattern实例订制了一个所用语法与 PERL的相似的正则表达式经编译后的模式,而后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工做。
(以上两图来自网络,不算太全面,放在这里能够方便你们查阅)
关于匹配次数:
[] 由方括号内的一个字符列表建立的自定义字符类 . 匹配任何单个字符 下面的字符将用于控制将一个子模式应用到匹配次数的过程: ? 重复前面的子模式0次到一次 * 重复前面的子模式0次或屡次 + 重复前面的子模式一次到屡次
笔者记性不太好因此emmmmmmmm就把本身用的几个肥肠常见的代码段贴在这里之后直接用嘿嘿嘿嘿 -_-
* 匹配并把匹配结果放到一个数组里面:
1 Pattern p = Pattern.compile("([/+/-]?\\d+)|[\\-\\+]"); 2 3 Matcher m = p.matcher(str); 4 5 List<String> strlist = new ArrayList<String>(); 6 7 while(m.find()) { 8 strlist.add(m.group()); 9 } 10 11 Str = new String[strlist.size()]; 12 13 int i=0; 14 for(String string : strlist) { 15 Str[i] = string; 16 i++; 17 }
* 读入一波字符串并进行必定的操做
1 Scanner sc = new Scanner(System.in); 2 String str=null; 3 4 if(sc.hasNextLine()) { 5 str = sc.nextLine();
//进行某种鲜为人知的操做 @_@ 6 } 7 sc.close(); //必定不要忘了阿!!!!!
* 关于一个字符串可能不方便一次性输出但须要在视觉上是一行:
System.out.print() 结尾没有换行符,很适合输出半句话
System.out.println()结尾有换行符,适合输出行尾
输出时使用一个String变量拼接一个字符串是一个很好的办法,JAVA里面的‘+’简直不能再好用了QAQ!!
问题代码段1:
1 public class ComputePoly{ 2 3 public void computer() { 4 Poly temp=new Poly(Split.len+1); 5 for(int i=0;i<Split.len+1;i++) {
6 temp.term[i]=Split.PolyList[0].term[i];
7 } 8 9 省略计算过程 10 ...... 11 } 12 public void print() {
打印结果 13 ..... 14 } 15 }
待提高提高技能点:一、多项式计算类直接访问split产生的public多项式数组属性,且修改了第一个数组元素的值,很是不安全。
二、第一次写面向对象程序,其实是“披着面向对象外衣的面向过程程序”,对计算类的分工不太明确,将print方法一并写入了计算多项式类的方法中。
解决方案:一、将split类数组属性设为Private但提供查看方法,值不容许写入到第一个数组元素的位置,而是在ComputePoly类设计一个保存结果的Poly类的对象。
二、ComputePoly类对外提供访问private结果属性的方法,打印经过另外一个类调用这个方法获取信息并拼接字符串来实现。
问题代码段2: check方法中的20个对不一样类符号位置合法性判断的方法,举其中两个说明问题
1 public void _1(String str) { 2 String pattern ="[^\\d\\)],"; 3 4 Pattern r = Pattern.compile(pattern); 5 6 Matcher m = r.matcher(str); 7 8 List<String> ComLeList = new ArrayList<String>(); 9 int flag=0; 10 while(m.find()) { 11 flag=1; 12 ComLeList.add(m.group()); 13 } 14 String[] ComLeBug = new String[ComLeList.size()]; 15 int i = 0; 16 for(String ComBug:ComLeList) { 17 ComLeBug[i] = ComBug; 18 i++; 19 } 20 if(flag==1) { 21 System.out.println("ERROR"); 22 for(int j=0;j<ComLeBug.length;j++) { 23 System.out.println("#"+ComLeBug[j]); 24 } 25 exit=1; 26 } 27 } 28 29 public void _2(String str) { 30 String pattern =",[^\\(\\d\\+\\-]"; 31 32 Pattern r = Pattern.compile(pattern); 33 34 Matcher m = r.matcher(str); 35 36 List<String> ComLeList = new ArrayList<String>(); 37 int flag=0; 38 while(m.find()) { 39 flag=1; 40 ComLeList.add(m.group()); 41 } 42 String[] ComLeBug = new String[ComLeList.size()]; 43 int i = 0; 44 for(String ComBug:ComLeList) { 45 ComLeBug[i] = ComBug; 46 i++; 47 } 48 if(flag==1) { 49 System.out.println("ERROR"); 50 for(int j=0;j<ComLeBug.length;j++) { 51 System.out.println("#"+ComLeBug[j]); 52 } 53 exit=1; 54 } 55 }
解决方案:”方法间只有匹配串不一样而检测逻辑彻底相同,因此应该封装为一个以匹配正则串和待检测字符串为参数的方法。经过屡次调用减小代码无用重复。
其余待提高技能点:善用try catch。
【BUG修复】
BUG: 输入:{(1,2 错误输出:{(1,2)}
输入 : { 错误结果:crash
出错缘由分析:局部位置匹配法设计出的正则匹配串用于检索匹配到其余字符的状况,但若是是旁边缺失则很难发现,甚至认为是正确输入继续计算,gg了。
方案修正:首先在这种环境下选用总体匹配可使代码健壮性更强,若是必定要使用局部位置匹配须要对括号这种必须成对出现的符号有单独判断。最佳方案是使用总体匹配判断输入正误,再用局部匹配反馈错误位置。添加try catch。
特别注意:
对回车、空格等空输入的处理。
做业2——傻瓜式电梯设计
做业重难点总结:
一、电梯类和调度类之间如何巧妙的交互??调度类怎么指挥电梯??
二、调度类怎么才能又快又准的排除同质请求并准备出一个新的请求?
三、如何使ER和FR既有不一样又存在能够合并处理的统一性?
四、对队列的操做怎样才能没有BUG?删除同质后下标必定要保持在原地而不是被加一再继续检查!!
五、对同质的准确理解!!抓住ER和FR必定不是同质!
问题代码段1:
1 sliptthenadd代码段
待提高技能点:split在写法上存在很大优化空间,这是由于split封装重用的空间很大,使用了20多个局部位置匹配函数致使对每一个字符串的处理都很费时间。split类中根据第一个有效字符是符号仍是数字分类,依次将信息存入多项式数组,但if和else的内部存储的过程除下标差1外基本重复,使代码量大幅度增长,给修改带来了很大困难,也增大了出错风险。分工不清,将split和add到队列中的过程设计为了一个方法,检查数据范围的过程重复书写,多个报ERROR的else能够统一设计为1到2个ERROR。
解决方案:将重复的部分封装成一个存储方法,不一样的地方能够传入变更信息进行替换,这样只须要调用这个存储函数并传入可变下标便可。分别为分离数据和加入到队列中的过程设计为两个方法,且使得方法对FR和ER指令都有必定的包容性。数字范围检查封装设计。合并多个非法输入的else。
问题代码段2:
将删除同质请求并schedule出一个可执行的请求的方法实如今了请求队列类。
待提高技能点:准备一个新的可执行合法指令的职责属于Scheduler类。请求队列自己只对外提供删除队列元素、查看队列元素、添加队列元素的操做将使得思路更加清晰。
解决方案:将这个自检并调度函数改到Scheduler类。
问题代码段3:
Scheduler类的commander方法将取指令和对电梯发出调度信号一并书写,致使第一条指令和非第一条指令关于调度发出信号的部分重复。
解决方案:将取指令和解析指令发出调度信号分开,实际上是否是第一次取指令交给电梯区别不大,能够合并。
虽然此次做业没有被查到功能性BUG,但我认为如下几点值得注意:
一、若是控制指令执行条数是100条,则当使用变量++记录数目并经过判断变量大小决定是否可继续读入时,须要注意边界条件的设计,尤为是取等条件。 2、因为队列的变更幅度比较大,最好采用动态数组,在动态数组中要熟练设计查看、移除、添加元素的方法。 3、属性一概设计为Private,并非全部的属性都须要对外提供get方法,尽可能减小提供get方法的机会,尽可能减小甚至杜绝提供set方法,必定要注意减小无心中的变量属性共享,尤为是数组属性。 四、检查输入格式和数字范围过程尽可能集中,利于修改。必定要大幅度改进封装水平和抽象水平。
做业3——可捎带(ALS)电梯
做业重难点:
此次做业主要是在理解捎带策略的状况下熟悉对tostring的重写、Scheduler的继承机制、接口的设计与实现等,对代码的重复冗余作了从新的封装优化。Scheduler继承了上次做业,主要继承的是schedule方法,也就是排除同质的方法,同时本身还要补充顺路捎带的调度方法。使用super来调用父类的内容。难点在于如何轻松的在父类和子类之间调用自如,而不是出现混乱。对继承的理解须要借助代码多加观察和练习。
另外,发现大多数同窗出现BUG的缘由是对捎带的边界条件认识不清。此处墙裂推荐同窗们:一、能够提前阅读指导书作到心中有数,但等指导书稳定下来再写代码,不然极可能会带着错误的认识写了一套不合题意的代码而后改的时候你就该哭唧唧了!二、指导书比较长,新建一个文档把重点粘贴下来!作一波面向本身设计需求的从新整理!三、发现本身混乱的时候不是先求助别人而是先从新看指导书再和别人讨论!不然极可能被越说越乱!
因为没有被发现功能性BUG(主要问题是get set有点多说明数据管理分配还有待改善),下面将学习过程当中的疑难点作简要总结:
一、重写和重载:
override(重写) 1、方法名、参数、返回值相同。 2、子类方法不能缩小父类方法的访问权限。 3、子类方法不能抛出比父类方法更多的异常(但子类方法能够不抛出异常)。 4、存在于父类和子类之间。 5、方法被定义为final不能被重写。 overload(重载) 1、参数类型、个数、顺序至少有一个不相同。 2、不能重载只有返回值不一样的方法名。 三、存在于父类和子类、同类中。
二、学习继承中一个有趣的现象:
1 public class TestExtend{ 2 public static void main(String args[]){ 3 Student s=new Student(); 4 s.disp(); 5 } 6 } 7 8 class Person{ 9 int a; 10 public Person(){ 11 a=1; 12 } 13 public void disp(){ 14 System.out.println(a); 15 } 16 } 17 18 class Student extends Person{ 19 int a; 20 public Student(){ 21 a=2; 22 } 23 }
解析:运行上面的程序,输出的是1仍是2?你会看到输出的是1!
上面的程序中Person和Student类中都有a属性,咱们定义了一个Student的对象s,调用s的disp()方法输出的不是Student的a而是Person的a。相信不少人在运行程序前都会以为应该输出2,但结果告诉咱们输出的就是1!子类Student虽然覆盖了父类的属性a,但子类没有重写父类的disp()方法,对象s调用disp()方法时调用的依然是父类的方法,而父类方法访问的依然是父类的a,而不是子类的a。这里或者重写父类的disp()方法,或者将Student中的int a;注释掉才能输出2!其实上面程序在逻辑上是有问题的,既然继承了父类的属性,就不该该在子类中新定义一遍,子类中能够增长属性,可是重写属性没有什么意义! 同时,子类对继承来的属性赋初值时,能够经过调用super(属性初值)也即父类的构造函数的方法。
关于继承的特色的总结:
1、子类只能继承父类全部非私有的成员(成员方法和成员变量) 2、子类不能继承父类的构造方法,可是能够经过super关键字去访问父类的构造方法。
三、咱们何时考虑继承?若是有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就能够考虑使用继承
四、重写某方法后子类仍然能够返回父类的方法:使用super
三次做业可能涉及到的一些JAVA易混淆的关键字、特性等的介绍
有关static
static方法是静态方法,没有static的是非静态方法。 静态方法必须建立对象才能访问非静态成员。静态方法能够不建立对象,直接访问静态成员,也能够经过建立对象来访问。
static修饰的静态方法会随着类的定义而被分配和装载入内存中,编译器只为整个类建立了一个静态变量的副本,也就是只分配一个内存空间,虽然可能有多个实例,但这些实例共享该内存,特别值得注意的是,任何一个对象对静态数据成员的修改,都会影响其它对象。
使用类名加前缀访问静态方法,使用实例化对象名访问静态方法。
静态方法只能访问静态数据成员,非静态方法能够访问静态方法和非静态方法,非静态方法能够直接访问非静态数据成员和静态数据成员。
参考代码:
1 import java.util.*; 2 3 public class TestStatic { 4 public static void main(String[]args){ 5 System.out.println(S.getStatic());//使用类名加前缀访问静态方法 6 S s=new S(); 7 System.out.println(s.getStatic());//使用实例化对象名访问静态方法 8 System.out.println(s.get()); 9 } 10 public static class S 11 { 12 private static int a; 13 private int t=0; 14 15 //静态初始器:由static和{}组成,只在类装载的时候(第一次使用类的时候)执行一次,每每用来初始化静态变量。 16 static{ 17 a=10; 18 } 19 20 //静态方法只能访问静态数据成员 21 public static int getStatic() 22 { 23 return a; 24 } 25 26 public int getT() 27 { 28 return t; 29 } 30 31 //非静态方法能够访问静态方法和非静态方法 32 public int get() 33 { 34 getT(); 35 getStatic(); 36 t=a;//非静态方法能够访问非静态数据成员和静态数据成员 37 return t; 38 } 39 } 40 }
super用法总结:
第1、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。 第2、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,用“super.成员变量名”来引用父类成员变量。固然,若是父类的成员变量没有被覆盖,也能够用“super.成员变量名”来引用父类成员变量,不过这是没必要要的。 第3、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有彻底相同的方法定义(但方法体能够不一样),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
关于final关键字:
它的主要用法有如下四种: 用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值没法被改变。对于成员变量来说,咱们必须在声明时或者构造方法中对它赋值; 用来修饰方法参数,表示在变量的生存期中它的值不能被改变; 修饰方法,表示该方法没法被重写; 修饰类,表示该类没法被继承。 上面的四种方法中,第三种和第四种方法须要谨慎使用,由于在大多数状况下,若是是仅仅为了一点设计上的考虑,咱们并不须要使用final来修饰方法和类。
this用法总结:
第1、经过this调用另外一个构造方法,用发是this(参数列表),这个仅仅在类的构造方法中,别的地方不能这么用。 第2、函数参数或者函数中的局部变量和成员变量同名的状况下,成员变量被屏蔽,此时要访问成员变量则须要用“this.成员变量名”的方式来引用成员变量。固然,在没有同名的状况下,能够直接用成员变量的名字,而不用this。 第3、在函数中,须要引用该函所属类的当前对象时候,直接用this。 其实这些用法都是从对“this是指向对象自己的一个指针”这句话的更深刻的理解而来的。
测试用例设计策略
一般是使用分支树不重不漏的进行测试,主要的测试思想是先总体联合后局部深刻,也即先对几个功能进行捆绑性测试,若是发现有问题再进一步细化测试,直到排查出具体错误功能。重点测试一些违反正常思惟的状况。
对本身的测试须要先测试输入再测试处理功能,对同窗互测的程序须要针对其代码设计猜测其最有可能出现漏洞的地方进行针对性优先测试,主要是先功能后输入,设计针对性的设计样例。
这就涉及到读对方的代码,不要求所有读懂,但要对其处理逻辑心中有数,由于可能他的处理逻辑自己就有漏洞,有必要时能够选用流程图的方式辅助认识其处理运行逻辑。能够结合其公测被测状况设计出公测可能没有测试到的但设计思惟相同的样例,好比公测发现其对ER的处理有问题,那么能够优先测试其对FR的类似处理是否是有问题。
对于输入型测试:
主要测试思路为:简单标准型、边界正确型、边界错误型、随机输入型、大规模输入压力测试型
对于功能型测试:
主要测试思路为:基础功能型、不知足处理条件正常退出型、多种被处理情形尤为包括边界状况知足被处理条件的情形。尤为注意一些极端状况的测试和维护。
下面对三次做业的重点测试类型概括并对经典测试样例举例:
做业1特殊样例:第一个多项式前有无符号、异常字符、空多项式、阶数或系数超大的多项式、单个多项式、负数阶多项式、系数为负的多项式、任意非法输入(包括右大小括号的缺失以及只有一个括号等极端状况的测试)
做业2特殊样例:各类随机输入、1层和10层的FR指令方向特殊性、符号和前导0等、以2的32次方(4字节)为边界的合法和不合法测试、输入时间乱序、同质请求测试(重点),首条指令的目标楼层在1层,多条相同或不一样类型的指令连续对同层操做,FR、ER交替发出、同时发出等。
做业3特殊样例:在做业2样例的基础上有意设计捎带的边界样例,尤为是对同层相同时间和不一样时间包括开关门阶段及边界的反复操做,以及对某一层的反复请求,注意观察被测程序对同质和选择捎带指令的顺序,由于此处很容易出现逻辑漏洞。以及输出顺序的问题等。
总结
耿直girl须要伪装这里有个总结——
总之由于是刚入门,本身的代码即便在没有BUG的状况下也是很须要优化写法的,明显感受到如下几点须要提起注意(相信也是大多数同窗的感觉):
一、命名要有意义有区分度。除了临时循环变量不一样类之间、不一样阶段之间尽可能不要出现命名彻底同样的变量,很容易蒙圈QAQ。
二、必定要注意封装重用!必定要注意封装重用!必定要注意封装重用!
三、必定要把握好全部的等号边界!!
四、尽可能减小private变量的get set方法!交互要简洁!
五、一个功能一次测试,事半功倍!
六、分工必定要准确有道,不可越俎代庖!!文档是好助手!
七、try-catch
八、测试时越不合常规的状况越要好好测!!边界数据使用各类姿式测试很重要!暴力数据也要测!BUG出如今夹缝中!
九、代码修改先不要删,先注释掉!没准是你脑袋瓦特忽然改错了!orz
十、必定要学会用eclipse调试,直接打印变量效率很低。
十一、readme不要自相矛盾emmm对于天然语言描述难令人理解的地方给出样例说明!
十二、在通常的数组和动态数组之间...选动态数组好吗!!动态数组省空间并且简直不能再好用!
1三、整理指导书!书读百遍,其义自见。
1四、不要惧怕学习没用过的东西,java巧妙的地方有不少。百度一下,你就知道。
要是还有没说完的重点或者手残写错的地方emmmmmmmm麻烦你们在评论区提醒下本智障嘻嘻谢= =!咱们下期再见!