zoukankan      html  css  js  c++  java
  • 20165227 实验二《Java面向对象程序设计》实验报告

    2017-2018-4 20165227实验二《Java面向对象程序设计》实验报告

    实验内容

    1. 初步掌握单元测试和TDD
    2. 理解并掌握面向对象三要素:封装、继承、多态
    3. 初步掌握UML建模
    4. 熟悉S.O.L.I.D原则
    5. 了解设计模式

    实验要求

    1. 没有Linux基础的同学建议先学习《Linux基础入门(新版)》《Vim编辑器》 课程
    2. 完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等)。报告可以参考范飞龙老师的指导
    3. 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。

    实验步骤

    一、单元测试

    1、三种代码
    要了解并养成用写三种代码来编程的习惯

    • 伪代码
    • 产品代码
    • 测试代码

    举个例子:我们要在一个MyUtil类中解决一个百分制成绩转成“优、良、中、及格、不及格”五级制成绩的功能。

    先写伪代码,伪代码与具体编程语言无关,不要写与具体编程语言语法相关的语句,伪代码从意图层面来解决问题,最终,伪代码产品代码最自然的、最好的注释。

    百分制转五分制:
    如果成绩小于60,转成“不及格”
    如果成绩在60与70之间,转成“及格”
    如果成绩在70与80之间,转成“中等”
    如果成绩在80与90之间,转成“良好”
    如果成绩在90与100之间,转成“优秀”
    其他,转成“错误”

    写完伪代码后,就可以用特定的编程语言翻译一下,就是可用的产品代码了。这里使用JavaMyUtil.java:

    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 "错误";
    }
    }

    一般来说产品代码出来后,大部分工作可以说是完成了,但是,谁能保证你的产品代码不会出现bug或者错误呢?所以这个时候就需要编写测试代码,通过测试代码能够更好的完善最后的产品代码~

    在IDEA中我们可以借助单元测试工具JUnit来辅助进行TDD,直接点击Create Test就可以了

    而且,测试代码仅测试一种情况往往是不够的,通常来说会进行三个方面的测试:
    正常情况

    import org.junit.Test;
    import junit.framework.TestCase;
    public class MyUtilTest extends TestCase {
    @Test
    public void testNormal() {
    assertEquals("不及格", MyUtil.percentage2fivegrade(55));
    assertEquals("及格", MyUtil.percentage2fivegrade(65));
    assertEquals("中等", MyUtil.percentage2fivegrade(75));
    assertEquals("良好", MyUtil.percentage2fivegrade(85));
    assertEquals("优秀", MyUtil.percentage2fivegrade(95));
    }
    }

    异常情况

    import org.junit.Test;
    import junit.framework.TestCase;
    public class MyUtilTest extends TestCase {
    @Test
    public void testException() {
    assertEquals("错误", MyUtil.percentage2fivegrade(-55));
    assertEquals("错误", MyUtil.percentage2fivegrade(105));
    }
    }

    边界情况

    import org.junit.Test;
    import junit.framework.TestCase;
    public class MyUtilTest extends TestCase {
    @Test
    public void testBoundary() {
    assertEquals("不及格", MyUtil.percentage2fivegrade(0));
    assertEquals("及格", MyUtil.percentage2fivegrade(60));
    assertEquals("中等", MyUtil.percentage2fivegrade(70));
    assertEquals("良好", MyUtil.percentage2fivegrade(80));
    assertEquals("优秀", MyUtil.percentage2fivegrade(90));
    assertEquals("优秀", MyUtil.percentage2fivegrade(100));
    }
    }

    • 如果测试通过就会显示test passed

    • 如果测试没通过,则会显示红色,并显示 test failed,而且会告知哪里出了错误

    通过最后的测试代码的成功测试后,我们的产品代码才算是真正的完工了。当然,测试代码的编写不能随意,应该尽可能地考虑周全,才能很好的完善产品代码

    码云链接
    MyUtil.java
    MyUtilTest.java

    二、TDD(Test Driven Devlopment, 测试驱动开发)

    1. 先写测试代码,再写产品代码的TDD的一般步骤如下:
    • 明确当前要完成的功能,记录成一个测试列表
    • 快速完成编写针对此功能的测试用例
    • 测试代码编译不通过(没产品代码呢)
    • 编写产品代码
    • 测试通过
    • 对代码进行重构,并保证测试通过(重构下次实验练习)
    • 循环完成所有功能的开发
    1. TDD的编码节奏是:
    • 增加测试代码,JUnit出现红条
    • 修改产品代码
    • JUnit出现绿条,任务完成
    1. 老师给的StringBuffer 的例子 积极主动敲代码,使用JUnit学习Java

    public class StringBufferDemo{
    public static void main(String [] args){
    StringBuffer buffer = new StringBuffer();
    buffer.append('S');
    buffer.append("tringBuffer");
    System.out.println(buffer.length());
    System.out.println(buffer.charAt(1));
    System.out.println(buffer.capacity();
    System.out.println(buffer.indexOf("tring"));
    System.out.println("buffer = " + buffer.toString());
    }
    }

    首先我们需要改写一下例子中的程序,使其能够使用TDD来测试。改代码之前我们得知道StringBufferDemo类中的方法都是什么功能,才能知道我们需要测试哪些内容。通过查阅资料,得知

    • StringBuffer( ):分配16个字符的缓冲区
    • length():返回字符串的长度
    • charAt(int i) :返回此序列中指定索引处的 char 值。第一个 char 值在索引 0 处,第二个在索引 1 处,依此类推
    • capacity():返回string分配的存储容量
    • indexOf(String s):返回输入的子字符串的第一个字母在母字符串的位置

    最后的出的产品代码:

    public class StringBufferDemo{
    StringBuffer buffer = new StringBuffer();
    public StringBufferDemo(StringBuffer buffer){
    this.buffer = buffer;
    }
    public Character charAt(int i){
    return buffer.charAt(i);
    }
    public int capacity(){
    return buffer.capacity();
    }
    public int length(){
    return buffer.length();
    }
    public int indexOf(String buf) {
    return buffer.indexOf(buf);
    }
    }

    通过IDEA中的TDD写出的测试代码:

    import junit.framework.TestCase;
    import org.junit.Test;
    public class StringBufferDemoTest extends TestCase {
    StringBuffer a = new StringBuffer("zhuyueniupi");//(<=16)
    StringBuffer b = new StringBuffer("zhuyueniupizhuyueniupi");//(>16&&<=34)
    StringBuffer c = new StringBuffer("zhuyueniupizhuyueniupizhuyueniupi");//(>=34)
    @Test
    public void testcharAt() throws Exception{
    assertEquals('z',a.charAt(0));
    assertEquals('u',a.charAt(2));
    assertEquals('p',a.charAt(9));
    assertEquals('i',a.charAt(10));
    }
    @Test
    public void testcapacity() throws Exception{
    assertEquals(27,a.capacity());
    assertEquals(38,b.capacity());
    assertEquals(49,c.capacity());
    }
    @Test
    public void testlength() throws Exception{
    assertEquals(11,a.length());
    assertEquals(22,b.length());
    assertEquals(33,c.length());
    }
    @Test
    public void testindexOf() throws Exception{
    assertEquals(0,a.indexOf("zh"));
    assertEquals(3,a.indexOf("yueniu"));
    assertEquals(7,a.indexOf("iupi"));
    }
    }

    测试运行截图:

    码云链接
    StringBufferDemo.java
    StringBufferDemoTest.java

    三、面向对象三要素

    • 抽象
      程序设计中,抽象包括两个方面,一是过程抽象,二是数据抽象

    例如:打印“1-100”这种大数据的时候

    public void printn(int n){
    for(int i=1; i<=n; i++)
    System.out.println(n);
    }

    而且能够更地简便打印

    printn(3);

    • 封装、继承与多态
      面向对象(Object-Oriented)的三要素包括:封装、继承、多态。
      包括:面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程实现(OOP)

    • 设计模式初步
      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,依赖倒置原则)

    码云链接
    MyDoc.java

    四、练习

    • 要求:使用TDD的方式设计关实现复数类Complex
    • 伪代码:

    // 定义属性并生成getter,setter
    double RealPart;
    double ImagePart;
    // 定义构造函数
    public Complex()
    public Complex(double R,double I)
    //Override Object
    public boolean equals(Object obj)
    public String toString()
    // 定义公有方法:加减乘除
    Complex ComplexAdd(Complex a)
    Complex ComplexSub(Complex a)
    Complex ComplexMulti(Complex a)
    Complex ComplexDiv(Complex a)

    • 产品代码:

    public class Complex {
    // 定义属性并生成getter,setter
    private double r;
    private double i;
    // 定义构造函数
    public Complex(double r,double i){
    this.r=r;
    this.i=i;
    }
    public static double getRealPart(double r){
    return r;
    }
    public static double getImagePart(double i){
    return i;
    }
    //Override Object
    public boolean equals(Object obj){
    Complex complex=(Complex) obj;
    if (complex.r!=r) {
    return false;
    }
    if(complex.i!=i){
    return false;
    }
    return true;
    }
    public String toString(){
    String str=new String();
    if (i==0) str=r+"";
    else if(i<0) str=r + ""+i+"i";
    else str=r+""+"+"+i+"i";
    return str;
    }
    // 定义公有方法:加减乘除
    Complex ComplexAdd(Complex a){
    return new Complex(r+a.r,i+a.i);
    }
    Complex ComplexSub(Complex a){
    return new Complex(r-a.r,i-a.i);
    }
    Complex ComplexMulti(Complex a){
    return new Complex(ra.r-ia.i,ra.i+ia.r);
    }
    Complex ComplexDiv(Complex a){
    return new Complex((ra.r+ia.i)/(a.ra.r+a.ia.i),(ia.r-ra.i)/(a.ra.r+a.ia.i));
    }
    }

    • 测试代码:

    import junit.framework.TestCase;
    import org.junit.Test;
    public class ComplexTest extends TestCase {
    Complex a=new Complex(1,2);
    Complex b=new Complex(-2,-1);
    Complex c=new Complex(4,-2);
    Complex d=new Complex(4,-2);
    @Test
    public void testequals(){
    assertEquals(false,a.equals(b));
    assertEquals(false,b.equals(c));
    assertEquals(true,c.equals(d));
    }
    @Test
    public void testAdd(){
    assertEquals(new Complex(-1,1),a.ComplexAdd(b));
    assertEquals(new Complex(5,0),a.ComplexAdd(c));
    }
    @Test
    public void testSub(){
    assertEquals(new Complex(3,3),a.ComplexSub(b));
    assertEquals(new Complex(-3,4),a.ComplexSub(c));
    }
    @Test
    public void testMulti(){
    assertEquals(new Complex(0,-5),a.ComplexMulti(b));
    assertEquals(new Complex(8,6),a.ComplexMulti(c));
    }
    @Test
    public void testDiv(){
    assertEquals(new Complex(0,0.5),a.ComplexDiv(c));
    assertEquals(new Complex(-0.3,-0.4),b.ComplexDiv(c));
    }
    }

    码云链接
    Complex.java
    ComplexTest.java

    五、实验感想

    这次的实验比之前的难度都有所提升,主要是学习了有关IDEA中单元测试工具JUnit来辅助进行TDD的主要知识点,让我们了解并学习了三种代码:伪代码产品代码测试代码。让我们的编写程序的理念进行了提升,同时也学到了新的代码编写和测试的方法,很有意义。

    实验中遇到的问题

    • 在使用Junit的时候,import junit.framework.TestCase; 中的Junit 显示红色

    提示是程序包org.junti不存在,后来通过百度查找解决了这个问题

    • @Test 是红色的
      在老师的博客中有解决方法

    直接File 中点击Project Structure ,然后找到Modules 里的Dependencies 添加junit.jar

    其中对于junit.jar 的地址查询可以用Everything软件快捷查到

    PSP(Personal Software Process)时间


    步骤 耗时 百分比
    需求分析 40min 20%
    设计 60min 30%
    代码实现 70min 30%
    测试 20min 10%
    分析总结 20min 10%

  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/zhuyue-study/p/8848024.html
Copyright © 2011-2022 走看看