20145214实验二 Java面向对象程序设计
初步掌握单元测试和TDD
三种代码
-
伪代码
`百分制转五分制:` `如果成绩小于60,转成“不及格”` `如果成绩在60与70之间,转成“及格”` `如果成绩在70与80之间,转成“中等”` `如果成绩在80与90之间,转成“良好”` `如果成绩在90与100之间,转成“优秀”` `其他,转成“错误”`
-
产品代码
public class MyUtil{ public static String percentage2fivegrade(int grade){ //如果成绩小于60,转成“不及格” if (grade < 60) return "不及格"; //如果成绩在60与70之间,转成“及格” else if (grade < 70) return "及格"; //如果成绩在70与80之间,转成“中等” else if (grade < 80) return "中等"; //如果成绩在80与90之间,转成“良好” else if (grade < 90) return "良好"; //如果成绩在90与100之间,转成“优秀” else if (grade < 100) return "优秀"; //其他,转成“错误” else return "错误"; } }
-
测试代码
-
1、用50分测试时:
public class MyUtilTest { public static void main(String[] args) { // 百分制成绩是50时应该返回五级制的“不及格” if(MyUtil.percentage2fivegrade(50) != "不及格") System.out.println("test failed!"); else System.out.println("test passed!"); } }
-
2、测试正常情况时:
public class MyUtilTest { public static void main(String[] args) { //测试正常情况 if(MyUtil.percentage2fivegrade(55) != "不及格") System.out.println("test failed!"); else if(MyUtil.percentage2fivegrade(65) != "及格") System.out.println("test failed!"); else if(MyUtil.percentage2fivegrade(75) != "中等") System.out.println("test failed!"); else if(MyUtil.percentage2fivegrade(85) != "良好") System.out.println("test failed!"); else if(MyUtil.percentage2fivegrade(95) != "优秀") System.out.println("test failed!"); else System.out.println("test passed!"); } }
-
3、输入负分或大于100时:
public class MyUtilTest3 { public static void main(String[] args) { //测试出错情况 if(MyUtil2.percentage2fivegrade(-10) != "错误") System.out.println("test failed 1!"); else if(MyUtil2.percentage2fivegrade(115) != "错误") System.out.println("test failed 2!"); else System.out.println("test passed!"); } }
-
4、增加对负分的判断后:
public class MyUtil3{ public static String percentage2fivegrade(int grade){ //如果成绩小于0,转成“错误” if ((grade < 0)) return "错误"; //如果成绩小于60,转成“不及格” else if (grade < 60) return "不及格"; //如果成绩在60与70之间,转成“及格” else if (grade < 70) return "及格"; //如果成绩在70与80之间,转成“中等” else if (grade < 80) return "中等"; //如果成绩在80与90之间,转成“良好” else if (grade < 90) return "良好"; //如果成绩在90与100之间,转成“优秀” else if (grade <= 100) return "优秀"; //如果成绩大于100,转成“错误” else return "错误"; } }
-
5、测试边界情况:
public class MyUtilTest4{ public static void main(String[] args) { //测试边界情况 if(MyUtil2.percentage2fivegrade(0) != "不及格") System.out.println("test failed 1!"); else if(MyUtil2.percentage2fivegrade(60) != "及格") System.out.println("test failed 2!"); else if(MyUtil2.percentage2fivegrade(70) != "中等") System.out.println("test failed 3!"); else if(MyUtil2.percentage2fivegrade(80) != "良好") System.out.println("test failed 4!"); else if(MyUtil2.percentage2fivegrade(90) != "优秀") System.out.println("test failed 5!"); else if(MyUtil3.percentage2fivegrade(100) != "优秀") System.out.println("test failed 6!"); else System.out.println("test passed!"); } }
-
6、优秀成绩包含100时:
TDD
-
先写测试代码,然后再写产品代码的开发方法叫“测试驱动开发”(TDD)。
-
TDD的一般步骤如下:
1、明确当前要完成的功能,记录成一个测试列表
2、快速完成编写针对此功能的测试用例
3、测试代码编译不通过(没产品代码呢)
4、编写产品代码
5、测试通过
6、对代码进行重构,并保证测试通过(重构下次实验练习)
7、循环完成所有功能的开发
-
TDD的编码节奏是:
1、增加测试代码,JUnit出现红条
2、修改产品代码
3、JUnit出现绿条,任务完成
理解并掌握面向对象三要素:封装、继承、多态
- 面向对象(Object-Oriented)的三要素包括:封装、继承、多态。
- 面向对象的思想涉及到软件开发的各个方面,如面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程实现(OOP)。
- OOA根据抽象关键的问题域来分解系统,关注是什么(what)。
- OOD是一种提供符号设计系统的面向对象的实现过程,用非常接近问题域术语的方法把系统构造成“现实世界”的对象,关注怎么做(how),通过模型来实现功能规范。
- OOP则在设计的基础上用编程语言(如Java)编码。贯穿OOA、OOD和OOP的主线正是抽象。
初步掌握UML建模
- 我们可以用UML中的类图来描述类
Dog
,首先我们在实验楼的环境中打开shell,在命令行中输入umbrello
,打开UML建模软件umbrello
熟悉S.O.L.I.D原则
- SRP(Single Responsibility Principle,单一职责原则)
- OCP(Open-Closed Principle,开放-封闭原则)
- LSP(Liskov Substitusion Principle,Liskov替换原则)
- ISP(Interface Segregation Principle,接口分离原则)
- DIP(Dependency Inversion Principle,依赖倒置原则)
练习
使用TDD的方式设计关实现复数类Complex
-
伪代码
复数类Complex 复数=实部数+虚部数 i 复数相加 = (实部+实部) + (虚部 + 虚部)i 复数相减 = (实部-实部) + (虚部 - 虚部)i 打印复数: 虚部大于0 "实部"+"+"+"虚部"+"i" 虚部小于0 "实部"+"虚部"+"i" 虚部为0 "实部"
-
产品代码
public class ComplexNumber { double r,i; public ComplexNumber(){ this.r=0; this.i=0; } public ComplexNumber(double r, double i){ this.r=r; this.i=i; } public double GetRealPart(){ return this.r; } public double GetImaginaryPart(){ return this.i; } public void SetRealPart(double r){ this.r=r; } public void SetImaginaryPart(double i){ this.i=i; } public ComplexNumber ComplexAdd(ComplexNumber a,ComplexNumber b) { ComplexNumber temp = new ComplexNumber(); temp.r = a.r + b.r; temp.i = a.i + b.i; return temp; } public ComplexNumber ComplexMinus(ComplexNumber a,ComplexNumber b) { ComplexNumber temp =new ComplexNumber(); temp.r=a.r - b.r; temp.i =a.i - b.i; return temp; } public ComplexNumber ComplexMulti(ComplexNumber a,ComplexNumber b) { ComplexNumber temp = new ComplexNumber(); temp.r = a.r*b.r-a.i*b.i; temp.i = a.r*b.i+a.i*b.r; return temp; } public void ComplexAdd(ComplexNumber c){ this.r=this.r+c.r; this.i=this.i+c.i; } public void ComplexMinus(ComplexNumber c){ this.r=this.r-c.r; this.i=this.i-c.i; } public void ComplexMulti(ComplexNumber c) { double temp=this.r; this.r=this.r*c.r-this.i*c.i; this.i =temp*c.i+this.i*c.r; } public void printComplexNumber(){ System.out.print(""+this.r+"+"+this.i+"i"); } }
-
测试代码
public class txet extends ComplexNumber{ public static void main(String[] args) //测试代码 { ComplexNumber cc=new ComplexNumber(4,5); cc.printComplexNumber(); System.out.println(); ComplexNumber dd=new ComplexNumber(2,4); dd.printComplexNumber(); System.out.println(); System.out.println("-----------------"); System.out.println(); ComplexNumber ff=new ComplexNumber(); ff=ff.ComplexAdd(cc,dd); ff.printComplexNumber(); System.out.println(); ff=ff.ComplexMinus(cc,dd); ff.printComplexNumber(); System.out.println(); ff=ff.ComplexMulti(cc,dd); ff.printComplexNumber(); System.out.println(); System.out.println("-----------------"); } }
总结单元测试的好处
在单元测试活动中,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试,可以查找错误、写出高质量的代码、提高编程水平。
经过网上查询资料,单元测试的好处远不止我目前发现的这些。它可以使代码可以放心修改和重构、使程序员从调用者而不是实现者的角度设计软件模块、
使程序员将软件模块写得易于测试和调用,从而有利于解耦、测试本身可作为被测代码的用法说明,从而替代了一部分文档功能。
我的PSP时间
步骤 | 耗时 | 百分比 |
---|---|---|
需求分析 | 30min | 12.5 |
设计 | 40min | 16.7 |
代码实现 | 100min | 41.7 |
测试 | 40min | 16.7 |
分析总结 | 30min | 12.5 |
实验心得体会
本次实验让我了解到想用程序解决实际问题时,不仅是只要写出一个代码就可以了,而是最好写出三种代码:伪代码、产品代码、测试代码,这样的程序才有
实际意义,方便使用。而且运用好单元测试可以在未来的程序设计中让自己负责的模块功能定义尽量明确,模块内部的改变不会影响其他模块,而且模块的质
量能得到稳定的、量化的保证。希望以后能通过实验了解更多运用java解决实际问题的方法。