2016-2017-2 20155322 实验三 敏捷开发与XP实践

2016-2017-2 20155322 实验三 敏捷开发与XP实践

实验内容

  1. XP基础
  2. XP核心实践
  3. 相关工具

实验知识点

  1. 敏捷开发(Agile Development)是一种以人为核心、迭代、循序渐进的开发方法。“敏捷流程”是一系列价值观和方法论的集合。从2001年开始,一些软件界的专家开始倡导“敏捷”的价值观和流程,他们肯定了流行做法的价值,但是强调敏捷的做法更能带来价值。

  2. 极限编程(eXtreme Programming,XP)是 是一种全新而快捷的软件开发方法。XP团队使用现场客户、特殊计划方法和持续测试来提供快速的反馈和全面的交流:

  • XP是以开发符合客户需要的软件为目标而产生的一种方法论
  • XP是一种以实践为基础的软件工程过程和思想
  • XP认为代码质量的重要程度超出人们一般所认为的程度
  • XP特别适合于小型的有责任心的、自觉自励的团队开发需求不确定或者迅速变化的软件
  • XP软件开发是什么样的通过 XP准则来表达:
  • 沟通 :XP认为项目成员之间的沟通是项目成功的关键,并把沟通看作项目中间协调与合作的主要推动因素。
  • 简单 :XP假定未来不能可靠地预测,在现在考虑它从经济上是不明智的,所以不应该过多考虑未来的问题而是应该集中力量解决燃眉之急。
  • 反馈 :XP认为系统本身及其代码是报告系统开发进度和状态的可靠依据。系统开发状态的反馈可以作为一种确定系统开发进度和决定系统下一步开发方向的手段。
  • 勇气:代表了XP认为人是软件开发中最重要的一个方面的观点。在一个软件产品的开发中人的参与贯穿其整个生命周期,是人的勇气来排除困境,让团队把局部的最优抛之脑后,达到更重大的目标。表明了XP对“人让项目取得成功”的基本信任态度。
  1. 编写代码一个重要的认识是“程序大多时候是给人看的”,编程标准使代码更容易阅读和理解,甚至可以保证其中的错误更少。编程标准包含:具有说明性的名字、清晰的表达式、直截了当的控制流、可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性。

实验步骤

实践一:Code菜单体验

  • 在IDEA中使用工具(Code->Reformate Code)把下面代码重新格式化,再研究一下Code菜单,找出一项让自己感觉最好用的功能。提交截图,加上自己学号水印。
public class CodeStandard {
public static void main(String [] args){
StringBuffer buffer = new StringBuffer();
buffer.append('S');
buffer.append("tringBuffer");
System.out.println(buffer.charAt(1));
System.out.println(buffer.capacity());
System.out.println(buffer.indexOf("tring"));
System.out.println("buffer = " + buffer.toString());
if(buffer.capacity()<20)
buffer.append("1234567");
for(int i=0; i<buffer.length();i++)
System.out.println(buffer.charAt(i));
}
}

我在菜单中找到一项比较好的功能叫optimize imports主要功能是删除无用和错误的import。

实践二:测试同伴Complex代码(加入不少于三个JUnit单元测试用例)

我找到了我同伴20155302的码云项目,找到了他的complex文件:


/**
 * Created by 20155302 on 2017/4/27.
 */

public class Complex1{
    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;
    }
}

根据他的代码我写出如下测试:

/**
 * Created by 20155322 on 2017/5/4.
 */
import junit.framework.TestCase;
import org.junit.Test;

    public class ComplexTest extends TestCase {
        Complex c1 = new Complex(0, 3);
        Complex c2 = new Complex(-1, -1);
        Complex c3 = new Complex(2,1);
        @Test
        public void testgetRealPart() throws Exception {
            assertEquals(-1.0, Complex.getRealPart(-1.0));
            assertEquals(5.0, Complex.getRealPart(5.0));
            assertEquals(0.0, Complex.getRealPart(0.0));
        }
        @Test
        public void testgetImagePart() throws Exception {
            assertEquals(-1.0, Complex.getImagePart(-1.0));
            assertEquals(5.0, Complex.getImagePart(5.0));
            assertEquals(0.0, Complex.getImagePart(0.0));
        }
        @Test
        public void testgetPart() throws Exception {
            assertEquals(4.0, Complex.getImagePart(4.0));
            assertEquals(5.0, Complex.getImagePart(5.0));
            assertEquals(1.0, Complex.getImagePart(1.0));
        }
        /*
        @Test
        public void testComplexAdd() throws Exception {
            assertEquals("-1.0+2.0i", c1.ComplexAdd(c2).toString());
            assertEquals("2.0+4.0i", c1.ComplexAdd(c3).toString());
            assertEquals("1.0", c2.ComplexAdd(c3).toString());
        }
        @Test
        public void testComplexSub() throws Exception {
            assertEquals("1.0+4.0i", c1.ComplexSub(c2).toString());
            assertEquals("-2.0+2.0i", c1.ComplexSub(c3).toString());
            assertEquals("-3.0 -2.0i", c2.ComplexSub(c3).toString());
        }
        @Test
        public void testComplexMulti() throws Exception {
            assertEquals("3.0 -3.0i", c1.ComplexMulti(c2).toString());
            assertEquals("-3.0+6.0i", c1.ComplexMulti(c3).toString());
            assertEquals("-1.0 -3.0i", c2.ComplexMulti(c3).toString());
        }
        @Test
        public void testComplexComplexDiv() throws Exception {
            assertEquals("-1.5 -1.5i", c1.ComplexDiv(c2).toString());
            assertEquals("1.2+0.6i", c1.ComplexDiv(c3).toString());
            assertEquals("-0.6 -0.6i", c2.ComplexDiv(c3).toString());
            }
            */

    }

测试结果如下:

实践三:重构练习

根据老师给的教学我对搭档的代码进行了重构练习,首先我找到的代码如下:

/**
* Created by dell on 2017/4/19.
*/
public class ClassTest1 {
   public static void main(String [] args) {
       //定义一个数组,比如
       int arr[] = {1,2,3,4,5,6,7,8};
       //打印原始数组的值
       for(int a:arr){
           System.out.print(a + " ");
       }
       System.out.println();

       // 添加代码删除上面数组中的5
       for(int a = 4; a <= (arr.length-2); a++){
           arr[a] = arr[a+1];
       }
       arr[7] = 0;
       //打印出 1 2 3 4 6 7 8 0
       for(int a:arr){
           System.out.print(a + " ");
       }
       System.out.println();

       // 添加代码再在4后面5
       for(int a = (arr.length-2); a >= 4; a--){
           arr[a+1] = arr[a];
       }
       arr[4] = 5;
       //打印出 1 2 3 4 5 6 7 8
       for(int a:arr){
           System.out.print(a + " ");
       }
       System.out.println();
   }
}

然后,我通过refactor->Extract->Method来实现对部分变量的封装,也同时对于重复的部分循环语句进行了封装,结果如下:

/**
 * Created by mac on 2017/5/4.
 */
public class RefactorTest {

    @Override
    public String toString() {
        return "RefactorTest{}";
    }

    public static void main(String [] args) {
        //定义一个数组,比如
        int arr[] = {1,2,3,4,5,6,7,8};
        //打印原始数组的值
        PrintOut(arr);
        PrintLn();

        // 添加代码删除上面数组中的5
        for(int a = 4; a <= (arr.length-2); a++){
            arr[a] = arr[a+1];
        }
        arr[7] = 0;
        //打印出 1 2 3 4 6 7 8 0
        PrintOut(arr);
        PrintLn();

        // 添加代码再在4后面5
        for(int a = (arr.length-2); a >= 4; a--){
            arr[a+1] = arr[a];
        }
        arr[4] = 5;
        //打印出 1 2 3 4 5 6 7 8
        PrintOut(arr);
        PrintLn();
    }

    private static void PrintLn() {
        System.out.println();
    }

    private static void PrintOut(int[] arr) {
        for(int a:arr){
            System.out.print(a + " ");
        }
    }
}

实践四:Java密码学相关内容的学习

根据老师提供的Java密码学算法,我和结对伙伴对DES算法进行了详细的了解和学习。针对老师提供的Java代码,我们根据实践三中所学到的重构知识对老师的源码进行了重构,下面是老师的解密算法sDEC:

import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class SDec{
   public static void main(String args[]) throws Exception{
        // 获取密文
        FileInputStream f=new FileInputStream("SEnc.dat");
        int num=f.available();
        byte[ ] ctext=new byte[num];          
        f.read(ctext);
        // 获取密钥
        FileInputStream  f2=new FileInputStream("keykb1.dat");
        int num2=f2.available();
        byte[ ] keykb=new byte[num2];          
        f2.read(keykb);
        SecretKeySpec k=new  SecretKeySpec(keykb,"DESede");
        // 解密
        Cipher cp=Cipher.getInstance("DESede");
        cp.init(Cipher.DECRYPT_MODE, k);
        byte []ptext=cp.doFinal(ctext);
         // 显示明文
        String p=new String(ptext,"UTF8");
        System.out.println(p);
   }
}

我们的重构如下:

/**
 * Created by mac on 2017/5/4.
 */

import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class SDec {
    public static void main(String args[]) throws Exception {
        // 获取密文
        FileInputStream f = getFileInputStream("SEnc.dat");
        int num = getAvailable(f);
        byte[] ctext = getBytes(num);
        f.read(ctext);
        // 获取密钥
        FileInputStream f2 = getFileInputStream("keykb1.dat");
        int num2 = getAvailable(f2);
        byte[] keykb = getBytes(num2);
        f2.read(keykb);
        SecretKeySpec k = new SecretKeySpec(keykb, "DESede");
        // 解密
        Cipher cp = Cipher.getInstance("DESede");
        cp.init(Cipher.DECRYPT_MODE, k);
        byte[] ptext = getBytes(ctext, cp);
        // 显示明文
        String p = getUtf8(ptext);
        System.out.println(p);
    }

    private static byte[] getBytes(byte[] ctext, Cipher cp) throws IllegalBlockSizeException, BadPaddingException {
        return cp.doFinal(ctext);
    }

    private static String getUtf8(byte[] ptext) throws UnsupportedEncodingException {
        return new String(ptext, "UTF8");
    }

    private static byte[] getBytes(int num) {
        return new byte[num];
    }

    private static int getAvailable(FileInputStream f) throws IOException {
        return f.available();
    }

    private static FileInputStream getFileInputStream(String name) throws FileNotFoundException {
        return new FileInputStream(name);
    }
}

实验心得与体会:

本次实验老师给我们介绍了什么叫敏捷开发与XP实践,结合上一次提到的测试驱动开发,感觉知识点的衔接很流畅,有种环环相扣的感觉,对于理解非常有帮助。

本次实验还有一个好处就是,让我们了解了通过Java来实现密码学算法,由于Java庞大的通用API积累,使用起来确实比C语言这种面向过程的语言方便了不少。

PSP(Personal Software Process)时间

步骤 耗时(min) 百分比(%)
需求分析 30 18
设计 50 28
代码实现 30 18
测试 30 18
分析总结 30 18

参考资料

posted @ 2017-05-07 21:13  blackay03  阅读(181)  评论(0编辑  收藏  举报
Live2D
*/