实验三 敏捷开发与XP实践
北京电子科技学院(BESTI)
实 验 报 告
课程:Java程序设计 班级:1351 姓名:黄君如 学号:20135117
成绩: 指导教师:娄嘉鹏 实验日期:2015.5.30
实验密级: 预习程度: 实验时间:16:30-18:30
仪器组次: 必修/选修:选修 实验序号:3
实验名称: 敏捷开发与XP实验
实验目的与要求:1.没有Linux基础的同学建议先学习《Linux基础入门(新版)》《Vim编辑器》课程
2.完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获、教训等)
3. 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。
实验仪器:
名称 |
型号 |
数量 |
PC |
MacBookAir |
1 |
一、实验内容
(一)敏捷开发与XP
1、常见的开发流程有:
- RUP(Rational Unified Process)
- PSP(Personal Software Process )
- TSP(Team Software Process )
- Agile Process
- ……
2、敏捷开发(Agile Development)是一种以人为核心、迭代、循序渐进的开发方法。
3、极限编程(eXtreme Programming,XP)是_是一种全新而快捷的软件开发方法。
- XP是以开发符合客户需要的软件为目标而产生的一种方法论
- XP是一种以实践为基础的软件工程过程和思想
- XP认为代码质量的重要程度超出人们一般所认为的程度
- XP特别适合于小型的有责任心的、自觉自励的团队开发需求不确定或者迅速变化的软件
XP的法则包括:快速反馈、假设简单性、递增更改、提倡更改、优质工作。
XP软件开发的基石是XP的活动,包括:编码、测试、倾听、设计。
项目成员用户成功执行XP活动的技术通过XP实践来呈现,包括编程、团队、过程相关的12条实践。
(二)编码标准
1、编程标准使代码更容易阅读和理解,甚至可以保证其中的错误更少。
2、编程标准包含:具有说明性的名字、清晰的表达式、直截了当的控制流、可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性。
3、在Ecipse中让程序按规范缩紧:单击source->Format
4、命名规则
- 要体现各自的含义
- 包、类、变量用名词
- 方法名用动宾
- 包名全部小写,如:io,awt
- 类名第一个字母要大写,如:HelloWorldApp
- 变量名第一个字母要小写,如:userName
- 方法名第一个字母要小写:setName
- ...
(三)结对编程
结对编程中有两个角色:
- 驾驶员(Driver)是控制键盘输入的人。
- 领航员(Navigator)起到领航、提醒的作用。
(四)版本控制
- 版本控制允许多人在同一代码上工作, 只要遵守一定的控制原则就行。 再也不会发生诸如一个人覆盖了另一个人编辑的代码,导致那个人的修改无效这样的情况。
- 版本控制系统保存了过去所作的修改的历史记录。如果你遭遇到一些惊讶的代码,通过版本控制系统可以很容易找出是谁干的, 修改了什么, 修改的时间, 如果幸运的话,还能找出原因。
- 版本控制系统还支持在主线上开发的同时发布多个软件版本。在软件发布的时候也不需要整个团队的停止工作,不需要冻结代码。
- 版本控制也是项目级的时间机器,你可以选择任何一个时间, 精确地查看项目在当时的情况。 这对研究非常有用, 也是重现以前某个有问题的发布版本的基础。
流行的版本控制工具有CVS,SVN,Git等。
(五)重构
1、重构(Refactor),就是在不改变软件外部行为的基础上,改变软件内部的结构,使其更加易于阅读、易于维护和易于变更 。
2、使用重构的功能来改名:单击要改的名字,选择Refactor->Rename,输入名称。
3、将鼠标移至name处,单击Refactor->Encapsulate Field,对age和id进行相同操作。
4、给Student类产生一个toString方法
5、重构的动机:
- 增加新功能;
- 原有功能有BUG;
- 改善原有程序的结构;
- 优化原有系统的性能 。
6、Bad Smell与相应的重构手法
7、完整的重构流程
1.从版本控制系统代码库中Check out code
2.读懂代码(包括测试代码)
3.发现bad smell
4.Refactoring
5.运行所有的Unit Tests
6.往代码库中Check in code
(六)实践项目
1.结对同学blog地址:http://www.cnblogs.com/lgysblog/
2. Git网址:https://git.oschina.net/huang.junru
3.实验代码如下
(1)
package Snake;
/**
*
* @author huangJunRu
*
* written 06-04
*
*/
public enum Dir {
L, U, R, D
}
(2)
package Snake;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
/**
*
* @author huangJunRu
*
* written 06-04
*
*/
public class Egg {
int row, col;
int w = Yard.BLOCK_SIZE;
int h = Yard.BLOCK_SIZE;
private static Random r = new Random();
private Color color = Color.GREEN;
public Egg(int row, int col) {
this.row = row;
this.col = col;
}
public Egg() {
this(r.nextInt(Yard.ROWS-2) + 2, r.nextInt(Yard.COLS));
}
public void reAppear() {
this.row = r.nextInt(Yard.ROWS-2) + 2;
this.col = r.nextInt(Yard.COLS);
}
public Rectangle getRect() {
return new Rectangle(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h);
}
public void draw(Graphics g) {
Color c = g.getColor();
g.setColor(color);
g.fillOval(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h);
g.setColor(c);
if(color == Color.GREEN) color = Color.RED;
else color = Color.GREEN;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
}
(3)
package Snake;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
/**
*
* @author huangJunRu
*
* written 06-04
*
*/
public class Snake {
private Node head = null;
private Node tail = null;
private int size = 0;
private Node n = new Node(20, 30, Dir.L);
private Yard y;
public Snake(Yard y) {
head = n;
tail = n;
size = 1;
this.y = y;
}
public void addToTail() {
Node node = null;
switch(tail.dir) {
case L :
node = new Node(tail.row, tail.col + 1, tail.dir);
break;
case U :
node = new Node(tail.row + 1, tail.col, tail.dir);
break;
case R :
node = new Node(tail.row, tail.col - 1, tail.dir);
break;
case D :
node = new Node(tail.row - 1, tail.col, tail.dir);
break;
}
tail.next = node;
node.prev = tail;
tail = node;
size ++;
}
public void addToHead() {
Node node = null;
switch(head.dir) {
case L :
node = new Node(head.row, head.col - 1, head.dir);
break;
case U :
node = new Node(head.row - 1, head.col, head.dir);
break;
case R :
node = new Node(head.row, head.col + 1, head.dir);
break;
case D :
node = new Node(head.row + 1, head.col, head.dir);
break;
}
node.next = head;
head.prev = node;
head = node;
size ++;
}
public void draw(Graphics g) {
if(size <= 0) return;
move();
for(Node n = head; n != null; n = n.next) {
n.draw(g);
}
}
private void move() {
addToHead();
deleteFromTail();
checkDead();
}
private void checkDead() {
if(head.row < 2 || head.col < 0 || head.row > Yard.ROWS || head.col > Yard.COLS) {
y.stop();
}
for(Node n = head.next; n != null; n = n.next) {
if(head.row == n.row && head.col == n.col) {
y.stop();
}
}
}
private void deleteFromTail() {
if(size == 0) return;
tail = tail.prev;
tail.next = null;
}
private class Node {
int w = Yard.BLOCK_SIZE;
int h = Yard.BLOCK_SIZE;
int row , col;
Dir dir = Dir.L;
Node next = null;
Node prev = null;
Node(int row, int col, Dir dir) {
this.row = row;
this.col = col;
this.dir = dir;
}
void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillRect(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h);
g.setColor(c);
}
}
public void eat(Egg e) {
if(this.getRect().intersects(e.getRect())) {
e.reAppear();
this.addToHead();
y.setScore(y.getScore() + 5);
}
}
private Rectangle getRect() {
return new Rectangle(Yard.BLOCK_SIZE * head.col, Yard.BLOCK_SIZE * head.row, head.w, head.h);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_LEFT :
if(head.dir != Dir.R)
head.dir = Dir.L;
break;
case KeyEvent.VK_UP :
if(head.dir != Dir.D)
head.dir = Dir.U;
break;
case KeyEvent.VK_RIGHT :
if(head.dir != Dir.L)
head.dir = Dir.R;
break;
case KeyEvent.VK_DOWN :
if(head.dir != Dir.U)
head.dir = Dir.D;
break;
}
}
}
(4)
package Snake;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
*
* @author huangJunRu
*
* written 06-04
*
*/
public class Yard extends Frame {
PaintThread paintThread = new PaintThread();
private boolean gameOver = false;
/**
* 设置游戏界面大小
*/
public static final int ROWS = 30;
public static final int COLS = 30;
public static final int BLOCK_SIZE = 15;
private Font fontGameOver = new Font("游戏结束", Font.BOLD, 50);
private int score = 0;
Snake s = new Snake(this);
Egg e = new Egg();
Image offScreenImage = null;
public void launch() {
this.setLocation(200, 200);
this.setSize(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setVisible(true);
this.addKeyListener(new KeyMonitor());
new Thread(paintThread).start();
}
public static void main(String[] args) {
new Yard().launch();
}
public void stop() {
gameOver = true;
}
@Override
public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.GRAY);
g.fillRect(0, 0, COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
g.setColor(Color.DARK_GRAY);
for(int i=1; i<ROWS; i++) {
g.drawLine(0, BLOCK_SIZE * i, COLS * BLOCK_SIZE, BLOCK_SIZE * i);
}
for(int i=1; i<COLS; i++) {
g.drawLine(BLOCK_SIZE * i, 0, BLOCK_SIZE * i, BLOCK_SIZE * ROWS);
}
g.setColor(Color.YELLOW);
g.drawString("score:" + score, 10, 60);
if(gameOver) {
g.setFont(fontGameOver);
g.drawString("游戏结束", 120, 180);
paintThread.pause();
}
g.setColor(c);
s.eat(e);
e.draw(g);
s.draw(g);
}
@Override
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
}
Graphics gOff = offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage, 0, 0, null);
}
private class PaintThread implements Runnable {
private boolean running = true;
private boolean pause = false;
public void run() {
while(running) {
if(pause) continue;
else repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void pause() {
this.pause = true;
}
public void reStart() {
this.pause = false;
s = new Snake(Yard.this);
gameOver = false;
}
public void gameOver() {
running = false;
}
}
private class KeyMonitor extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_F2) {
paintThread.reStart();
}
s.keyPressed(e);
}
}
/**
* 得到成绩
*/
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
二、总结
- 实验体会
这次实验难度总体来说较大。根据实验指导书,前面的几项任务都不太复杂,根据指导可以很容易实现,并且让我们了解了重构、还有如何快速规范化代码的格式的方法。此外我觉得最有用的就是版本控制,在同学的帮助下我创建了自己的一个git账号,使用了这个工具以后,只要每次修改代码都及时推送到本地及个人的git网址上,在日后就可以任意恢复某次修改代码之后的样子。我认为这个工具对于编程学习有十分大的帮助。最难的就是最后一个步骤,结对做一个小游戏。我和我的搭档参考了网上“贪吃蛇”的代码并一起调试运行,对代码进行解读、消化。发现其实大部分代码我们可以看得懂,但是如果要让我们自己编程却有很大难度。说明要学好java这门语言我们还有很长的一段路,一定要多加练习。
2.PSP时间
步骤 |
耗时 |
百分比 |
需求分析 |
24min |
20% |
设计 |
12min |
10% |
代码实现 |
12min |
10% |
测试 |
48min |
40% |
分析总结 |
24min |
20% |