Five Reasons Standardizing Your Process is a Terrible Idea

Soon after an organization adopts agile software development methods, it seems that mangers inevitably talk about the need to “mature” and “standardize” their process. Here are a few reasons standardizing your agile process is a terrible idea.

Standardizing on a process, across teams and projects, prevents innovation and progress. As the Agile Manifesto urges, “At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.” If a process is standardized, then it will be either impossible or very difficult to adjust your practices. One thing I really love about iterative development is that you can run experiments on your development process itself. You can modify your process for an iteration or two and see how it works. If it’s an improvement, you can continue. If it’s detrimental, then at least you learned something. Rigid standardization prevents this.

In the worst scenario, standardization can force teams to knowingly do the wrong things. No project is alike, no team is alike. The context always varies, even perhaps from iteration to iteration. The fact is that a “best practice” for one team may not be a good practice for a team in a different context. There are few, if any, absolutely best practices that are applicable to all situations. A standard process can force a team to follow a rule that it intuitively knows to be inappropriate.

Standardization will require some type of process or oversight, which will exist solely to enforce the standardized process. There will be some amount of work involved to make sure each team is following the rules. Otherwise how do you know that team down the hall is actually doing TDD instead of just writing tests after the fact? Somebody has to own, and enforce, the process. This flies in the face of simplicity – maximizing the amount of work not done.

A standardized process ruins the outcome-oriented spirit of agile software development. If a rigid process that I can’t change is being enforced, and I follow the process and work diligently, I can’t be held accountable for failure. After all, I followed the rules. Instead, development teams should stick to the motto “Get ‘r done!”

Related to that, standardizing a process removes need to actually understand why certain practices exist. When you don’t have to derive, or at least continually justify, your practices from first principles, then it’s fairly easy to not bother understanding what those first principles are, and how they correlate to your practices. Allowing teams to vary their process as needed will help ensure that those processes flow from actual common values.

I’m not against all forms of standardization, and I think an organization – even the entire craft of software development – should have some “default” practices. Stay tuned for a future post on why standardizing your process is a wonderful idea!

Name your unit tests clearly

I advocate unit testing, and particularly test driven development, for several reasons. The most obvious is that unit testing helps prevent bugs. Good unit tests also help you design better – if it’s hard to test your class, you’ll refactor it so it is easier to test, and consequently wind up with a more loosely coupled design.

In addition, good unit tests can serve as excellent documentation of what the code is supposed to do. This is actually kind of hard to do well. One technique that helps me with this is to name my unit tests clearly. Each test correlates to one behavior of a class, and the name of the test reflects that behavior.

For instance, say you have an application that is responsible for order fulfillment and billing. An order has a purchaser, and optionally a shipping address. If the shipping address is null, you want to use the purchaser’s billing address. The code might look like this:

public class Order {
  private Address shippingAddress;
  private Purchaser purchaser;
  // ...
  public Address getShippingAddress() {
    if (shippingAddress != null) {
      return shippingAddress;
    }
    else {
      return purchaser.getBillingAddress();
    }
}

A typical way of writing unit tests (which I blame on Eclipse’s JUnit plugin) would be to write a single testGetShippingAddress test, and test both cases inside it:

public void testGetShippingAddress() {
  Address billing = new Address(...);
  Address shipping = new Address(...);
  Order o = new Order();
  Purchaser p = new Purchaser(billing,...);
  o.setPurchaser(p);
  o.setShippingAddress(shipping);
  assertEquals(shipping, o.getShippingAddress);

  // now test what happens if shipping not explicitly set
  o.setShippingAddress(null);
  assertEquals(billing, o.getShippingAddress);
}

This does effectively test the class, but it isn’t very clear about the behavior if the shipping address isn’t set – particularly if you don’t notice that the shipping address was being set back to null. Instead, we could write it like this:

public void testCanExplicitlySetShippingAddress() {
  Address billing = new Address(...);
  Address shipping = new Address(...);
  Order o = new Order();
  Purchaser p = new Purchaser(billing,...);
  o.setPurchaser(p);
  o.setShippingAddress(shipping);
  assertEquals(shipping, o.getShippingAddress);
}

public void testUsePurchasersBillingAddressIfShippingAddressNotSet() {
  Address billing = new Address(...);
  Order o = new Order();
  Purchaser p = new Purchaser(billing,...);
  o.setPurchaser(p);
  assertEquals(billing, o.getShippingAddress);
}

It’s true that there’s now some duplication between these methods, but that would be removed fairly easily and I only left it in for clarity. What we’re left with is two simple, clear tests that leave no doubt about what this class is supposed to do. If this class’s behavior changes in the future, seeing that testUsePurchasersBillingAddressIfShippingAddressNotSet() failed is going to make a lot more sense than seeing that testGetBillingAddress() failed somewhere, and digging through that test to figure out just what I broke. You can just drop the word “test” from the front of each test method and it reads like a simple spec.

This approach also works well with TDD’s “write a test, make it pass, refactor, check in” approach. Each test represents exactly one behavior and supports the iterative approach of building a class one failing test at a time. In fact, I suspect that using fewer, coarser-grained tests (as in my first example) is pretty good evidence that the coder didn’t do TDD.

Fix your process, don’t manage it

There are lots of bug/issue tracking systems in existence. For example, Wikipedia’s comparison of bug and issue tracking software scrolls to 15 full screens on my computer. If you look at that list, in addition to licensing, system requirements, etc., one way these apps are classified is whether or not they support a customizable workflow. Many of them are called out for features such as “extensive workflow”.

I have no doubt that a customizable workflow is important. But I think it’s a smell when heavy workflow customization is an important feature of bug tracking software. These features are only really important when you’re using the tool to manage a complex process. Rather than finding something to help you manage a complex process, simplify it.

Let’s consider a fairly typical workflow.

  1. A defect or feature request comes in. It is marked as “high priority”, as they always are.
  2. Someone investigates it and either addresses it, rejects it, or validates it.
  3. A fight ensues over whether it’s a defect or new feature.
  4. Someone decides how to schedule this – slate it for a future release, fix it immediately, or leave it open indefinitely?
  5. A developer gets assigned to work on it.
  6. The developer tries to fit this in with the fifteen other things he’s working on, and ultimately either makes his own decision or asks his boss, who tells him that everything is priority 1.
  7. The developer investigates the issue, changes the code, tests it, commits it, and gets on to the remaining fifteen priority 1 issues.
  8. A tester picks up the change, looks at the ticket, comes up with his interpretation of the need, and tests the developers code.
  9. The documentation specialist picks up the change, looks at the ticket, comes up with his interpretation, writes a document, calls the developers, rewrites the document.
  10. Repeat for the next issue.

Keep in mind, even this is a fairly simple workflow. We didn’t get into UAT, performance testing, integration, build and release management, etc. But it’s still far too complex.

Along the way, the issue tracking tool can gather metrics on how long the issue spent in a variety of states, perform automated routing and resolution based on many factors, and spam the world every time the issue’s status changes.

Instead of finding a suitable configurable and sophisticated tool to manage this process, focus on simplifying it. Treat exceptions as exceptional, and don’t worry about a process and tool that can handle every imaginable scenario, regardless how rare. Use a simple process. Remember that code is written, tested, and documented by actual people, and help them work together. Hold them all responsible for the results.

Why I’m Passionate about Software Development

Software development seems to be an odd thing to be passionate about. We developers don’t exactly have a reputation for being passionate sorts of people – we’re in sort of the same category as accountants. Yes, it’s a good job, and sometimes interesting, but something to be passionate about?

I am passionate about software because coding is an inherently creative thing to do. More than almost any other profession, we can create ex nihilo. We’re really alone among the engineering and science disciplines in our power to create – engineers are at least constrained by such mundane factors as the laws of physics. We aren’t, in general. As Frederick Brooks observed

“The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination.”

Only writers and artists can approach our ability to create. This is exciting to me. When I start coding, nothing existed there before. Then I work, and I change the world, even if just a very small piece.

Closely related to this, coding gives us an opportunity to perfect and demonstrate our craftsmanship, without being bothered with annoyances such as the physical world. Make a mistake while carving and you’ll have a tough time fixing it. Make a mistake while coding, and you can undo it. Nothing to paint over, nothing to sand out.

Creativity and crafstmanship are things to value, things even to be passionate about.