Monday, March 19, 2012

Agile programming in extremis -- the first refactoring.

See the previous post (Agile programming in extremis) for the start of the story.

The first agile developer to examine this code said: “It’s not clear what that if statement is testing.” and produced the following improved version (2 files; 28 lines of production code; around 50 lines of test code):
public class EventListener{
  static final int X_LIMIT = 200;
  static final int Y_LIMIT = 200;
  static final long TIME_LIMIT = 500L;

  private DuplicateEventHandler duplicateEventHandler;
  private Event previousEvent = null;
  
  public EventListener(
       DuplicateEventHandler duplicateEventHandler){
    this.duplicateEventHandler = duplicateEventHandler;
  }
  
  public void onEvent(Event currentEvent)
  {
    bool previousEventIsValid = (previousEvent != null);
    if(previousEventIsValid && 
         isSameEvent(previousEvent, currentEvent)) {
       duplicateEventHandler.handleSameEvent(currentEvent);
    }
    previousEvent = currentEvent.cloneEvent(); 
  }    
  
  private bool isSameEvent(
       Event currentEvent, Event previousEvent){
    return 
      ((math.abs(currentEvent.getX() – previousEvent.getX()) 
         < X_LIMIT) &&
       (math.abs(currentEvent.getY() – previousEvent.getY()) 
         < Y_LIMIT) &&
       (currentEvent.getTime – previousEvent.getTime() 
         < TIME_LIMIT));
  }
};

public class EventListenerTest{
  private EventListener testObject;
  
  private Event event1 = new Event(parameter);

  @Mock
  private DuplicateEventHandler duplicateEventHandler;

  @Before  
  public void setup(){
    testObject = new EventListener(duplicateEventHandler);
    testObject.onEvent(event1);
  }    
  
  @Test
  public void thisIsATypicalTest(){
    Event event2 = new Event(various parameters
       to test boundary conditions);
    testObject.onEvent(event2);
    verify(duplicateEventHandler).handleSameEvent(event2);
    // or depending on the parameters to event2...
    verify(duplicateEventHandler, never()).handleSameEvent
         (event2);
  }
};

No comments: