• # 20155219实验二 Java面向对象程序设计


    20155219实验二 Java面向对象程序设计

    一、实验内容

    1.初步掌握单元测试和TDD

    2.理解并掌握面向对象三要素:封装、继承、多态

    3.初步掌握UML建模

    4.熟悉S.O.L.I.D原则

    5.了解设计模式

    二、实验步骤

    (一)单元测试

    (1) 三种代码

    1.伪代码:以简洁的自然语言表明设计步骤;伪代码是产品代码最自然的、最好的注释。

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

    2.产品代码:用以实现特定功能的程序或机器语言。

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

    3.测试代码:用以对产品代码进行测试的代码。

    • 测试一:选取某一合法输入值进行测试
    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!");
    }
    }
    

    测试结果如下
    image

    • 测试二:全面覆盖各等级段
    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!");
    }
    }
    

    运行结果如下:
    image

    • 测试三:异常情况测试
    public class MyUtilTest {
    public static void main(String[] args) {
        //测试出错情况
        if(MyUtil.percentage2fivegrade(-10) != "错误")
            System.out.println("test failed 1!");
        else if(MyUtil.percentage2fivegrade(115) != "错误")
            System.out.println("test failed 2!");
        else 
            System.out.println("test passed!");
    }
    }
    

    运行结果如下:image
    出现此错误的 原因是判断不及格时没有要求成绩大于零,因此需要增加对负分的判断:

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

    之后再次运行程序:image
    程序通过编译正确运行。

    • 测试四:测试分段结点
      我们对输入为“0,60,70,80,90,100”这些边界情况进行测试的代码如下:
    public class MyUtilTest {
        public static void main(String[] args) {
            //测试边界情况
            if(MyUtil.percentage2fivegrade(0) != "不及格")
                System.out.println("test failed 1!");
            else if(MyUtil.percentage2fivegrade(60) != "及格")
                System.out.println("test failed 2!");
            else if(MyUtil.percentage2fivegrade(70) != "中等")
                System.out.println("test failed 3!");
            else if(MyUtil.percentage2fivegrade(80) != "良好")
                System.out.println("test failed 4!");
            else if(MyUtil.percentage2fivegrade(90) != "优秀")
                System.out.println("test failed 5!");
            else if(MyUtil.percentage2fivegrade(100) != "优秀")
                System.out.println("test failed 6!");
            else 
                System.out.println("test passed!"); 
        }
    

    TDD研究方式

    TDD的一般步骤如下:

    明确当前要完成的功能,记录成一个测试列表。

    快速完成编写针对此功能的测试用例

    测试代码编译不通过(没产品代码呢)

    编写产品代码

    测试通过

    对代码进行重构,并保证测试通过(重构下次实验练习)

    循环完成所有功能的开发

    以 TDD的方式研究学习StringBuffer

    • 源代码如下:
    public class StringBufferDemo {
        public static String append1(StringBuffer a,String b)
        {
            return a.append(b).toString();
        }
        public  static char charAt1(StringBuffer a,int i)
        {
            return a.charAt(i);
        }
        public  static int capacity1(StringBuffer a)
        {
            return a.capacity();
        }
        public static int indexof(StringBuffer a,String b)//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
        {
            return a.indexOf(b);
        }
        public static int length1(StringBuffer a)
        {
            return a.length();
        }
    }
    
    
    • 测试代码如下:
    import junit.framework.TestResult;
    import org.junit.Test;
    import junit.framework.TestCase;
    public class StringBufferDemoTest extends TestCase {
        StringBuffer buffer = new StringBuffer(20);
        @Test
        public void testNormal() {
            assertEquals("String",StringBufferDemo.append1(buffer,"String"));
            assertEquals('r',StringBufferDemo.charAt1(buffer,2));
            assertEquals(20,StringBufferDemo.capacity1(buffer));
            assertEquals(1,StringBufferDemo.indexof(buffer,"tring"));
            assertEquals(6,StringBufferDemo.length1(buffer));
        }
    }
    

    Java面向对象程序设计

    • 对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式。
    • 让系统支持Short类,并在MyDoc类中添加测试代码表明添加正确。

    代码如下所示:

    import java.lang.*;
    // Server Classes
    abstract class Data {
        abstract public void DisplayValue();
    }
    class Integer extends  Data {
        int value;
        Integer() {
            value=100;
        }
        public void DisplayValue(){
            System.out.println (value);
        }
    }
    class Short extends Data{
        short  value;
        Short()
        {
            value=100;
        }
        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();
        }
    }
    class ShortFactory extends Factory{
        public Data CreateDataObject()
        {
            return new Short();
        }
    }
    //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 ShortFactory());
            d.DisplayData();
        }
    }
    

    其中包含了老师给的支持Integer()类,和字节编写的支持short()类。
    运行结果如下图:image

    练习

    使用TDD的方式设计关实现复数类Complex

    1.伪代码:

    Complex类要输出实部,输出虚部,并按照a+bi的形式输出复数。
    Complex类中有两个变量,实部RealPart和虚部ImaginePart;
    
    方法:
    getRealPart(int RealPart);返回实部
    getImaginePart(int ImaginePart);返回虚部
    add(Complex c);实现复数相加
    minus(Complex c);实现复数相减
    multiply(Complex c);实现复数相乘
    toString(int RealPart,int ImaginePart);将复数输出成a+bi的格式。
    

    最终代码:

    public class MyComplex {
        private double m;
        private double n;
        public double getm(double m)
        {
            return m;
        }
        public double getn(double n)
        {
            return n;
        }
        public void setm(double m)
        {
            this.m=m;
        }
        public void setn(double n)
        {
            this.n=n;
        }
        public MyComplex(double m, double n) {
            this.m = m;
            this.n = n;
        }
        public MyComplex add(MyComplex c) {
            return new MyComplex(m + c.m, n + c.n);
        }
        public MyComplex minus(MyComplex c) {
            return new MyComplex(m - c.m, n - c.n);
        }
        public MyComplex multiply(MyComplex c) {
            return new MyComplex(m * c.m - n * c.n, m * c.n + n * c.m);
        }
        public MyComplex  ComplexDiv(MyComplex c)
        {
            return new MyComplex((m*c.m+n*c.n)/((c.m*c.m)*(c.n*c.n)),(n*c.m-m*c.n)/((c.m*c.m)*(c.n*c.n)));
        }
        public String toString() {
            String str = new String();
            if (this.n>=0)
            {
                str=m+"+"+n+"i";
            }
            else str=m+"-"+(-n)+"i";
            return str;
        }
        public boolean equals(MyComplex c)
        {
            if(this.m==c.m&&this.n==c.n)
                return true;
            else
                return false;
        }
    }
    

    测试代码:

    public class MyComplexTest extends TestCase {
        MyComplex a = new MyComplex(1, 2);
        MyComplex b = new MyComplex(1, -4);
        MyComplex c = new MyComplex(19, 0);
        MyComplex d = new MyComplex(0, -3);
        MyComplex e = new MyComplex(1, 0);
        MyComplex f = new MyComplex(1, 0);
        @Test
        public void testadd()
        {
            assertEquals("2.0-2.0i",a.add(b).toString());
            assertEquals("1.0-1.0i",a.add(d).toString());
        }
        @Test
        public void testminus()
        {
            assertEquals("0.0+6.0i", a.minus(b).toString());
            assertEquals("-18.0+2.0i", a.minus(c).toString());
        }
        @Test
        public void testmultiply()
        {
            assertEquals("9.0-2.0i", a.multiply(b).toString());
            assertEquals("19.0+38.0i", a.multiply(c).toString());
        }
        @Test
        public void testComplexDiv()
        {
            assertEquals("-0.4375+0.375i",a.ComplexDiv(b).toString());
            assertEquals("1.1875+4.75i",c.ComplexDiv(b).toString());
        }
        @Test
        public void testequals()
        {
            assertEquals(false,a.equals(b));
            assertEquals(true,e.equals(f));
        }
    }
    

    利用StarUML软件进行UML建模

    image将生成代码稍作修改,可以得到输出如下:image

    实验总结与体会

    这一次的实验我学会了如何使用单元测试,单元测试不仅能保证项目进度还能优化我们的设计,我们可以从测试中发现一些设计时所遗漏的问题,从而改善自己的代码,测试说到底其实也就是一个发现BUG的过程,我们没有必要对一些能够肯定正确的答案进行测试,相反,我们要尽可能把那些觉得容易出错的答案进行测试,这样也就能够更快的发现BUG的所在。

    PSP(Personal Software Process)时间

    步骤 耗时 百分比
    需求分析 15min 12.5%
    设计 15min 12.5%
    代码实现 60min 50.0%
    测试 15min 12.5%
    分析总结 15min 12.5%

    参考资料

  • 相关阅读:
    垃圾回收app冲击(一)
    本篇看似是一篇拍马屁的博客!但是真情实感!
    搜索建议
    冲击团队项目需求分析
    疫情分析冲击(五)
    疫情分析冲击(四)
    疫情分析冲击(三)
    疫情分析冲击(二)
    垃圾分类网站
    Android学习——singleInstance
  • 原文地址:https://www.cnblogs.com/paypay/p/6746321.html
Copyright © 2020-2023  润新知