实验三 敏捷开发与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;

   }

 

}

 

二、总结

  1. 实验体会

    这次实验难度总体来说较大。根据实验指导书,前面的几项任务都不太复杂,根据指导可以很容易实现,并且让我们了解了重构、还有如何快速规范化代码的格式的方法。此外我觉得最有用的就是版本控制,在同学的帮助下我创建了自己的一个git账号,使用了这个工具以后,只要每次修改代码都及时推送到本地及个人的git网址上,在日后就可以任意恢复某次修改代码之后的样子。我认为这个工具对于编程学习有十分大的帮助。最难的就是最后一个步骤,结对做一个小游戏。我和我的搭档参考了网上“贪吃蛇”的代码并一起调试运行,对代码进行解读、消化。发现其实大部分代码我们可以看得懂,但是如果要让我们自己编程却有很大难度。说明要学好java这门语言我们还有很长的一段路,一定要多加练习。

     2.PSP时间

步骤

耗时

百分比

需求分析

24min

20%

设计

12min

10%

代码实现

12min

10%

测试

48min

40%

分析总结

24min

20%

    

posted @ 2015-06-04 20:35  20135117黄君如  阅读(199)  评论(0编辑  收藏  举报