Unit Test Success using Ports, Adapters, and Simulators

December 1, 2014 at 3:38 pm

There is a very cool pattern called Port/Adapter/Simulator that has changed my perspective about unit testing classes with external dependencies significantly and improved the code that I’ve written quite a bit. I’ve talked obliquely about it and even wrote a kata about it, but I’ve never sat down and written something that better defines the whole approach, so I thought it was worth a post. Or two – the next one will be a walkthrough of an updated kata to show how to transform a very simple application into this pattern.

I’m going to assume that you are already “down” with unit testing – that you see what the benefits are – but that you perhaps are finding it to be more work than you would like and perhaps the benefits haven’t been quite what you hoped.

Ports and Adapters

The Ports and Adapters pattern was originally described by Alistair Cockburn in a topic he called “Hexagonal Architecture”. I highly recommend you go and read his explanation, and then come back.

I take that back, I just went and reread it. I recommend you read this post and then go back and read what he wrote.

I have pulled two main takeaways from the hexagonal architecture:

The first is the “hexagonal” part, and the takeaway is that the way we have been drawing architectural diagrams for years (User with a UI on top, app code in between (sometime in several layers), database and other external dependencies at the bottom) doesn’t really make sense. We should instead delineate between “inside the application” and “outside of the application”.  Each thing that is outside of the application should be abstracted into what he calls a port (which you can just think of as an interface between you and the external thing). The “hexagonal” thing is just a way of drawing things that emphasizes the inside/outside distinction.

Dealing with externals is a common problem when we are trying to write unit tests; the external dependency (say, the .NET File class, for example) is not designed with unit testing in mind, so we add a layer of abstraction (wrapping it in a class of our own), and then it is testable.

This doesn’t seem that groundbreaking; I’ve been taking all the code related to a specific dependency – say, a database – and putting it into a single class for years. And,  if that was all he was advocating, it wouldn’t be very exciting.

The second takeaway is the idea that our abstractions should be based on what we are trying to do in the application (the inside view) rather than what is happening outside the application. The inside view is based on what we are trying to do, not the code that we will write to do it.

Another way of saying this is “write the interface that *you wish* were available for the application to use”.  In other words, what is the simple and straightforward interface that would make developing the application code simple and fun?

Here’s an example. Let’s assume I have a text editor, and it stores documents and preferences as files. Somewhere in my code, I have code that accesses the file system to perform these operations. If I wanted to encapsulate the file system operations in one place so that I can write unit tests, I might write the following:

class FileSystem
{
    public void CreateDirectory(string directory) { }
    public string ReadTextFile(string filename) { }
    public void WriteTextFile(string filename, string contents) { }
    public IEnumerable<string> GetFiles(string directory) { }
    public bool FileExists(string filename) { }
}

And I’ve done pretty well; I can extract an interface from that, and then do a mock/fake/whatever to write tests of the code that uses the file system. All is good, right? I used to think the answer is “yes”, but it turns out the answer is “meh, it’s okay, but it could be a lot better”.

Cockburn’s point is that I’ve done a crappy job of encapsulating; I have a bit of isolation from the file system, but the way that I relate to the code is inherently based on the filesystem model; I have directories and files, and I do things like reading and writing files. Why should the concept of loading or saving a document be tied to this thing we call filesystem? It’s only tied that way because of an accident of implementation.

To look at it another way, ask yourself how hard it would be to modify the code that uses FileSystem to use a database, or the cloud? It would be a pretty significant work item. That also means that my encapsulation is bad.

What we are seeing – and this is something Cockburn notes in his discussion – is that details from the implementation are leaking into our application. Instead of treating the dependency technology as a trivial choice that we might change in the future, we are baking it into the application. I’m pretty sure that somewhere in our application code we’ll need to know file system specifics such as how to parse path specifications, what valid filename characters are, etc.

A better approach

Imagine that we were thinking about saving and loading documents in the abstract and had no implementation in mind. We might define the interface (“port” on Cockburn’s lingo) as follows:

public interface IDocumentStore
{
    void Save(DocumentName documentName, Document document);
    Document Load(DocumentName documentName);
    bool DoesDocumentExist(DocumentName documentName);
    IEnumerable<DocumentName> GetDocumentNames();
}

This is a very simple interface – it doesn’t need to do very much because we don’t need it to. It is also written fully using the abstractions of the application – Document and DocumentName instead of string, which makes it easier to use. It will be easy to write unit tests for the code that uses the document store.

Once we have this defined, we can write a DocumentStoreFile class (known as an “adapter” because it adapts the application’s view of the world to the underlying external dependency).

Also note that this abstraction is just what is required for dealing with documents; the abstraction for loading/saving preferences is a different abstraction, despite the fact that it also uses the file system. This is another way this pattern differs from a simple wrapper.

(I should note here that this is not the typical flow; typically you have code that it tied to a concrete dependency, and you refactor it to something like this. See the next post for more information on how to do that).

At this point, it’s all unicorns and rainbows, right?

Not quite

Our application code and tests are simpler now – and that’s a great thing – but that’s because we pushed the complexity down into the adapter. We should test that code, but we can’t test that code because it is talking with the non-testable file system. More complex + untestable doesn’t make me happy, but I’m not quite sure how to deal with that right now, so let’s ignore it for the moment and go write some application unit tests.

A test double for IDocumentStore

Our tests will need some sort of test double for code that uses the IDocumentStore interface. We could write a bunch of mocks (either with a mock library or by hand), but there’s a better option

We can write a Simulator for the IDocumentStore interface, which is simply an adapter that is designed to be great for writing unit tests. It is typically an in-memory implementation, so it could be named DocumentStoreMemory, or DocumentStoreSimulator, either would be fine (I’ve tended to use “Simulator”, but I think that “Memory” is probably a better choice).

Nicely, because it is backed by memory, it doesn’t have any external dependencies that we need to mock, so we can write a great set of unit tests for it (I would write them with TDD, obviously) that will define the behavior exactly the way the application wants it.

Compared to the alternative – mock code somewhere – simulators are much nicer than mocks. They pull poorly-tested code out of the tests and put it into a place where we can test is well, and it’s much easier to do the test setup and verification by simply talking to the simulator. We will write a test that’s something like this:

DocumentStoreSimulator documentStore = new DocumentStoreSimulator();
DocumentManager manager = new DocumentManager(documentStore);
Document document = new Document("Sample text");
DocumentName documentName = new DocumentName("Fred");
manager.Save(documentName);

Assert.IsTrue(documentStore.DoesDocumentExist(documentName));
Assert.AreEqual("Sample text", documentStore.Load(documentName).Text);

Our test code uses the same abstractions as our product code, and it’s very easy to verify that the result after saving is correct.

A light bulb goes off

We’ve now written a lot of tests for our application, and things mostly work pretty well, but we keep running into annoying bugs, where the DocumentStoreFile behavior is different than the DocumentStoreMemory behavior. This is annoying to fix, and – as noted earlier – we don’t have any tests for DocumentStoreFile.

And then one day, somebody says,

These aren’t DocumentStoreMemory unit tests! These are IDocumentStore unit tests – why don’t we just run the tests against the DocumentStoreFile adapter?

We can use the simulator unit tests to verify that all adapters have the same behavior, and at the same time verify that the previously-untested DocumentStoreFile adapter works as it should.

This is where simulators really earn their keep; they give us a set of unit tests that we can use both to verify that the real adapter(s) function correctly and that all adapters behave the same way.

And there was much rejoicing.

In reality, it’s not quite that good initially, because you are going to miss a few things when you first write the unit tests; things like document names that are valid in one adapter but not another, error cases and how they need to be handled, etc. But, because you have a set of shared tests and they cover everything you know about the interface, you can add the newly-discovered behavior to the unit tests, and then modify the adapters so they all support it.

Oh, and you’ll probably have to write a bit of code for test cleanup, because that document that you stored in your unit tests will be there the next time if you are using the file system adapter but not the memory adapter, but these are simple changes to make.

Other benefits

There are other benefits to this approach. The first is that adapters, once written, tend to be pretty stable, so you don’t need to be running their tests very much. Which is good, because you can’t run the tests for any of the real adapters as part of your unit tests suite; you typically need to run them by hand because they use real versions of the external dependencies and require some configuration.

The second is that the adapter tests give you a great way to verify that a new version of the external dependency still works the way you expect.

The simulator is a general-purpose adapter that isn’t limited to the unit test scenario. It can also be used for demos, for integration tests, for ATDD tests; any time that you need a document store that is convenient to work with. It might even make it into product code if you need a fast document cache.

What about UI?

The approach is clearest when you apply it to a service, but it can also be applied to the UI layer. It’s not quite as cool because you generally aren’t about to reuse the simulator unit tests the same way, but it’s still a nice pattern. The next post will delve into that a bit more deeply.

Simulators or not?

October 3, 2014 at 8:47 pm

I’ve been spending some time playing with Cockburn’s hexagonal architecture  (aka “ports and adapters”), and the extension I learned from Arlo, simulators. I’ve found it to be quite useful.

I was writing some code, and I ended up at a place I didn’t expect. Here’s the situation. I have the following external class (ie “port”).

class EntityLoader
{
    public EntityLoader(string connectionInformation) {}

    public IEnumerable<Entity> Fetch(EntithyType itemType) { … }
}

I need to use this class to some different kinds of entities, do some light massaging of data, and then query against the data. I’ll start figuring out what the adapter should be, and I’ll define it by the question that I want to ask it:

interface IPeopleStore
{
    IEnumerable<Employee> GetAllEmployeesForManager(Employee employee);
}

Now that I have the interface, I can use TDD to write a simulator that implements the interface:

class PeopleStoreSimulator: IPeopleStore
{
    public IEnumerable<Employee> GetAllEmployeesForManager(Employee employee) { …}
}

The implementation for this will be pretty simple; I just add a way to get the list of employees for a manager into the simulator. Now I have unblocked my team members; they can code against the interface and use the simulator for their testing while I figure out how to write the version that talks to the EntityLoader.

And this is where it got interesting…

One of the cool things about port/simulator/adapter is that you can write one set of tests and run them against all of the adapters, including the simulator. This verifies that the simulator and the real adapter have the same behavior.

That’s going to be problematic because the interface for Entity doesn’t give me any way to put data into it, so I can’t use the simulator tests on it. It will also do two things; fetch the data from the entity and implement the GetAllEmployeesForManager() method, and because I can’t put data into it, I don’t have a way to write a test for the method().

It also violates one of my guidelines, which is to separate the fetching of data and the processing of data whenever possible. The problem is that we have the lookup method logic in a class that we can’t test – ie so we can’t adapt the data into what we need. That’s a good sign that adapter may not be a good choice here. How about a simpler approach, such as wrapper?

Let’s start with the lookup logic. We’ll make PeopleStore a simple container class, and that will make the lookup logic trivial to test.

class PeopleStore
{
    IList<Employee> m_employees;
    IList<Employee> m_managers;

    public PeopleStore(IList<Employee> employees, IList<Employee> managers)
    {
        m_employees = employees;
        m_managers = managers;
    }
   
    public IEnumerable<Employee> GetAllEmployeesForManager(Employee employee)
    {
        …
    }
}

Now, I’ll work on the wrapper level. After going with an interface, I end up switching to an abstract class, because there is a lot of shared code.

abstract class EntityStoreBase
{
    protected IEnumerable<Employee> m_employees;
    protected IEnumerable<Employee> m_managers;

    IEnumerable<Employee> FetchEmployees() { return m_employees; }
    IEnumerable<Employee> FetchManagers() { return m_managers; }
}

class EntityStoreSimulator: EntityStoreBase
{
    public EntityStoreSimulator(IEnumerable<Employee> employees, IEnumerable<Employee> managers)
    {
        m_employees = employees;
        m_managers = managers;
    }
}

class EntityStore : EntityStoreBase
{
    public EntityStore(string connectionInformation)
    {
        EntityLoader loader = new EntityLoader(connectionInformation);

        m_employees = loader.Fetch(EntityType.Employee)
                            .Select(entity => new Employee(entity));
        m_managers = loader.Fetch(EntityType.Manager)
                            .Select(entity => new Employee(entity));
    }
}

That seems to work fine. Now I need a way to create the PeopleStore appropriately. How about a factory class?

public static class EntityStoreFactory
{
    public static EntityStoreBase Create(IEnumerable<Employee> employees, IEnumerable<Employee> managers)
    {
        return new EntityStoreSimulator(employees, managers);
    }

    public static EntityStoreBase Create(string connectionInformation)
    {
        return new EntityStore(connectionInformation);
    }
}

This feels close; it’s easy to create the right accessor and the EntityLoader class is fully encapsulated from the rest of the system. But looking through the code, I’m using 4 classes just for the entity-side part, and the code there is either not testable (the code to fetch the employees from the EntityLoader), or trivial. Is there a simpler solution? I think so…

public static class PeopleStoreFactory
{
    public static PeopleStore Create(IEnumerable<Employee> employees, IEnumerable<Employee> managers)
    {
        return new PeopleStore(employees, managers);
    }

    public static PeopleStore Create(string connectionInformation)
    {
        EntityLoader loader = new EntityLoader(connectionInformation);

        var employees = loader.Fetch(EntityType.Employee)
                            .Select(entity => new Employee(entity));
        var managers = loader.Fetch(EntityType.Manager)
                            .Select(entity => new Employee(entity));

        return Create(employees, managers);
    }
}

This is where I ended up, and I think it’s a good place to be. I have a class that is well-adapted to what the program needs (the PeopleStore), and very simple ways to create it (PeopleStoreFactory).

Thinking at the meta level, I think the issue with the initial design was the read-only nature of the EntityStore; that’s what made the additional code untestable. So, as fond as I am of port/adapter/simulator, there are situations where a simple factory method is a better choice.

Identifying your vertical story skeleton

September 24, 2014 at 8:39 am

I’ve been leading an agile team for a while now, and I thought I would share some of the things we’ve learned. This one is about vertical slices, and learning how to do this has made the team more efficient and happier.

To make this work you need a team that is cross-functional and has the skills to work on your whole stack (database/server/ui/whatever).

As an example, assume that the team is working on the following story as part of a library application:

As a authenticated library user, I can view the list of the books that I have checked out.

The team discusses what this means, and here’s what they come up with:

  1. Authenticate the current user
  2. Fetch the list of book ids that are checked out by that user
  3. Fetch the book title and author for each book id
  4. Display the nicely-formatted information in a web page

My old-school reaction is to take these four items, assign each of them to a pair, and when all of them are done, integrate them together, and the story will be complete. And that will work; lots of teams have used that approach over the years.

But I don’t really like it. Actually, that’s not quite strong enough – I really don’t like it, for a bunch of reasons:

  • It requires a lot of coordination on details to keep everybody in sync. For example, changes need to be coordinated across the teams.
  • We won’t have anything to show until the whole story is done, so we can’t benefit from customer feedback.
  • Teams will likely be waiting for other teams to do things before they can make progress.
  • The different areas will take different amounts of time to finish, so some people are going to be idle.
  • Our architecture is going to be a bit clunky in how the pieces fit together.
  • It encourages specialization.
  • Nobody owns the end-to-end experience
  • Integrations are expensive; when we integrate the parts together we will likely find issues that we will have to address.

The root problem is that the units of work are too coupled together. What I want is a work organization where the units of work are an end-to-end slice, and a pair (or whatever grouping makes sense) can go from start to finish on it.

That seems to be problematic; the story describes a simple business goal, and it’s unclear how we can make it simpler. We *need* all the things we thought of to achieve success.

This situation blocks most teams. And they are right in their analysis; there is no way to be simpler and to achieve success. Therefore, the only thing that might work is to redefine success.

That’s right, we’re going to cheat.

This cheating involves taking the real-world story and simplifying it by making it less real-world. Here’s a quick list of ways that we could make this story simpler:

  • We don’t really need the book title and author, so we redefine “list of books” to “list of book ids”.
  • The display doesn’t have to be nicely formatted, it could just be a list of book ids on a web page.
  • The display could even just be the results of a call to a web API that we make in a browser.
  • We could build the initial version as a console app, not as a web app.
  • The story doesn’t have to work for every user, it could just work for one user.
  • The list of returned books doesn’t have to be an actual list of checked-out books, it could be a dummy list.

This is just a quick list I came up with, so there may be others. Once we have this list, we can come up with our first story:

As a developer, I can call an API and get a predefined list of book ids back

I’ve taken to calling this a “skeleton story”, because it’s a bare-bones implementation that we will flesh out later.

We will go off and implement this story, deploy it as a working system, and – most importantly – verify that it behaves as it should.

Getting to this story is the hard part, and at this point the remaining vertical slices are merely adding back the parts of the story that we took out. Here’s a possible list of enhancements:

  1. Fetch the list of book ids for a predefined user
  2. Fetch the list of book ids for a user passed into the api.
  3. Display the book ids in web page
  4. Display a book description instead of just a book id.
  5. Make the web page pretty.

These will all be converted to stories, and we will verify that each one makes the system more real in a user-visible way. They aren’t perfect; some of the slices depend on the result of earlier slices, so we can’t parallelize across all 5 of them, and we will still need to have some coordination around the changes we make. These issues are more tractable, however, because they are in relation to a working system; discussions happen in the context of actual working code that both parties understand, and it’s easy to tell if there are issues because the system is working.

Rational behavior and the Gilded Rose kata…

July 10, 2014 at 1:03 pm

The following is based on a reply to an internal post that I almost wrote this morning, before I decided that it might be of more general interest. It will take a little time to get to my point so perhaps this would be a good time to grab whatever beverage is at the top of your beverage preference backlog.

Are you back? Okay, I’ll get started…

A while back my team spent an afternoon working on the Gilded Rose kata. We used it to focus on our development skills using a pairing & TDD approach. This kata involves taking a very tangled routine (deliberately tangled AFAICT) and extending it to support a new requirement. It is traditionally viewed as an exercise in refactoring, and in the introduction to the kata, I suggested that my team work on pinning tests before refactoring or adding new functionality. My team found the kata to be quite enjoyable, as it involved a puzzle (unraveling the code) and the opportunity to work on code that is much worse than our existing codebase.

This week, another team did the String Calculator kata (a nice introduction to katas and one that works well with pairing/TDD), and somebody suggested that Gilded Rose would be a good next step. I started to write a quick reply, which became a longer reply, which then evolved into this post.

My initial reply was around how to encourage people to take the proper approach (if it’s not obvious, the “proper” approach is the one I took when I last did the kata…) – which was “write pinning tests, refactor to something good, and then add new functionality”. When writing it, however, it seemed like I was being overly prescriptive, and it would make more sense to remind people of a general principle that would lead them to a good approach.

At this point, I realized that I had a problem. Based on the way the kata is written, I was not longer sure that my approach *was* the proper choice. The reason is that the kata provides a detailed and accurate description of the current behavior of the system and the desired changed behavior. After a bit of thought, I came up with four alternatives to move forward:

  1. Attempt to extract out the part of the code that is related to the area that I need to change, write pinning tests for it, and then TDD in the new functionality.
  2. Write pinning tests on the current implementation, refactor the code, then add new functionality.
  3. Write pinning tests on the current implementation, write new code that passes all the pinning tests, then add new functionality.
  4. Reimplement the current functionality from scratch using TDD and based on the detailed requirements, then add new functionality.

Which one to choose?

Well, the first one is something I commonly do in production code to make incremental changes. You can make things a little better with a little investment, and many times that’s the right choice WRT business value. If you want more info on this approach, Feather’s “Working Effectively With Legacy Code” is all about this sort of approach. It’s one of the two books that sits on my desk (anybody want to guess the other one?).

Presuming that a kata that I finish quickly isn’t really my going, that leaves me with three options. My experience says that, if I have the Gilded Rose code and a complete specification of the desired behavior, I’m going for the last option. The problem isn’t very complex and, doing TDD is going to be straightforward, so I’m confident that I can get to an equivalent or better endpoint with less effort than dealing with refactoring the existing code.

That conclusion was a bit surprising to me, given that this is commonly thought to be a refactoring kata, but it’s the logical outcome of having a perfect specification for the current functionality available. Last year I had the chance to fix a buggy area of code that handled UI button enabling/disabling, and I took this exact approach; I knew what the functionality would be, wrote a nice clean class & tests, and tossed the old code out. Worked great.

In reality, however, this case is somewhat rare; most times you just have the code and your requirement is to add something new without changing the existing behavior, whatever it might be. Or, you have some requirements and some code, but the requirements are out of date and don’t match the code. So… I think the Gilded Rose kata would be a lot better if you didn’t have the description of the current behavior of the system, because:

  1. That’s when pinning becomes important, to document the existing behavior.
  2. Automated refactoring becomes more interesting because it allows me to make *safe* changes even if my tests aren’t perfect.
  3. I get led towards these approaches automatically.

If I don’t have the description, I’m going to choose between the last two approaches. The tradeoff likely depends on how good my pinning tests are; if they are perfect I should just choose the option that is quicker. If they are less than perfect – which is generally going to be the case – then doing it through refactoring is likely a better choice.

Or, to put it another way, the effort to write a reasonable set of pinning tests and refactor the code is generally going to be less than the effort to write a perfect set of pinning tests and write the code from scratch.

Small in, Big out

November 19, 2012 at 4:52 pm

I’ve come across some code that is using – and overusing – IEnumerable<T>, and thought it might be of general interest.

Consider the following method signatures:

IEnumerable<string> Process(List<string> input);

IList<string> Process(IEnumerable<string> input);

Of the two, which is the better choice? Write down your answer.

There are really two questions – what is the best choice for input parameters, and what is the best choice for return values. I’ll cover them separately:

Small In

The input parameter should be the smallest (ie least functional) type that allows the method to efficiently do what it needs to do. I’ve seen methods like this:

void Process(List<string> input)
{
    foreach (string in input)
    {
        …
    }
}

(or maybe the Linq equivalent).

In this case, you are just making things harder for the caller; all you really need is an IEnumerable<string>, so that’s what you should specify. On the other hand, I’ve also seen code like this:

void Process(IEnumerable<string> items, IEnumerable<ReferenceItem> referenceItems)
{
    var lookup = referenceItems.ToDictionary(referenceItem => referenceItem.Name, referenceItem => referenceItem.Contents)’
    …
}

This code takes a simple enumerable, and constructs a dictionary out of it. This is worse than the first case; if you need a dictionary, ask for a dictionary.

Big Out

Output parameters should be the biggest (ie most functional) type that is acceptable for the scenario. I’ve seen methods like this:

IEnumerable<string> Process(List<string> input)
{
    List<string> items = new List<string>();

    // fill list here

    return items;
}

The developer has created a beautiful, functional list object, but they’re only going to let the caller enumerate over it. This often leads to my favorite outcome, where the caller writes something like:

List<string> items = new List<string>(myClass,Process(input));

Don’t do that. Just return the List<string> or perhaps the IList<string>.

Return values aren’t as cut-and-dried as input parameters, however. If we modify the previous example as follows:

IList<string> Process(List<string> input)
{
    m_items = new List<string>();

    // fill list here

    return m_items;

In this example, the class is retaining ownership of the list, and in that case, it probably doesn’t want to give it out to somebody who could clear it, or replace all the strings with the string “Haddock”. If the class is going to retain ownership, it should use a return type that prevents bad things like that from happening.

Metricism

July 12, 2010 at 9:21 am

Your neologism for the day…

Metricism

A devotion to creating and implementing metrics for a system or process while loosing sight of the real goal.

Examples:

  • Evaluating software developers on how many bugs they fix.
  • Evaluating newsgroup interaction quality based on the percentage of posts answered in the first day.

Thoughts on “Thoughts on TDD”…

April 19, 2010 at 10:46 am

Brian Harry wrote a post entitled “Thoughts on TDD” that I thought I was going to let lie, but I find that I need to write a response.

I find myself in agreement with Brian on many points in the post, but I disagree with his conclusion.

Not surprisingly, I agree with the things that he likes about TDD. Focusing on the usage rather than the implementation is really important, and this is important whether you use TDD or not. And YAGNI was a big theme in my “Seven Deadly Sins of Programming” series.

Now, on to what he doesn’t like.

He says that he finds it inefficient to have tests that he has to change every time he refactors.

Here is where we part company.

If you are having to do a lot of test rewriting (say, more than a couple of minutes work to get back to green) *often* when you are refactoring your code, I submit that either you are testing things that you don’t need to test (internal details rather than external implementation), your code perhaps isn’t as decoupled as it could be, or maybe you need a visit to refactorers anonymous.

I also like to refactor like crazy, but as we all know, the huge downside of refactoring is that we often break things. Important things. Subtle things. Which makes refactoring risky.

*Unless* we have a set of tests that have great coverage. And TDD (or “Example-based Design”, which I prefer as a term) gives those to us. Now, I don’t know what sort of coverage Brian gets with the unit tests that he writes, but I do know that for the majority of the developers I’ve worked with – and I count myself in that bucket – the coverage of unit tests written afterwards is considerably inferior to the coverage of unit tests that come from TDD.

For me, it all comes down to the answer to the following question:

How do you ensure that your code works now and will continue to work in the future?

I’m willing to put up with a little efficiency on the front side to get that benefit later. It’s not the writing of the code that’s the expensive part, it’s everything else that comes after.

I don’t think that stepping through test cases in the debugger gets you what you want. You can verify what the current behavior is, sure, and do it fairly cheaply, but you don’t help the guy in the future who doesn’t know what conditions were important if he has to change your code.

His second part that he doesn’t like backing into an architecture (go read to see what he means).

I’ve certainly had to work with code that was like this before, and it’s a nightmare – the code that nobody wants to touch. But that’s not at all the kind of code that you get with TDD, because – if you’re doing it right – you’re doing the “write a failing tests, make it pass, refactor” approach. Now, you may miss some useful refactorings and generalizations for this, but if you do, you can refactor later because you have the tests that make it safe to do so, and your code tends to be easy to refactor because the same things that make code easy to write unit tests for make it easy to refactor.

I also think Brian is missing an important point.

We aren’t all as smart as he is.

I’m reminded a bit of the lesson of Intentional Programming, Charles Simonyi’s paradigm for making programming easier. I played around with Intentional Programming when it was young, and came to the conclusion that it was a pretty good thing if you were as smart as Simonyi is, but it was pretty much a disaster if you were an average developer.

In this case, TDD gives you a way to work your way into a good, flexible, and functional architecture when you don’t have somebody of Brian’s talents to help you out. And that’s a good thing.

The power of “ouch”…

March 25, 2010 at 12:06 pm

From my bicycle blog…


Three of them

The power of “no”…

December 1, 2009 at 10:25 am

Eric Brechner wrote an interesting post titled “Don’t panic“, about how to deal with requests. I sometimes agree and sometimes disagree with what Eric writes, but it’s usually a pretty good read.


In this case, I agree with his approach, but disagree with his advice.


He advocates that when anybody comes with you for a request, your first response should always be “Yes, I’d be happy to help”.  Which is wrong.


Way back when my daughter was 4, I was sitting on the couch and she came and asked me for something. My memory is a bit hazy on what she asked for, but I think it was some sort of snack. I didn’t think deeply about it, and made a quick decision and answered “no”. She got pretty upset and started crying and asked again.


At that point I had a quandry. I thought about it a bit more, and realized that her request was a reasonable one (lunch was a long time ago) and that there was really no reason to grant it, but I knew that I couldn’t because at that point is wasn’t about the request but instead was about the way it was asked and the pattern me changing my mind would set. I didn’t want to set up a behavior where getting upset and crying is expected to make your dad change his mind. So I held firm.


And felt really bad about it, because I made the wrong initial call.


The whole point of the story – assuming that there is a point – is that you need to look not at the current interaction but instead at the meta-level. What message is your response sending? What pattern of interaction is it reinforcing?


If somebody comes and asks you to do something and you say, “yes”, once that word leaves your lips you can assume that the person making the request will think that they are getting everything they want from you. They have in mind a big feature delivered on an impossible date, and your job then becomes trying to scope their expectations down to something manageable, but even if you succeed they’ll still be stuck on what they originally had in mind, and will be disappointed with you.


Not to mention the fact that if you immediately say “yes”, it seems like you’re either working on unimportant stuff and/or not working hard enough.


The right thing to do is to say “no”, but in the right way. Something like “I’m/we’re currently booked and have a lot of high-priority work planned, so I think that would be hard to fit in, but let me understand exactly what you’re asking”. That puts the requester in the position of having to convince you of the importance of what they want to do and be able to explain the details coherently.


At that point, you can start the nuanced discussions that Eric talks about – talking about the details of what they want, why they think it’s important, etc. It becomes very clear very fast whether the requester has done his homework, and if they haven’t you can point out the additional things he needs to figure out before you talk more. If he has done her homework, you can discuss where you think the feature ranks (always subject to the approval of whoever approves features), and how it might be broken apart/modified to bring it in earlier.


At that point, the answer usually becomes, “yes, we can do <x> in timeframe <y>”, which makes the requester happy – you’ve spent the time to explain to them why you put a specific priority on the request and you’ve made your life harder by rearranging things to slot their request into your current schedule and (probably) taking on the task of explaining to everybody who’s below the new feature’s priority why they aren’t getting what they expected.


And, you’ve set up a healthy pattern of behavior. Requesters are likely to do a bit of homework before they talk to you, and you are busy but willing to take on new work if it makes sense to do so.


And that’s the power of “no”.

Thoughts on agile design and platforms

August 14, 2009 at 2:47 pm

I started by writing a broad post about design, and it got away from me (apparently I should have spent some time designing the post first…), so I deleted it all and decided to write something shorter, and, with any luck, more understandable and useful.

I’ve been reading some discussions about how design relates to Agile. Some teams get into trouble because they think that agile means “no design”, when in fact it means “right design”.

The whole point of design in my mind is to save you work later on. There’s a sweet spot between no design and big design that makes sense in a particular situation. I don’t think that’s a unique insight at all, though I have seen groups how use the “design document” approach where there’s a document with 18 sections in it that everybody has to use.

The two areas I would like to talk about are about what you are building and the scope of what you are doing right now. I’ll talk about scope first.

The amount of design you should do depends on the scope of what you are doing, and scope in this situation doesn’t mean “amount of code change” (though it often correlates somewhat with that), it means “impact of code change on the customer”. This is obviously different for every change you make to the code, and my general guideline is that spending 5 minutes bouncing your thoughts off of somebody else generally gives you a good enough conclusion about how much design is required. Notice that I said “guideline” – I expect that developers can use their best judgement about when they can make changes without consulting with others.

Some people would say that not having the opportunity to make a wrong choice about when to consult with others is a strength of pair programming. I think that’s probably true, but obviously only works for teams that do pair, and that’s not that common in my neck of the woods (and, I suspect in others).

So, anyway, that’s what I think about scope, and, once again, I don’t think it’s a unique insight.

My second point – that the amount of design depends on what you are building – is something I haven’t heard talked about much, especially in agile circles. Because most software developers deliver applications, the agile processes are described in that context.

And in that context, I think that many developers do far too much design up front. You can spend 3 days writing something up that covers how you will do something, or you can spend 2 days doing early implementations and then know which one works better, and have real code to show people. Trying to figure out how things should work before you write them is often less efficient than just writing them when you need them.

Given that I consider premature generalization to be the #1 sin of developers, no surprises there.

But – and I think I may be finally getting to the point – that perspective comes from applications, where you own the code that you’re building, and refactorings can be done when you learn more.

Platforms are different.

If you are building a platform, things get a bit schizophrenic. Internally, you are an application – you can refactor the internals without a lot of impact elsewhere, and therefore the amount of design you do should keep that in mind.

But externally, people depend on your APIs to stay the same. This means that, for a given feature, you need to get it right (or as close to right as you can) on your first release. It also means that you need to think about how the feature that you’re doing right now might be extended for things you might do in the future.

Which is exactly the thing that you shouldn’t be doing if you’re building an app, because it’s a pain, it’s expensive, you’ll make the wrong choices, and you’ll have to throw work away.

In my current team, we own both applications and platform API, so we get to spend time in both of these areas.

And now it’s lunchtime. I may write a future post on how I think you should do platform design.