August 2008

Working To End Agile

I’m looking forward to the day when I don’t have to do agile software development anymore.  In fact I believe that we should all be working hard to bring the agile movement to an end.  Allow me to explain.

I’ll start by taking a look at the original Manifesto for Agile Software Development.  The manifesto begins with this statement:

We are uncovering better ways of developing software by doing it and helping others do it.

It’s important to step back from time to time and think about that statement and remember what agile is about: finding better ways to develop software.  It’s even more important to think about what is not involved in that statement: sprints, stand-ups, test-driven development, continuous integration, or any of the multitude of other things that we have come to associate with agile.  The important thing is finding better ways to make software.

The reason that I have begun to look forward to the end of the agile movement is simple: it’s working.  Agile methods have consistently shown that they can yield better software than the majority of the processes that we were using previously.  All over the software industry people are taking notice.  Job postings looking for candidates with agile experience are commonplace, agile consultancies are thriving, and blogs (like this one) with an agile slant are everywhere.

If agile methods are working and the industry is noticing it’s only a matter of time until it stops being “agile” and just becomes “software development.”  In many cases these days “agile” is used as a weapon.  Rather than focus on the “find a better way” aspect we focus on the established “agile” processes and hammer them in to places where they might not fit.  As agile becomes mainstream and the need for forcing change through process lessens I hope that we can get back to the original goals of finding ways to build great software.


Uncategorized

Comments (0)

Permalink

I don’t want you hanging around with that code anymore

Your code may be a bad influence on you.  When you set out to tackle a specific task driven by a certain customer need the code can quickly lead you astray.  Sometimes it tempts you with juicy refactorings that look relevant to your task but end up being long distractions with little immediate value.  Other times it might suggest new code that fits nicely into the current architecture and almost but not quite fills the customer’s needs.  Worst of all are the cases when the existing code is so bad that it can be difficult to focus on the needed changes at all.

The solution: step away from the code.  Often times it’s too easy to write more code.  Spending too much time sitting at the keyboard listening to what the code is telling you can be a dangerous time sink.  It can be helpful several times a day to get away from the screen and reflect on what you are trying to accomplish.  You might be surprised how much time taking a walk can save you.


Uncategorized

Comments (0)

Permalink

Your Framework, Probably Won’t

It has happened to just about all of us. Your customer has a requirement X. You recognize that you can satisfy X as well as Y and Z and innumerable other needs that you are certain will be the the customer will have in the future easily if you just build the proper framework. (Please take a moment to appreciate how useful it is that you can see the future).  It’s a satisfying feeling. You’ve taken the whole project up a level. You are writing code that is useful to both you and your customer. You are flying high (while still taking care to stay below the stratosphere). This is what software development is all about.

There is just one problem. There is disappointment in your future. Maybe for you or maybe for your customer but probably for both of you. Odds are your framework won’t actually do the job. Either your customer is stuck accepting compromises in their needs for the software because the range of achievable functionality is constrained by the framework. Or you are forced to make nasty compromises in the framework and code in general because the customer holds fast and demands the functionality that they actually need despite what your existing framework easily supports.

As Jeffery Palermo says, creating frameworks and libraries is very satisfying to developers because you essentially get to be your own customer.  However, frameworks and libraries are also some of the hardest code to get right.  I have seem many fail with this same pattern.  I’ve written more than I’d like to admit that failed with this same pattern.  If you write the application that your customer needs you will get the satisfaction of delivering working software that enhances some one’s life or work.  If you do spot a repeatable pattern in functioning software that can be used elsewhere than by all means extract it and create a reusable framework.  If you try to build the framework first you will probably find only disappointment.


Uncategorized

Comments (1)

Permalink

Creating Better Mock Tests With Hamcrest Custom Matchers

The use of TDD along with mock objects while designing for testability can help us to write extremely high quality code.  In fact I have learned that practicing these techniques regularly can help move 100% coverage away from a nearly impossible (and questionably valuable) goal and much closer to a milestone achievable with an extra bit of incremental effort.

There are situations I have come across where the steps required for complete design for testability seem just a bit excessive.  Sometimes when we design for testability we get application code and tests that are much more complex than we would like them to be.

Let’s look at an example.

public class ComplexValue {
  private String ourProperty;
  private String otherProperty;
  private String lastProperty;

  public ComplexValue() {
    ...
  }

  public ComplexValue(String ourProperty) {
    this.ourProperty = ourProperty;
    ...
  }

  public String getOurProperty() {
    return ourProperty;
  }
}



public interface ActionService {
  public void act(ComplexValue value);
}



public class Actor {
  private ActionService service;

  public Actor(ActionService service) {
     this.service = service;
  }

  public void doAction(String propertyValue) {
    service.act(new ComplexValue(propertyValue));
  }
}

Notice that ComplexValue has three property fields.  In this context assume we care about one (the one that we construct it with) and the other two properties may or may not be given other values in the constructor.

The simplest test we can write for this class uses jMock like this:


public class ActorTest {
  private Mockery mockery = new Mockery();
  private ActionService actionService;
  private Actor actionClass;

  @Before
  public void setUp() {
    actionService = mockery.mock(ActionService.class);
    actionClass = new Actor(actionService);
  }

  @Test
  public void testDoAction() {
    mockery.checking(new Expectations() {
      {
         one(actionService).act(with(any(ComplexValue.class)));
       }
    });

    actionClass.doAction("Test Property Value.");
    mockery.assertIsSatisfied();
  }
}

This type of test will do wonders for your coverage report.  It’s not really testing much though is it?  The responsibility of the Actor is to construct the ComplexValue with the property we passed in and pass that along to the ActionService.  When we ignore the value of the property in the test we in turn ignore a large part of the Actor functionality.

If we redesign slightly for testability we can write much better tests.


public interface ComplexValueFactory {
  public ComplexValue build(String property);
}


public class ComplexValueFactoryImpl implements ComplexValueFactory {
  public ComplexValue build(String property) {
    return new ComplexValue(property);
  }
}


public class Actor {
  private ActionService service;
  private ComplexValueFactory factory;

  public Actor(ActionService service, ComplexValueFactory factory) {
    this.service = service;
    this.factory = factory;
  }

  public void doAction(String propertyValue) {
    service.act(factory.build(propertyValue));
  }
}

Now the tests will look like this:


public class ActorTest {
  private Mockery mockery = new Mockery();
  private ActionService actionService;
  private ComplexValueFactory factory;
  private Actor actionClass;

  @Before
  public void setUp() {
    actionService = mockery.mock(ActionService.class);
    factory = mockery.mock(ComplexValueFactory.class);
    actionClass = new Actor(actionService, factory);
  }

  @Test
  public void testDoAction() {
    final ComplexValue dummyValue = new ComplexValue();
    mockery.checking(new Expectations() {
      {
        one(factory).build("Test Property Value.");
        will(returnValue(dummyValue));
        one(actionService).act(dummyValue);
      }
    });

    actionClass.doAction("Test Property Value.");
    mockery.assertIsSatisfied();
  }
}

public class ComplexValueFactoryImplTest {
  private ComplexValueFactoryImpl factory;

  @Before
  public void setUp() {
    factory = new ComplexValueFactoryImpl();
  }

  @Test
    public void testBuild() {
    String propertyValue = "Property Value For Test";
    ComplexValue expectedValue = new ComplexValue(propertyValue);
    assertEquals(expectedValue, factory.build(propertyValue));
  }
}

Now that we have moved the construction of the ComplexValue into a separate factory we can test that Actor appropriately calls that factory and uses the result as we expect it to.  Independently, we can also test that the factory produces the ComplexValue as expected.  While this fulfills our goals of useful tests and in fact introduces a factory which might someday be useful for other reasons it still seems like a lot of extra clutter in our application code.  Lets explore another option that can get us the same valuable testing without so much load on our application code.

Lets take a look again at the original test that we wrote for Actor:


public class ActorTest {
  private Mockery mockery = new Mockery();
  private ActionService actionService;
  private Actor actionClass;

  @Before
  public void setUp() {
    actionService = mockery.mock(ActionService.class);
    actionClass = new Actor(actionService);
  }

  @Test
  public void testDoAction() {
    mockery.checking(new Expectations() {
      {
        one(actionService).act(with(any(ComplexValue.class)));
      }
    });

    actionClass.doAction("Test Property Value.");
    mockery.assertIsSatisfied();
  }
}

In this test we used the jMock “any” matcher to insure that the ActionService’s act() method with an instance of ComplexValue.  In order to make this test more useful we would like to insure the the act() method is called with an instance of ComplexValue that with the ourProperty property matching the value that we specified to the Actor.  We can write just such a test if we create a custom Hamcrest matcher for jMock to validate against.


public class ComplexValueOurPropertyMatcher extends TypeSafeMatcher<ComplexValue> {
  private String ourPropertyValue;

  public StringStartsWithMatcher(String ourPropertyValue) {
    this.ourPropertyValue = ourPropertyValue;
  }

  public boolean matchesSafely(ComplexValue v) {
    return v.getOurProperty() == ourPropertyValue;
  }

  public StringBuffer describeTo(Description description) {
    return description.appendText("a ComplexValue with ourPropertyEqual to ").appendValue(ourPropertyValue);
  }
}

This is a custom Hamcrest matcher that will return true to the matchesSafely method if it is passed a ComplexValue that has the same ourProperty value as the one specified.  In addition we will create a matcher factory that will make the jMock expectations using our new matcher easier to read.


@Factory
public static Matcher<ComplexValue> complexValueWithOurProperty(String ourProperty ) {
  return new ComplexValueOurPropertyMatcher(ourProperty);
}

Now we can modify our test class to look like this:


public class ActorTest {
  private Mockery mockery = new Mockery();
  private ActionService actionService;
  private Actor actionClass;

  @Before
  public void setUp() {
    actionService = mockery.mock(ActionService.class);
    actionClass = new Actor(actionService);
  }

  @Test
  public void testDoAction() {
    mockery.checking(new Expectations() {
      {
        one(actionService).act(with(complexValueWithOurProperty("Test Property Value.")));
      }
    });

    actionClass.doAction("Test Property Value.");
    mockery.assertIsSatisfied();
  }
}

Now we have a test that is just as valuable as the tests we were able to write with the Factory solution while not needing to add any additional application code.

In many cases a solution that is designed for testability is the best way to create good tests.  Applications that are designed for testability often get maintainability, extensibility, and simplicity as side effects.  It can still be very useful to have the additional flexibility that using Hamcrest custom matchers in your mock object tests can provide.


Uncategorized

Comments (0)

Permalink

Cooking Up Some Software

The field of software development has no shortage of metaphors.  There’s engineering, construction, and manufacturing to name a few.  Since no metaphor does a perfect job of capturing the essence of what making software is all about, I always enjoy exploring new ones to see what else they can teach us.

Todd Hoff, who writes the fantastic High Scalability Blog, recently linked to a series of posts on his personal site that adds a new metaphor to the mix: food service.  Hoff details some of the lessons we can learn about software from chef Gordon Ramsay (of Hell’s Kitchen and Kitchen Nightmares fame).  He gives an extensive list of cooking and restaurant business lessons learned from the shows and leaves it as an exercise for the reader to fill in the software metaphors.  As a fan of Ramsay’s television shows, I was drawn to this concept of extending what he has to say to software.  I want to expand upon Hoff’s first bullet item:

Quality can never be compromised. Let nothing slide.

In the software business it is too often the case that quality is the first thing to slide.  How often have you heard some variation of “Due to time pressure we went with a quick and dirty solution”?  Such an idea is disturbing in any kitchen.  In the kitchens of the caliber of restaurant that chefs like Ramsay operate it would be unheard of.

However in software and food service alike there is a range of expected and acceptable levels of quality.  Many of us eat every day at establishments that provide a lesser quality product in exchange for increased speed and lower price.  Likewise many of us work in organizations that make the same trade offs in the software that they deliver.

I would like to think that Ramsay is right and quality really can never be comprised.  The reality is otherwise.  It helps though to remember what kind of software you aspire to create while you are making those compromises.  Are you providing a delicious healthy meal or a fast food burger?


Uncategorized

Comments (0)

Permalink