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

实验报告封面

  • 课程:Java程序设计 班级:1652班 姓名:王杨鸿永 学号:20165231

  • 指导教师:娄嘉鹏 实验日期:2018年4月16日

  • 实验时间:13:45 - 15:25 实验序号:实验二

  • 实验名称:Java面向对象程序设计

实验内容:

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

实验知识点:
1、TDD的一般步骤如下:

  • 明确当前要完成的功能,记录成一个测试列表
  • 快速完成编写针对此功能的测试用例
  • 测试代码编译不通过(没产品代码呢)
  • 编写产品代码
  • 测试通过
  • 对代码进行重构,并保证测试通过(重构下次实验练习)
  • 循环完成所有功能的开发

2、面向对象(Object-Oriented)的三要素包括:封装、继承、多态。

3、封装就是将数据与相关行为包装在一起以实现信息就隐藏。Java中用类进行封装。

4、继承指一个类的定义可以基于另外一个已经存在的类,即子类基于父类,从而实现父类代码的重用。继承是实现软件可重用的根基,是提高软件系统的可扩展性与可维护性的主要途径。

5、面向对象三要素是“封装、继承、多态”,任何面向对象编程语言都会在语法上支持这三要素。如何借助抽象思维用好三要素特别是多态还是非常困难的,S.O.L.I.D类设计原则是一个很好的指导:

  • SRP(Single Responsibility
  • Principle,单一职责原则)
  • OCP(Open-Closed Principle,开放-封闭原则)
  • LSP(Liskov SubstitusionPrinciple,Liskov替换原则)
  • ISP(Interface Segregation Principle,接口分离原则)
  • DIP(Dependency Inversion Principle,依赖倒置原则)

实验步骤

第一个提交点

参考 http://www.cnblogs.com/rocedu/p/6371315.html#SECUNITTEST 完成单元测试的学习  
提交最后三个JUnit测试用例(正常情况,错误情况,边界情况)都通过的截图,截图上要有画图加水印,输入自己的学号  
本提交点考查JUnit会不会使用,测试用例至少要包含正常情况,错误情况,边界情况的测试  

三种代码

编程是智力活动,不是打字,编程前要把干什么、如何干想清楚才能把程序写对、写好。与目前不少同学一说编程就打开编辑器写代码不同,我希望同学们养成一个习惯,当你们想用程序解决问题时,要会写三种码:

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

伪代码:伪代码从意图层面来解决问题,是产品代码最自然的、最好的注释

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

  • 产品代码:按照伪代码的思路逐步实现程序的就是产品代码
public class MyUtil{
   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 "错误";
   }
}
  • 测试代码:为了防止Bug没发现而将产品提交给别人,可以使用测试代码测试bug。
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));
    }
    @Test
    public void testExceptions(){
        assertEquals("错误",MyUtil.percentage2fivegrade(105));
        assertEquals("错误",MyUtil.percentage2fivegrade(-55));
    }

    @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));
    }
}

我们是该“先写产品代码,然后再写测试代码,通过测试发现了一些Bugs,修改代码”,还是该“先写测试代码,然后再写产品代码,从而写出来的代码就是正确的”呢?当然先写测试代码了。这种先写``测试代码`,然后再写产品代码的开发方法叫“测试驱动开发”(TDD)。TDD的一般步骤如下:

  • 明确当前要完成的功能,记录成一个测试列表
  • 快速完成编写针对此功能的测试用例
  • 测试代码编译不通过(没产品代码呢)
  • 编写产品代码
  • 测试通过
  • 对代码进行重构,并保证测试通过(重构下次实验练习)
  • 循环完成所有功能的开发

Java中有单元测试工具JUnit来辅助进行TDD,IDEA中使用JUnit要安装插件,选择File->Setting打开设置对话框:
image
在设置对话框中选择Plugins, 单击Install JetBrains plugin...按钮打开插件安装界面:
image
在插件安装对话框的搜索中输入junit,单击JunitGenerator V2.0,单击右边绿色的Install按钮安装:
image
安装完成:
image

然后在IDEA中新建一个空的类,鼠标单击类名会出现一个灯泡状图标,单击图标或按Alt + Entert,在弹出的菜单中选择Create Test后自动生成一个test类
image
image
image

如果TestCase是红色的,需要在IDEA中的项目(模块)中加入junit.jar包,junit.jar包的位置一般在安装目录下lib文件夹中可以找到,然后在IDEA中选择菜单File->Project Structure...在弹出的对话框中选择Dependancies标签页,单击+号,选择JARs or Directories...,输入junit的文件地址。

最后run测试类,所有test通过就算是通过了.(新版本的IDEA可能没有老版本的小绿条和小红条,但是会有小绿勾和橙感叹)
image
image

测试结果:
image

第二个提交点

  • 参考 积极主动敲代码,使用JUnit学习Java (http://www.cnblogs.com/rocedu/p/4837092.html)
  • 以 TDD的方式研究学习StringBuffer
  • 提交你的单元测试用例和测试通过的截图,截图要加上学号水印
  • 测试自己会不会写JUnit测试用例

根据老师给的代码,进行对Junit的应用。

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

产品代码:

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);
    }
}

测试代码:

import junit.framework.TestCase;
import org.junit.Test;
import static org.junit.Assert.*;

public class StringBufferDemoTest extends TestCase {
    StringBuffer a = new StringBuffer("StringBuffer");
    StringBuffer b = new StringBuffer("StringBufferStringBuffer");
    StringBuffer c = new StringBuffer("StringBufferStringBufferStringBuffer");

    @Test
    public void testcharAt() throws Exception {
        assertEquals('S',a.charAt(0));
        assertEquals('B',a.charAt(6));
        assertEquals('r',a.charAt(11));
    }

    @Test
    public void testcapacity() throws Exception {
        assertEquals(28, a.capacity());
        assertEquals(40, b. capacity());
        assertEquals(52, c.capacity());
    }

    @Test
    public void testlength() throws Exception {
        assertEquals(12, a.length());
        assertEquals(24, b.length());
        assertEquals(36, c.length());
    }

    @Test
    public void testindexOf() throws Exception {
        assertEquals(0, a.indexOf("Str"));
        assertEquals(6, a.indexOf("Buf"));
        assertEquals(10,a.indexOf("er"));
    }
}

按照提交点一的步骤测试
测试截图:
image

第三个提交点

参考实验二 Java面向对象程序设计
对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式
用自己的学号%6进行取余运算,根据结果进行代码扩充 :
0:让系统支持Byte类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
1:让系统支持Short类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
2:让系统支持Boolean类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
3:让系统支持Long类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
4:让系统支持Float类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
5:让系统支持Double类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印

代码如下:测试支持short型

abstract class Data {
        abstract public void DisplayValue();
    }
    class Integer extends  Data {
        int value;
        Integer() {
            value=31;
        }
        public void DisplayValue(){
            System.out.println (value);
        }
    }
    // Pattern Classes
    abstract class Factory {
        abstract public Data CreateDataObject();
    }
    class IntFactory extends Factory {
        public Data CreateDataObject(){
            return new Integer();
        }
    }
    //Client classes
    class Document {
        Data pd;
        Document(Factory pf){
            pd = pf.CreateDataObject();
        }
        public void DisplayData(){
            pd.DisplayValue();
        }
    }
    //Test class
    public class MyDoc {
        static Document d;
        public static void main(String[] args) {
            d = new Document(new IntFactory());
            d.DisplayData();
        }
    }

测试截图:
image

第四个提交点

提交:单元测试代码和运行成功截图及码云上代码链接,截图要加上学号水印

参考http://www.cnblogs.com/rocedu/p/6736847.html

任务:以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 {
    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;
    }

    public Complex ComplexAdd(Complex c) {
        return new Complex(r + c.r, i + c.i);
    }

    public Complex ComplexSub(Complex c) {
        return new Complex(r - c.r, i - c.i);
    }

    public Complex ComplexMulti(Complex c) {
        return new Complex(r * c.r - i * c.i, r * c.i + i * c.r);
    }

    public Complex ComplexDiv(Complex c) {
        return new Complex((r * c.i + i * c.r) / (c.i * c.i + c.r * c.r), (i * c.i + r * c.r) / (c.i * c.i + c.r * c.r));
    }

    public String toString() {
        String s = " ";
        if (i > 0)
            s = r + "+" + i + "i";
        if (i == 0)
            s = r + "";
        if (i < 0)
            s = r + " " + i + "i";
        return s;
    }
}

测试代码:

import junit.framework.TestCase;
import  org.junit.Test;

public class ComplexTest extends TestCase {
  Complex a =new Complex(0,3);
  Complex b=new Complex(-1,-1);

  @Test
    public void testComplexAdd() throws Exception {
      assertEquals("-1.0+2.0i",a.ComplexAdd(b).toString());
  }

  @Test
  public void testComplexSub() throws Exception {
      assertEquals("1.0+4.0i", a.ComplexSub(b).toString());
  }

    @Test
    public void testComplexMulti() throws Exception {
        assertEquals("3.0 -3.0i", a.ComplexMulti(b).toString());
    }

    @Test
    public void testComlexDiv() throws Exception {
        assertEquals("-1.5 -1.5i", a.ComplexDiv(b).toString());
    }
}

测试结果:
image

第五个提交点

使用StarUML对实验二中的代码进行建模
更具老师提供的代码实例得出的UML图:
image

实验中第三个提交点MyDoc的UML图:
image

实验总结和体会

本次实验开始觉得很有难道,从没有接触过什么TDD,什么测试代码之类的,看了一下午的博客终于看出点名堂了,然后开始参考着手设计。伪代码 产品代码 测试代码对以后的编程设计由着极大的帮助,伪代码相当于立意提纲,测试代码检查bug,就可以设计出比较完美的程序了。

原文地址:https://www.cnblogs.com/Yhooyon/p/8847685.html