Please Don’t Make Me Say This Twice

Don’t Repeat Yourself.  It’s a powerful principle for eliminating duplication in code to facilitate easier change.  It should not stop there though.  If fully embraced, DRY can help you improve your system, your team, and even your organization.  Automating testing, deployment, and other processes can free up more time to make other improvements.  Uniting your team under a common set of values, principles, and practices can help team members more efficiently communicate and work together to make progress.  Establishing a consistent vision and message for your organization to rally under can help your teams to understand the work that needs to be done.  Failing to do any of these things means you are at risk of repeating yourself either on performing tasks that you shouldn’t need to or rehashing the same discussions to get the team working together and understanding each other.

If we stop repeating ourselves, we can use the extra time to make real progress, otherwise, we are often working hard to stand still.


Comments (0)

Permalink

New Rule: If You Can’t Name It, You Don’t Need It

When creating new software it is important to give simple meaningful names to the features and concepts that we create.  This allows us to communicate effectively with other team members and, more importantly, the users.  It can sometimes be difficult to give names to all of our concepts.  I believe that this is because modern software combines both established concepts that are familiar to the users as well as evolutionary ideas that were often not possible without computers.

It is important that we take care not to introduce more new concepts than are actually necessary to the user.  In the past I have seen features that have concepts with names like “base configurations”, “templates”, and “flavors” while the user only cares about the simple overall feature.  I have also seen vague lower level ideas like “pipelines”, “modules”, and “reflection” exposed to the customers.  Introducing ideas like these will usually just confuse the user (and often other engineers) while providing no actual value.

If you are considering adding something to your system and are having difficulty giving it a name, you probably don’t need it.  If your features do not mirror existing concepts in the user’s domain or established software patterns you are either adding unneeded complexity or developing revolutionary new designs.  I would not bet on the latter very often.


Comments (0)

Permalink

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.


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.


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.


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.


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?


Comments (0)

Permalink

Cover Me

I have read a great many things questioning the value of the measurement of test coverage.  I believe that there is a common misconception about test coverage and what our coverage numbers can tell us about our code.

The common criticisms are that while the coverage report can tell us how much of the code has been exercised it does not tell us how well.  This is absolutely true.  High coverage numbers are no substitute for reading the code (and the tests) and understanding what it supposed to do.  What the coverage numbers can give us is a measure of testability.

If you need to make changes to a piece of code that has very high test coverage you can plan that work with the confidence that the code is designed in a way that will not make it incredibly difficult to change.  This typically means that it adheres good design principles like Single Responsibility and Inversion of Control.  Furthermore it means you will have some tests to look at along with the code you are trying to understand before you change it.  Even if the quality of those tests is not enough to give you the confidence you need to change the code, you will already have the starting point you need to add better tests.  It’s much easier to change incomplete tests into good tests than it is to change no tests into good tests.

Perhaps instead of test coverage we should call it testability coverage.


Comments (1)

Permalink

Spotting a Team

Patrick Kua has a post about a topic I’ve thought about a lot recently: the power of a true team vs. a loosely organized group of people working together.  I believe he is spot on about there being significant benefits to building a tightly integrated team.  He even offers some suggestions for how you can form such teams in your own organiation.

There is a simple test that I often use to gauge how well the teams that I am a part of are composed.  During your daily stand-up or scrum (or better yet scrum of scrums) take the time to very careful go around the room and look at the face of each individual.  What do you see?  Are the team members engaged and interested?  Do they ask focused and pertinent questions?  If so, it’s a good bet that you have a team that is well invested in accomplishing the team’s common goals.  On the other hand if the majority of people look distant, bored, and anxious for the stand-up to end, it’s likely that you have a group of individuals that are more focused on their individual priorities.

Give it a shot at your next stand-up.


Comments (0)

Permalink

Building Bridges

Sometime is the last year I had a conversation with a colleague who was not yet convinced about the value of agile development processes.  This particular individual was a good engineer who had made it his practice to write top quality code when provided with a detailed specification.  He just couldn’t imagine that we could write good software without such a specification.  As is often the case when talking about software we eventually worked our way around to a construction analogy when he asked if I could imagine building a bridge with less than a detailed spec.  I responded at the time that the analogy doesn’t really hold up.  In software we have the option to build a less than complete product and test it’s acceptability as we progress toward completeness.  This is mostly made possible by the fact that the most expensive resources in software engineering are time and knowledge.  Spending those resources to develop a product that is not yet complete but is usable enough to evaluate our approach is not likely to be a big risk.  In real world construction the cost of real materials as well as the safety risks force us to do everything we can to build the bridge completely and correctly the first time.

Paulo Caroli at Agile Tips does my response one better though and turns the analogy around showing just how bridges can be and likely actually are built using agile processes.  He also throws in a few bridges that failed to get built with more traditional processes.


Comments (0)

Permalink