20145210 实验三 实验报告

实验三 敏捷开发与XP实践

实验内容

  1. XP基础

  2. XP核心实践

  3. 相关工具

实验步骤

(一)敏捷开发与XP

1.敏捷开发

敏捷开发(Agile Development)是一种以人为核心、迭代、循序渐进的开发方法。“敏捷流程”是一系列价值观和方法论的集合。

2.极限编程

极限编程(eXtreme Programming,XP)是 是一种全新而快捷的软件开发方法:

(1)XP是以开发符合客户需要的软件为目标而产生的一种方法论

(2)XP是一种以实践为基础的软件工程过程和思想

(3)XP认为代码质量的重要程度超出人们一般所认为的程度

(4)XP特别适合于小型的有责任心的、自觉自励的团队开发需求不确定或者迅速变化的软件

3.XP准则:

(1)沟通 :XP认为项目成员之间的沟通是项目成功的关键,并把沟通看作项目中间协调与合作的主要推动因素。

(2)简单 :XP假定未来不能可靠地预测,在现在考虑它从经济上是不明智的,所以不应该过多考虑未来的问题而是应该集中力量解决燃眉之急。

(3)反馈 :XP认为系统本身及其代码是报告系统开发进度和状态的可靠依据。系统开发状态的反馈可以作为一种确定系统开发进度和决定系统下一步开发方向的手段。

(4)勇气:代表了XP认为人是软件开发中最重要的一个方面的观点。在一个软件产品的开发中人的参与贯穿其整个生命周期,是人的勇气来排除困境,让团队把局部的最优抛之脑后,达到更重大的目标。表明了XP对“人让项目取得成功”的基本信任态度。

4.一项实践在XP环境中成功使用的依据通过XP的法则呈现,包括:快速反馈、假设简单性、递增更改、提倡更改、优质工作。

5.XP软件开发的基石:编码、测试、倾听、设计。

6.项目成员用户成功执行XP活动的技术通过XP实践来呈现,包括编程、团队、过程相关的12条实践,我们关注其中的编码标准,结对编程,代码集体所有,测试,重构等实践:

(二)编码标准

1.编程标准:

具有说明性的名字、清晰的表达式、直截了当的控制流、可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性,例:

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

该程序没有最基本的缩进,让人读起来很费劲,在IDEA里可以很好地解决这个问题:

2.Java中的一般的命名规则

(1)要使命名有一定意义

(2)包、类、变量用名词

(3)方法名用动宾

(4)包名全部小写,如:io,awt

(5)类名第一个字母要大写,如:HelloWorldApp

(6)变量名第一个字母要小写,如:userName

(7)方法名第一个字母要小写:setName

3.代码标准

(三)结对编程

1.结对编程的角色

(1)驾驶员(Driver)是控制键盘输入的人。

(2)领航员(Navigator)起到领航、提醒的作用。

2.如何更好地实现结对编程

(1)驾驶员:写设计文档,进行编码和单元测试等XP开发流程。

(2)领航员:审阅驾驶员的文档、驾驶员对编码等开发流程的执行;考虑单元测试的覆盖率;思考是否需要和如何重构;帮助驾驶员解决具体的技术问题。

(3)驾驶员和领航员不断轮换角色,不要连续工作超过一小时,每工作一小时休息15分钟。领航员要控制时间。

(4)主动参与。任何一个任务都首先是两个人的责任,也是所有人的责任。

(5)只有水平上的差距,没有级别上的差异。

(四)版本控制

1.版本控制的好处

(1)版本控制提供项目级的 undo(撤销)功能:没有什么事情是终结版本,任何错误必须很容易回滚。

(2)版本控制允许多人在同一代码上工作,只要遵守一定的控制原则就行。

(3)版本控制系统保存了过去所作的修改的历史记录。

(4)版本控制系统支持在主线上开发的同时发布多个软件版本。

(5)版本控制也是项目级的时间机器,你可以选择任何一个时间, 精确地查看项目在当时的情况。

2.开通我的代码库:http://git.shiyanlou.com/20145210

3.学习如何将代码提交到代码库:

$ cd /home/shiyanlou/Code/shiyanlou_cs212
# 修改代码文件
# 添加修改文件
$ git add 所有修改的文件
# 提交到环境中本地代码仓库
$ git commit -m '本次修改的描述'
# push到git.shiyanlou.com,无需输入密码
$ git push

4.实际操作:

首先进入Code目录,你会发现有了shiyanlou_cs212目录,进入shiyanlou_cs212,创建HelloWorld目录,并创建HelloWorld.java文件,如下图所示:

编辑HelloWorld.java文件:

往代码库提交的代码一定编译、运行、测试都没有问题的代码,上面测试代码没有问题了,可以提交了:

Git log HelloWorld查看记录:

(五)重构

  1. 概念

重构(Refactor),就是在不改变软件外部行为的基础上,改变软件内部的结构,使其更加易于阅读、易于维护和易于变更。

  1. eclipse中Refactor

重新命名:Rename

封装成员变量:Encapsulate Field...

抽象方法:Extract Method...

重构前:

重构后:

3.实用的方法

  1. 完整的重构流程包括:

从版本控制系统代码库中Check out code→读懂代码(包括测试代码)→发现bad smell→Refactoring→运行所有的Unit Tests→往代码库中Check in code

(六)实践项目

1.结对伙伴blog网址:http://home.cnblogs.com/u/xzh20145231/

2.代码:

•控制程序ControlSnake:


import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
import java.util.Random;

@SuppressWarnings("serial")
public class ControlSnake extends JPanel implements ActionListener {
	Random rand;

	ArrayList<Point> list, listBody;

	String str, str1;

	static boolean key;

	int x, y, dx, dy, fx, fy, flag;

	int snakeBody;

	int speed;

	public ControlSnake() {
		snakeBody = 1;

		str = "上下左右方向键控制 P键暂停...";
		str1 = "现在的长度为:" + snakeBody;
		key = true;
		flag = 1;

		speed = 700;
		rand = new Random();
		list = new ArrayList<Point>();
		listBody = new ArrayList<Point>();

		x = 5;
		y = 5;
		list.add(new Point(x, y));
		listBody.add(list.get(0));

		dx = 10;
		dy = 0;

		fx = rand.nextInt(30) * 10 + 5;// 2
		fy = rand.nextInt(30) * 10 + 5;// 2

		setBackground(Color.WHITE);
		setSize(new Dimension(318, 380));

		final Timer time = new Timer(speed, this);
		time.start();

		addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == 37) {
					dx = -10;
					dy = 0;
				} else if (e.getKeyCode() == 38) {
					dx = 0;
					dy = -10;
				} else if (e.getKeyCode() == 39) {
					dx = 10;
					dy = 0;
				} else if (e.getKeyCode() == 40) {
					dx = 0;
					dy = 10;
				} else if (e.getKeyCode() == 80) {
					if (flag % 2 == 1) {
						time.stop();
					}
					if (flag % 2 == 0) {
						time.start();
					}
					flag++;
				}
			}
		});

	}

	public void paint(Graphics g) {
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, 400, 400);
		g.setColor(Color.DARK_GRAY);
		g.drawLine(3, 3, 305, 3);
		g.drawLine(3, 3, 3, 305);
		g.drawLine(305, 3, 305, 305);
		g.drawLine(3, 305, 305, 305);
		g.setColor(Color.PINK);

		for (int i = 0; i < listBody.size(); i++) {
			g.fillRect(listBody.get(i).x, listBody.get(i).y, 9, 9);
		}
		g.fillRect(x, y, 9, 9);
		g.setColor(Color.ORANGE);
		g.fillRect(fx, fy, 9, 9);

		g.setColor(Color.DARK_GRAY);
		str1 = "现在的长度为:" + snakeBody;
		g.drawString(str, 10, 320);
		g.drawString(str1, 10, 335);
	}

	public void actionPerformed(ActionEvent e) {
		x += dx;
		y += dy;
		if (makeOut() == false) {
			JOptionPane.showMessageDialog(null, "重新开始......");

			speed = 700;

			snakeBody = 1;

			x = 5;
			y = 5;

			list.clear();
			list.add(new Point(x, y));
			listBody.clear();
			listBody.add(list.get(0));

			dx = 10;
			dy = 0;

		}
		addPoint(x, y);
		if (x == fx && y == fy) {
			speed = (int) (speed * 0.8);// 速度增加参数
			if (speed < 200) {
				speed = 100;
			}
			fx = rand.nextInt(30) * 10 + 5;// 2
			fy = rand.nextInt(30) * 10 + 5;// 2
			snakeBody++;// 2
		} // 2
		repaint();
	}

	public void addPoint(int xx, int yy) {
		// 动态的记录最新发生的50步以内的移动过的坐标
		// 并画出最新的snakeBody
		if (list.size() < 100) {// 蛇身长度最长为100
			list.add(new Point(xx, yy));
		} else {
			list.remove(0);
			list.add(new Point(xx, yy));
		}
		if (snakeBody == 1) {
			listBody.remove(0);
			listBody.add(0, list.get(list.size() - 1));
		} else {
			listBody.clear();
			if (list.size() < snakeBody) {
				for (int i = list.size() - 1; i > 0; i--) {
					listBody.add(list.get(i));
				}
			} else {
				for (int i = list.size() - 1; listBody.size() < snakeBody; i--) {
					listBody.add(list.get(i));
				}
			}
		}
	}

	public boolean makeOut() {
		if ((x < 3 || y < 3) || (x > 305 || y > 305)) {
			return false;
		}
		for (int i = 0; i < listBody.size() - 1; i++) {
			for (int j = i + 1; j < listBody.size(); j++) {
				if (listBody.get(i).equals(listBody.get(j))) {
					return false;
				}
			}
		}
		return true;
	}
}

•用户操作界面程序MainClass:

import java.awt.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class MainClass extends JFrame {
	ControlSnake control;

	Toolkit kit;

	Dimension dimen;

	public static void main(String[] args) {
		new MainClass("my snake");
	}

	public MainClass(String s) {
		super(s);
		control = new ControlSnake();
		control.setFocusable(true);
		kit = Toolkit.getDefaultToolkit();
		dimen = kit.getScreenSize();

		add(control);
		setLayout(new BorderLayout());
		setLocation(dimen.width / 3, dimen.height / 3);// dimen.width/3,dimen.height/3
		setSize(FWIDTH, FHEIGHT);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setResizable(false);
		setVisible(true);
	}

	public static final int FWIDTH = 315;

	public static final int FHEIGHT = 380;
}

3.运行结果:

4.PSP时间:

原文地址:https://www.cnblogs.com/20145210ysy/p/5428940.html