Monday, March 19, 2012

Agile Programming in extremis -- re-refactoring.

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

The next person to look at the code said: "What does isSameEvent do? I can't tell from the code." The changes resulted in two files containing 39 lines of production code and 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 isSameLocation(currentEvent, prevousEvent) &&
           isSameTime(currentEvent, previousEvent);
  }
  
  private bool isSameLocation(
        Event currentEvent, Event previousEvent){
    return (isSamePoint(
               currentEvent.getX(), 
               previousEvent.getX(), 
               X_LIMIT) &&
           (isSamePoint(
               currentEvent.getY(), 
               previousEvent.getY(), 
               Y_LIMIT);
  }
  
  private bool isSameTime(
       Event currentEvent, Event previousEvent){
    return currentEvent.getTime() - previousEvent.getTime() 
      < TIME_LIMIT;
  }
  
  private bool isSamePoint(
       int current, int previous, int tolerance){
    return math.abs(current - previous) < tolerance;
  }
};

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(varying 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: