结对编译与TDD结合的方式是:首先,第一个人写一个失败的单元测试,第二个人写代码让这个单元测试通过,然后第二个人再写一个失败的单元测试,交给第一个人,他再写代码让其通过...依次交替,直至完成。写代码之前或完成编码单元测试通过后都可对代码进行重构。
训练题目:机器人探查火星
RobotTest.java
package com.study.robot.test; import org.junit.Assert; import org.junit.Test; import com.study.robot.ControlCenter; import com.study.robot.Position; import com.study.robot.Robot; public class RobotTest { @Test public void test_turn_left() { Position position = new Position(0,"N"); Robot robot = new Robot(position); robot.command("L"); Position resultPosition = robot.position; Assert.assertEquals(new Position(0,"W"),resultPosition); } @Test public void test_turn_right() { Position position = new Position(0,"N"); Robot robot = new Robot(position); robot.command("R"); Position resultPosition = robot.position; Assert.assertEquals(new Position(0,"E"),resultPosition); } @Test public void test_when_given_0_0_S_position_turn_right() { Position position = new Position(0,"S"); Robot robot = new Robot(position); robot.command("R"); Position resultPosition = robot.position; Assert.assertEquals(new Position(0,resultPosition); } @Test public void test_when_given_0_0_S_position_and_turn_twice() { Position position = new Position(0,"S"); Robot robot = new Robot(position); robot.command("R"); robot.command("R"); Position resultPosition = robot.position; Assert.assertEquals(new Position(0,"N"),resultPosition); } @Test public void test_when_given_0_0_N_move_and_no_turn() { Position position = new Position(0,"N"); Robot robot = new Robot(position); robot.command("M"); Position resultPosition = robot.position; Assert.assertEquals(new Position(0,1,resultPosition); } @Test public void test_when_given_0_0_E_move_and_no_turn() { Position position = new Position(0,"E"); Robot robot = new Robot(position); robot.command("M"); Position resultPosition = robot.position; Assert.assertEquals(new Position(1,resultPosition); } @Test public void test_when_given_0_0_S_move_then_return_0_0_S() { Position position = new Position(0,"S"); Robot robot = new Robot(position); robot.command("M"); Position resultPosition = robot.position; Assert.assertEquals(new Position(0,"S"),resultPosition); } @Test public void test_when_given_0_3_W_move_then_return_2_3_N() { Position position = new Position(0,3,"W"); Robot robot = new Robot(position); robot.command("M"); robot.command("R"); robot.command("R"); robot.command("M"); robot.command("M"); robot.command("L"); Position resultPosition = robot.position; Assert.assertEquals(new Position(2,resultPosition); } @Test public void test_two_robots() { Position position = new Position(0,"E"); Robot robot1 = new Robot(position); Robot robot2 = new Robot(position); ControlCenter controlCenter = new ControlCenter(); controlCenter.addRobots(robot1); controlCenter.addRobots(robot2); controlCenter.command("M"); Assert.assertEquals(new Position(1,robot1.position); Assert.assertEquals(new Position(1,robot2.position); } @Test public void test_two_robots_turn_left_and_move() { Position position = new Position(0,"E"); Robot robot1 = new Robot(position); Robot robot2 = new Robot(position); ControlCenter controlCenter = new ControlCenter(); controlCenter.addRobots(robot1); controlCenter.addRobots(robot2); controlCenter.command("L"); controlCenter.command("M"); Assert.assertEquals(new Position(0,robot1.position); Assert.assertEquals(new Position(0,robot2.position); } }
Position.java
package com.study.robot; public class Position { public int x; public int y; public String direction; public Position(int x,int y,String direction) { this.x = x; this.y = y; this.direction = direction; } public Position(){ super(); } @Override public boolean equals(Object object) { Position position = (Position)object; if(x != position.x){ return false; } if(y != position.y){ return false; } if(!direction.equals(position.direction)){ return false; } return true; } public void operateX(Integer opx){ if(opx == null) { return; } if(this.x == 0 && opx < 0) { return; } this.x += opx; } public void operateY(Integer opy) { if(opy == null) { return; } if(this.y == 0 && opy < 0) { return; } this.y += opy; } }
ControlCenter.java
package com.study.robot; import java.util.ArrayList; import java.util.List; /** * 采用命令模式实现 */ public class ControlCenter { private List<Robot> robots = new ArrayList<Robot>(); public void addRobots(Robot robot) { robots.add(robot); } public void command(String command) { for(Robot robot: robots) { robot.command(command); } } }
Robot.java
package com.study.robot; import java.util.HashMap; import java.util.Map; /** * 表驱动法实现命令的执行 * 表驱动法是一种编程模式——从表中查找信息而不是使用逻辑语句(if或else)。如果逻辑很复杂,导致逻辑判断链很长,使用驱动表法有助于降低复杂度。否则,表驱动法只会增加复杂度。 * 从表中查询条目有三种方法: * a.直接访问(Directory access)表 * b.索引访问(Index access)表 * c.阶梯访问(Stair-step access)表 * 表中保存的可能是数据、函数指针,对象实例等(说明:如果保存的是对象实例的话,那就是命令模式) */ public class Robot { public Position position; private String DIRECTION_EAST = "E"; private String DIRECTION_WEST = "W"; private String DIRECTION_SOUTH = "S"; private String DIRECTION_NORTH = "N"; private String COMMAND_LEFT = "L"; private String COMMAND_RIGHT = "R"; private String COMMAND_MOVE = "M"; Map<String,String> directionSearchTable = new HashMap<String,String>(){{ put(DIRECTION_EAST+COMMAND_LEFT,DIRECTION_NORTH); put(DIRECTION_WEST+COMMAND_LEFT,DIRECTION_SOUTH); put(DIRECTION_SOUTH+COMMAND_LEFT,DIRECTION_EAST); put(DIRECTION_NORTH+COMMAND_LEFT,DIRECTION_WEST); put(DIRECTION_EAST+COMMAND_RIGHT,DIRECTION_SOUTH); put(DIRECTION_WEST+COMMAND_RIGHT,DIRECTION_NORTH); put(DIRECTION_SOUTH+COMMAND_RIGHT,DIRECTION_WEST); put(DIRECTION_NORTH+COMMAND_RIGHT,DIRECTION_EAST); }}; Map<String,Integer> xSearchTable = new HashMap<String,Integer>(){{ put(DIRECTION_EAST,new Integer(1)); put(DIRECTION_WEST,new Integer(-1)); }}; Map<String,Integer> ySearchTable = new HashMap<String,Integer>(){{ put(DIRECTION_SOUTH,new Integer(-1)); put(DIRECTION_NORTH,new Integer(1)); }}; public Robot(Position position) { this.position = new Position(); this.position.x = position.x; this.position.y = position.y; this.position.direction = position.direction; } public void command(String command) { if(command.equals(COMMAND_LEFT) || command.equals(COMMAND_RIGHT)) { position.direction = directionSearchTable.get(position.direction+command); } if(command.equals(COMMAND_MOVE)){ position.operateX(xSearchTable.get(position.direction)); position.operateY(ySearchTable.get(position.direction)); } } }