DaedTech

Stories about Software

By

More and More With TDD

TDD Revisited Again

Previously I blogged about TDD with some reservations and then later as I re-introduced myself to the pure practice as I had learned it some many moons ago. For the last month, I have been plowing ahead methodically with this experiment, and I thought I’d revisit some of my thoughts from earlier.

Reinforced Pros

First off, the pros still stand in my mind, but I’d like to add one enormous additional pro, which is that you get code right the first time. I mean, really, really right. Right as in coding for a few days without ever running the application you’re working on, and then firing it up and having it work flawlessly the first time you run it.

And, I’m not talking about plodding along with some tiny development exercise like scoring a bowling game. I mean, I recently wrote an application that would parse a text file, format and filter records, and insert the result in a database. Using a combination of Moq for my internal seams and Moles for external concerns (file and database), I exhaustively tested everything I wanted to do as I went, following the red-green-refactor process to the letter. After some hours here and there of working on this (shaking off my TDD rust being part of the time spent), I finally hit F5 and it worked. My files were parsed, my databases updated, my log file written accurately. This wasn’t a fluke, either, because I repeated the process when I wrote another utility that piggy-backed on this first one to send out emails with the results. I wrote an API for setting up custom mail messages, dependency injection for different mail clients, and wireup code for integrating. Never once did I step through the debugger trying to figure out what network credential I had missed or which message was missing which formatting. I put the finishing touches on it with my tests passing and code coverage at 100%, hit F5 and had a well-formed, perfect message in my inbox before I even looked away from my screen, expecting to be kicked into the debugger. That is a remarkable pro.

I mean, think of that. If you’re a skeptic about TDD or unit testing in general, you’ve probably never experienced anything like that. If you have, that’s amazing. I don’t know anyone that doesn’t develop in this fashion that has this happen. I mean, people who are really sharp get it mostly right, and sometimes just have to tweak some things here and maybe step through a few functions a few times, but without ever running the code? I’m not buying it. And even if they did, I come out way ahead this way. A non-tested code base is going to be harder to modify. I have hundreds of passing tests now that will tell me if subsequent changes break anything.

Cons Mitigated

So, I’d like to take a look back at the cons, and revisit my opinions after a month of doggedly sticking with TDD:

  1. Larger design concepts do not seem to be emergent the way they might be in a more shoot from the hip approach — figuring out when you need a broader pattern seems to require stepping out of the TDD frame of mind
  2. There is no specific element of the process that naturally pushes me away from the happy path — you wind up creating tests for exceptional/edge cases the way you would without TDD (I guess that’s not strictly a con, just a lack of pro).
  3. It becomes easier to keep plodding away at an ultimately unworkable design – it’s already hard to throw work you’ve put in away, and now you’re generating twice as much code.
  4. Correcting tests that have been altered by changing requirements is magnified since your first code often turns out not to be correct — I find myself refactoring tests as often as code in the early going.
  5. Has the potential to slow development when you’re new to the process — I suppose one might look at this as a time investment to be paid off when you get more fluid and used to doing it.

Regarding (1) and (3), this seems not to be the issue that I thought it would be. I had grown used to a fast flurry trying out a class concept, and realizing what refactorings needed to be done on the fly, causing it to morph very quickly. I had gotten very proficient at ongoing refactoring without the red-green preceding it, so, in this way, I was able to ‘fake’ the TDD benefit. However, I realized a paradoxical benefit – TDD forced me to slow down at the beginning. But rather than really slowing me down on the whole, it just made me toss out fewer designs. I still refactor with it, but it isn’t necessary as often. The TDD forces me to say “what do I want out of this method/class” rather than to say “what should this do and how should it relate to others”. The difference is subtle, but interesting. The TDD way, I’m looking at each method as an atom and each class as a unit, whereas the other way I’m putting the cart a bit before the horse and looking at larger interactions. I thought this was a benefit, but it resulted in more scratch out work during prototyping than was really necessary. I was concerned that TDD would force me to throw away more code because I’d be tossing tests as well as code, but in reality, I just toss less code.

Regarding (2), this has sorted itself out as well. TDD does tend to lead you down the happy path as you’re using it to incrementally correct and refine a method’s behavior, but there’s nothing that stops you from tossing in along with that a thought of “how do I want this to handle an exception in a method that it calls?” This, I’m finding is a discipline and one that I luckily brought with me from testing after or testing during. It is not incompatible with TDD, though TDD does help me not get carried away focusing on corner cases (which can be ferreted out with tools like Pex or smoke tests later).

Regarding (4), this has also proved not to be too much of an issue, though I have seen a touch of this. But, the issue really comes in when it turns out that I don’t need some class, rather than a swath of tests. TDD helps my classes be better thought out and more decoupled, and so, I’ve found that when I’m cutting things, it tends to be surgical rather than a bloodbath.

Regarding (5), this is true, but I’ve fought through the burn. However, there is another thing that goes on here that I’d point out to people considering a foray into TDD. Imagine the scenario that I described above, and that you’re the non-TDD hare and I’m the TDD tortoise. I’m plodding along, red-green-refactoring my parser when you’ve finished yours. You’re probably running it on an actual file and making changes while I’m still working methodically. By the time I’m finished with my parser and doing the formatting, you’ve got your formatting finished and are working on the database. By the time I get to the database, you’ve already got things working 90%, and are busy stepping through the debugger and cursing the OleDbCommand API.

But, that’s where things start to get interesting. Often times, in my experience, this is the part of development that has you at the office late, pulling your hair out. The application is 90% done at 4:00, and you’re happy because you just need to make a minor tweak. Suddenly, it’s 8:00 and you’re hungry and cranky and cursing because no one is left in the office. That’s a brutal 4 hours specifically because you imagined in to be 20 minutes at 4:00. But, let’s say you finally get it and go home. I’ll finish an hour or so after you and you win the first leg of the race, though I’ll do it without a lot of fanfare and frustration, since I’m never hitting snags like that with my methodical process.

But now, an interesting thing happens. We send our versions out for Beta testing, and the issues start coming back. You have your own knowledge of your code to go on as you fix defects and perform minor refactorings, while I have 100% code coverage. I quickly find issues, fix them, see all green and am ready to deliver. You quickly find issues, fix them, and then run the application a bunch of times in different scenarios trying to ferret out anything that you could possibly have broken. I’m gaining on you fast. And, I’m going to keep gaining on you as the software grows. If Beta lasts more than a short time, I’ll win. If there are multiple versions of the software, I’ll win easily. At some point, I’ll lap you as you spend way more time repairing defects you’re introducing with each change than fixing the one you set out to fix. The time investment isn’t new TDD versus seasoned TDD. It’s a little time up front for a lot of time later.

Eating Crow

I had tried TDD in the past, but I think I wasn’t ready or doing it right. Now, I’m convinced that it’s definitely the path for me. Somewhere, I saw a presentation recently that mentioned sort of an arc of unit testing. People tend to start out with test-last, and then move to test during, then test-first and then test-driven, according to this presentation (I wish I remember whose it was so I could link and give credit). I think my previous issue was that I had short circuited the arc and was trying to assimilate too much all at once. If you’re a developer trying to convince others of the merits of unit tests, TDD might be a lot to spring on them up front.

I was thinking about why that might be, and something occurred to me from way back in my undergrad days. The first thing we all tend to do is want to write all of the code at once. Since we’re given small assignments to start, this works. It’s hard to turn bubble sort into a lot of different feedback passes — you write the whole thing and then debug the ‘finished’ product. As classes get harder, you try to keep this dream alive, but at some point you have the “aha” moment that you need to get shorter feedback cycles to prevent assembling the whole thing and getting it all wrong. So, you do this by making your code modular and developing components. That carries you through into the early part of your career, and you have a natural tendency to want to get code up and running as quickly as possible for feedback. Then, TDD comes along and changes the nature of the feedback altogether. You’re no longer getting the feedback from your running application, but from your unit tests of small components. So, if you’re building a house app, you don’t start with the House class and run it. Instead, you start with a “Bedroom” class, or even a “Bed” class. While your counterparts are adding rooms to their running houses, you’re getting your “Bed” class working flawlessly. And, while they’re cobbling furniture into their rooms, you’re assembling rooms from their furniture. When they’re debugging, you’re finally ready for your first “F5” feedback. But, you haven’t come full circle and turned into that freshman with bubble sort – you’ve gotten real feedback every 30 seconds or so. You’ve gotten so much feedback, that there’s little anticipation with the first real run of the component you’re working on for that week. You’re pretty sure it’s going to work and you’re going to be heading home at 5:00.

So, yeah, I guess I’m a TDD convert, and will eat some crow for my earlier posts.

By

Using Moles with the System Assembly

Short but sweet post tonight, and I’m mostly putting this here for reference. It’s annoyed me a few times, and each time I have to google around until I find something like this stack overflow post.

If you add a moles assembly for System, unlike other framework assemblies, building your test project will blow up spectacularly with too many compiler errors to count. I don’t know all the whys and wherefores, but I do know that it’s easily remedied as hveiras says. You simply change:


  

to


  

in your System.Moles file that’s generated. That’s it.

Philosophically, it seems like a bit of an oversight that this would be necessary, as this never fails to fail out of the box. There may be something I’m missing, but it seems like it’d be nice if this attribute were added by default for the System Assembly. In any case, I (and you) have it here for posterity now, though probably the act of explicitly typing it out has rendered it moot for me, as documenting things usually makes me remember them and not need my documentation… which reminds me – I’m probably about due for a periodic re-reading of one of my all time favorite books.

By

Builder

Quick Information/Overview

Pattern Type Creational
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Relatively easy.

Up Front Definitions

Here are terms that I’ll be using in this explanation and what they mean:

  1. Composite: This is another design pattern, but I’m using it here to mean an object that is composed of other objects.

The Problem

For this design pattern, I’ll use the example of modeling computers. A computer is a classic example of a composite object. That is, a computer object isn’t just a collection of simple literals, but is actually composed of other objects in your domain (most likely anyway, and it will be in the example).

So, let’s say that you get an assignment to model computer composition and pricing, perhaps for a website for a store that builds custom rigs. For a proof of concept, let’s say that you very much oversimplify things and decide to create an implementation where a computer has memory, a CPU, and a motherboard.

Now, since we’re modeling price rather than actual operation, it’s important to keep in mind that the abstraction for actual computer construction and sales is limited to “what will work with what” rather than modeling the actual interaction. So, if CPU X doesn’t work with motherboard Y, you don’t want to sell that combination. But, worrying about the details of how CPU x works with motherboard Y is beyond the scope of this application. Another thing to consider here is that all components have a price, and the assembled machine will have a price that equals the sum of its components, perhaps with a cost of assembly added as well.

Now, let’s also assume that there is a dependency relationship in ordering how machines are built. That is, you have an external requirement of some sort that the motherboard must be chosen first, followed by the CPU, and then by the memory. So, you create objects for your components and a computer object, and it looks something like the following (remember, this is an example and an example of a POC at that – let’s not get too immersed in the details)

public abstract class Cpu
{
    public int Cores { get; set; }
    public int ProcessorSpeed { get; set; }

    public abstract double Price { get; }

    public virtual bool IsCompatibleWith(Memory memory)
    {
        return true;
    }
}

public class Intel : Cpu 
{
    public override double Price { get { return 300.00; } }
}
public class Athalon : Cpu 
{
    public override double Price { get { return 140.00; } }
}
public abstract class MotherBoard
{
    public int PciSlots { get; set; }
    public int IdeSlots { get; set; }

    public abstract double Price { get; }

    public virtual bool IsCompatibleWith(Cpu cpu)
    {
        return true;
    }

    public virtual bool IsCompatibleWith(Memory memory)
    {
        return true;
    }
}

public class Acer : MotherBoard
{ 
    public override double Price { get { return 200.00; } } 
}
public class IntelMobo : MotherBoard 
{ 
    public override double Price { get { return 500.00; } } 
}
public abstract class Memory
{
    public int Slots { get; set; }
    public int CapacityPerSlot { get; set; }

    public abstract double Price { get; }
}

public class Crucial : Memory 
{ 
    public override double Price { get { return 100.00; } 
    } 
}
public class Kingston : Memory 
{ 
    public override double Price { get { return 200.00; } } 
}

And, finally, the computer:

public class Computer
{
    private MotherBoard _motherboard;
    private Cpu _cpu;
    private Memory _memory;

    public double GetPrice()
    {
        return _memory.Price + _cpu.Price + _motherboard.Price; //Fails if anyone is null
    }
        
    public bool AddMotherboard(MotherBoard motherboard)
    {
        _motherboard = motherboard;
        return true;
    }

    public bool AddCpu(Cpu cpu)
    {
        if (_motherboard == null || !_motherboard.IsCompatibleWith(cpu))
        {
            return false;
        }
        _cpu = cpu;
        return true;
    }

    public bool AddMemory(Memory memory)
    {
        if (_motherboard == null || !_motherboard.IsCompatibleWith(memory) ||
            _cpu == null || !_cpu.IsCompatibleWith(memory))
        {
            return false;
        }
        _memory = memory;
        return true;
    }
}

And, life is good. You have a computer class that can have components added to it in the proper order, with each add returning false if you’ve made an oops. The compatibility standards are a little permissive at the moment, but, remember, POC.

So, the next thing that you’d do is actually set about building these computers, presumably based on user input. The user would first choose a MOBO, and you’d add it to an empty computer object. Then, the user would choose a CPU, and you’d flag an error message if trying to add that didn’t work, or add it if it did, and life would still be good.

But, let’s say that you want to add some functionality to let the user select some pre-assembled machines and then, perhaps customize them. So, you get the first spec in and, no problem, you add it, perhaps to the presentation layer class for backing the view of the computer building screen (remember, POC 🙂 ):

public Computer BuildBudgetComputer()
{
    var myComputer = new Computer();
    myComputer.AddMotherboard(new Acer());
    myComputer.AddCpu(new Athalon());
    myComputer.AddMemory(new Crucial());

    return myComputer;
}

There you go – you’ve got a method in the class that builds a budget computer, pre-assembled for selection, allowing users to build their own or take your canned construction. Then, a requirement for another pre-configured one comes in, and you dutifully add it:

public Computer BuildBudgetComputer()
{
    var myComputer = new Computer();
    myComputer.AddMotherboard(new Acer());
    myComputer.AddCpu(new Athalon());
    myComputer.AddMemory(new Crucial());

    return myComputer;
}

public Computer BuildExpensiveComputer()
{
    var myComputer = new Computer();
    myComputer.AddMotherboard(new IntelMobo());
    myComputer.AddCpu(new Intel());
    myComputer.AddMemory(new Crucial());

    return myComputer;
}

The two methods look pretty similar, but you’re doing a POC, so you choose not to sweat the small stuff, like “Don’t Repeat Yourself”. Now, each time you want to add new preconfigured computer, you have a design pattern. All you have to do is copy one of those methods and put different objects in the Add() calls.

Now, let’s fast forward a few months. After explaining that this was just a POC to management, management decides to ship the POC since it’s working so well. In the interim, you’ve gotten requirements to add hard drives, USB hubs, monitors, keyboards, mice, etc. You also now have to offer hundreds of pre-built computers to the users, along with the coolness of building their own.

Now, along comes an interesting new requirement. Instead of picking the MOBO first, the users now have to pick the CPU first. So, you switch the method preconditions for the AddCpu() and AddMotherboard() methods in Computer, run your unit tests/application, and discover that nothing works. D’oh! You’re still building them in the same order. You just need to switch the order of the client calls to AddMotherboard() and AddCpu(), and…. oh. You need to go through hundreds of methods doing this. Ouch…

So, What to Do?

At this point, “what to do” requires an examination of “what went wrong?” Everything here was a little slapdash, but relatively reasonably constructed. There was no obvious step where things got out of hand, and yet you suddenly have a mess. As it turns out, you have a mess that was completely avoidable.

Think back to the step where we copy/pasted some code and how that didn’t feel right. Well, turns out it wasn’t right (hint: it’s pretty much never right — Don’t. Repeat. Yourself. ). That little concession early in the game led to big problems later. We duplicated the logic of ordering the construction of the computer over and over again.

What could we have done instead? Well, builder pattern to the rescue. Let’s rewind to when we just had our computer and components, and our first method for a canned computer. Taking another look at that method, we see:

public Computer BuildBudgetComputer()
{
    var myComputer = new Computer();
    myComputer.AddMotherboard(new Acer());
    myComputer.AddCpu(new Athalon());
    myComputer.AddMemory(new Crucial());

    return myComputer;
}

Looking at this a bit more abstractly, we have a method that accepts no parameters and returns a computer object. Hard-coded in there are various derived polymorphs that are specific to this particular construction. Also hard-coded in there is obeying the temporal coupling between the different add operations. So here, we’re doing two things — defining which components will be added, and defining the order in which they are added. Now, when we define our next implementation via copy/paste, we’re duplicating the ordering logic but giving different specific objects. What if, instead of coupling these two things, we introduced an abstraction:

public Computer BuildBudgetComputer(Motherboard motherboard, Cpu cpu, Memory memory)
{
    var myComputer = new Computer();
    myComputer.AddMotherboard(motherboard);
    myComputer.AddCpu(cpu);
    myComputer.AddMemory(memory);

    return myComputer;
}

Now, BuildComputer() just encapsulates the logic for navigating the temporal coupling. It’s up to somebody else which components it should be given. This is already a vast improvement and a solution to the problem that we created. Now, client code is making calls like:

public Dictionary BuildPreassembledComputers()
{
    var myComputers = new Dictionary();
    myComputers["Budget"] = BuildComputer(new Acer(), new Athalon(), new Crucial());
    myComputers["Expensive"] = BuildComputer(new IntelMobo(), new Intel(), new Crucial());

    return myComputers;
}

public Computer BuildComputer(MotherBoard motherboard, Cpu cpu, Memory memory)
{
    var myComputer = new Computer();
    myComputer.AddMotherboard(motherboard);
    myComputer.AddCpu(cpu);
    myComputer.AddMemory(memory);

    return myComputer;
}

Now, we’ve solved our main initial problem where the logic for the ordering of computer construction being strewn all over the place. With this code, we have one method to change: BuildComputer(), rather than hundreds.

But, we still have a subtle problem. Recall that we’d talked about now having additional components like monitors and hard drives, and we have hundreds of pre-canned combinations. Think about what BuildPreassembledComputers() is going to look like. It’s going to contain hundreds of permutations of parts, named only by the key in that dictionary. Every time you want to add a new pre-assembled computer, you’re going to have to open that class and add a line to that gargantuan method. If some of the computers become obsolete, you’re going to have to remove them from that method. That is, a the composition of a “budget” computer is going to change over the course of time as new parts come out and old ones become obsolete. Why should your presenter/controller/ViewModel have to change when that happens? At some point, you’re going to have to tie the particular computer to some hard-coded name, but it needn’t be there.

So, let’s extrapolate to something a little closer to the builder pattern.

public abstract class AlmostBuilder
{
    public abstract Computer BuildComputer();

    protected Computer AssembleComputer(MotherBoard motherboard, Cpu cpu, Memory memory)
    {
        var myComputer = new Computer();
        myComputer.AddMotherboard(motherboard);
        myComputer.AddCpu(cpu);
        myComputer.AddMemory(memory);

        return myComputer;
    }
}

public class BudgetBuilder : AlmostBuilder
{
    public override Computer BuildComputer()
    {
        return AssembleComputer(new Acer(), new Athalon(), new Crucial());
    }
}

public class ExpensiveBuilder : AlmostBuilder
{
    public override Computer BuildComputer()
    {
        return AssembleComputer(new IntelMobo(), new Intel(), new Crucial());
    }
}


public class Client
{
    public Dictionary BuildPreassembledComputers()
    {
        var myComputers = new Dictionary();
        myComputers["Budget"] = new BudgetBuilder().BuildComputer();
        myComputers["Expensive"] = new ExpensiveBuilder().BuildComputer());

        return myComputers;
    }
}

Now, we’re onto something. The builder base class encapsulates a method where the temporal coupling is defined exactly once. The derived builders have the responsibility for defining exactly which components are part of the computer that they’ll return. And, the presentation layer class has the responsibility only for presenting things to the user. It knows what kind of computer it wants, and it delegates the construction totally – both the temporal coupling of the construction and the components used in assembly.

The derived classes have only the responsibility of determining which parts will be added to the composite, and the base class’s Assemble() method has the sole responsibility for navigating the assembly particulars. This solves the issue of modifying a method in a presentation class over and over again and an implied violation of the Open/Closed principle. Now, if we want to define a different building paradigm we can define a new class that derives from AlmostBuilder base class. Of course, somewhere or another we will need to add a line of creation code for that, but it won’t be here in the presentation layer, and we probably already have a creational pattern for that somewhere (like a factory).

Now, to get to the bonafide pattern, we define a “Director” class and different Builders expose methods like “BuildMemory()”, “BuildCpu()” and “BuildMotherBoard()”. The Director takes a builder polymorph as an argument and use its different members to assemble the composite.

public class Director
{
    public Computer BuildComputer(Builder builder)
    {
        var myComputer = new Computer();
        myComputer.AddMotherboard(builder.BuildMotherboard());
        myComputer.AddCpu(builder.BuildCpu());
        myComputer.AddMemory(builder.BuildMemory());

        return myComputer;
    }
}

public abstract class Builder
{
    public abstract Memory BuildMemory();

    public abstract Cpu BuildCpu();

    public abstract MotherBoard BuildMotherboard();
}

public class BudgetBuilder : Builder
{
    public override Cpu BuildCpu()
    {
 	    return new Athalon();
    }

    public override Memory BuildMemory()
    {
        return new Crucial();
    }

    public override MotherBoard BuildMotherboard()
    {
        return new Acer();
    }
}

public class ExpensiveBuilder : Builder
{
    public override Cpu BuildCpu()
    {
        return new Intel();
    }

    public override Memory BuildMemory()
    {
        return new Crucial();
    }

    public override MotherBoard BuildMotherboard()
    {
        return new IntelMobo();
    }
}


public class Client
{
    public Dictionary BuildPreassembledComputers()
    {
        var myComputers = new Dictionary();
        var myDirector = new Director();
        myComputers["Budget"] = myDirector.BuildComputer(new BudgetBuilder());
        myComputers["Expensive"] = myDirector.BuildComputer(new ExpensiveBuilder());

        return myComputers;
    }
}

I didn’t show this until just now because I wanted to go through the series of mental leaps and abstractions that would lead us to this point. It may not be necessary at first to launch into an all out implementation. There are steps along the way, and each introduces a new degree of abstraction that’s great and helpful as long as it’s not overkill.

This full blown builder pattern has all of the previous advantages, and the addition of the Director both adds complexity and customizability. You can now inject the director and/or the builders into your presentation class for maximum flexibility.

I’d also like to note that you can use this pattern to do some cool stuff with fluent interfaces. Imagine if the builders, instead of returning their components, all returned new Computer objects (assuming Computer had some kind of copy constructor or clone method). You would have an interface like

var myExpensiveComputer = myBuilder.AddMotherboard(new IntelMobo()).AddCpu(new Intel()).AddMemory(new Crucial());

A More Official Explanation

So pulling back for a moment, let’s consider what we’ve really done here. What got us into trouble was having the methodology of the construction of our composite object, computer, mixed together with the definition of the composite components themselves. To speak plainly, we mixed the how with the what.

According to wikipedia, the main purpose of the Builder Pattern is “to abstract steps of construction of objects so that different implementations of these steps can construct different representations of objects”. Again, this describes separating the how (“construction of objects”) from the what (“different representations of the objects”).

Other Quick Examples

Other examples of using the builder pattern might include:

* You have some object that provides all of the services for your application and you want to supply different services for different runtime configurations, and you want to separate selection of the services from building and instantiating them.
* You’re modeling a pizza delivery service and you want to offer customizable pizzas but also some pre-defined ones that change perhaps by season or specials of the week or something.
* You’re assembling a multi-level composite.

A Good Fit – When to Use

More generally, a good heuristic for when to use the builder pattern is when construction of an object is complicated. In my experience, builder is generally appropriate if and only if you’re building a composite object, though YMMV. So, you might want to consider a builder pattern usage if your composite has temporal coupling as to how it needs to be built. You might also want to do it if your composite can have different configurations.

But, the most important and subtle point here is that you want to do this when there’s some notion of wanting to define discrete assembly characteristics – some assemblies work together but not others according to your business rules. In this sense, you’re separating business rules for valid configuration from the actual nuts and bolts construction of the object.

Square Peg, Round Hole – When Not to Use

Conversely to the idea of discrete assemblies, it’s not a good idea to use this if you have relatively infinite possibilities. For instance, let’s say you defined a “DateRange” struct that consisted of two DateTime objects. You don’t want a builder for this. All other things being equal, the only real restriction on creation of this object is that start date should probably not come after end date. You don’t need a builder to navigate the particulars of construction here — just a simple check in the struct’s constructor. You’d get more into builder territory as the rules for date creation tightened (say, you had a specific application where you could only choose from one of four start dates and one of four end dates or something).

Another bad reason to use this is if you don’t actually need it. We sort of pushed it with the example above — the abstraction of the BuildComputer() method might have sufficed for the requirements as stated up to that point. The pattern is powerful, but it introduces complexity, and it’s important to make sure the complexity isn’t of the needless variety.

And finally, I’d like to emphasize that there is a specific construction mode for where there is a far better design pattern — building polymorphs. Builder is for composites. Don’t use it for a situation where you have a “Food” base class and you read in strings like “IceCream” and “Steak” and create inheritors IceCream and Steak depending on what you read in. That calls for one variation or another of the factory pattern — a pattern specifically for figuring out how to create inheritors of a common base or implementers of a common interface.

So What? Why is this Better?

Object construction is one of those things that tends to creep up on you in terms of complexity. In the book “The Pragmatic Programmer: From Journeyman to Master”, Dave Thomas and Andy Hunt describe the boiling frog phenomenon. The idea is (and the authors swear never to have tried it) that if you put a frog in a boiling pot of water, it will, predictably, leap out. But, if you put it in cold water and increase the temperature gradually over time, the frog will remain there even when the temperature is eventually raised to boiling and cooks the frog.

That is how object creation tends to work in code bases. There is nothing simpler than a “var myClass = new MyClass()” declaration, so why spend a lot of time thinking about where to put it? Eventually, myClass’s constructor gets more complicated, and it picks up some initialization logic and other things, and then you need to create lists and dictionaries of it, and at some point it gets inheritors that you also need to create. Before you know it, your ad-hoc creation of these things is a nightmare.

As shown above, the Builder Pattern alleviates this problem. It separates the logic for providing components for a complicated object from the logic that governs the order of assembly of those components, and it separates both of those things from the logic that actually uses the components. When used in this fashion, changes to any one of those concerns do not affect the other two. And, decoupling and dependency management is the key to avoiding maintenance and feature-addition headaches.

By

MS Test Report Generator v1.1

In the comments of this post, Kym pointed out that I had been remiss in providing instructions, so I’ve now corrected that state of affairs. I’ve uploaded v1.1 to SourceForge, and the zip file includes an MSI installer as well as PDF and DOCX formats of instructions.

As I alluded to in the comments of my previous post, I got a little carried away once I started on the instructions. I made a few minor modifications to the logic for generating reports, and added TRX as an additional, acceptable extension. That is the default extension for MS Test results files, but during the course of my build process, the files get renamed to .xml, so I didn’t have the .trx whitelisted in my validation routines. But now, I do.

The biggest change, though, is the addition of an interactive GUI, pictured here from SourceForge:

MS Test Report Generator

As I was adding instructions, it occurred to me that most people wouldn’t be following my build process, so I added a WPF project to my existing solution and set about making a GUI for this over the last week in my spare time. My over-engineered, layered implementation actually came in handy because this required very little in the way of changes to the underlying architecture. I just had to add logic to it for finding solutions and test files on disk, and the rest was sufficient.

The GUI isn’t perfect, but it’s pretty functional. If people like it, I’ll be happy to add to it (or you’re welcome to snag the source and contribute yourself if you want–it’s still available from the subversion repository). The gist is that you pick a solution and the tool will show you test runs for that solution. You then choose a test run and generate a report for it.

As I became my first user, I decided that it’d be interesting to have this open while developing, and that prompted me to add a “refresh” button so that I could do a test run, refresh, and generate a report for my latest run. In this fashion, I actually spent a few days developing where I’d view all my test results with this tool instead of the Visual Studio “Test Results” window.

There is plenty of room for extension, which I’ll do if people are interested. I could poll the filesystem for new tests instead of a manual refresh, for instance. But incremental baby steps. This is one of a bunch of pet projects that I have, so it’s not exactly as if I’m flush with time to get crazy with it. I’ll let the response level guide how much work I put in.

In that vein, if you like it or even if you don’t like it, but want me to do something to make you like it, send and email or post a comment here or on SourceForge! Aside from monitoring the SourceForge download content (and who knows what that really says about the project), that’s my only way of getting feedback.

By

Bridge

Quick Information/Overview

Pattern Type Structural
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Somewhat complex to grasp, moderate to implement.

Up Front Definitions

There are no special definitions that I’ll use here not defined inline.

The Problem

The iconic example of a situation in which the Bridge pattern is applicable is modeling a wall switch and the thing that it controls. Let’s say that you start out with a set of requirements that says users want to be able to turn an overhead light on and off. Skipping right to implementation, you do something like this:

public class OverheadLamp
{
    public bool IsOn { get; private set; }
    public bool IsUp { get; private set; }

    public void FlipSwitch()
    {
        IsUp = !IsUp;
        IsOn = !IsOn;
    }
}

This is fine, and you deliver it to production, and everyone is happy. But in the next iteration, a new requirement comes in that users want to be able to use a rocker switch or a push-button switch. And just as you’re getting ready to implement that, you’re also told that you need to implement a rotary switch (like a door deadbolt, you turn this to two different positions). Well, that’s fine, because you have just the trick up your sleeve in a polymorphic language: the interface!

public interface IOverheadLamp
{
    bool IsOn { get; }

    void OperateSwitch();
}

public class RockerOperatedLamp : IOverheadLamp
{
    public bool IsOn { get; private set; }
    public bool IsUp { get; private set; }

    public void OperateSwitch()
    {
        IsUp = !IsUp;
        IsOn = !IsOn;
    }
}

public class PushButtonOperatedLamp : IOverheadLamp
{
    public bool IsOn { get; private set; }
        
    public void OperateSwitch()
    {
        IsOn = !IsOn;
    }
}

public class RotarySwitchOperatedLamp : IOverheadLamp
{
    public bool IsOn { get; private set; }
    public bool IsToTheLeft { get; private set; }

    public void OperateSwitch()
    {
        IsOn = !IsOn;
        IsToTheLeft = !IsToTheLeft;
    }

}

Notice the change in “FlipSwitch” to the more abstract “OperateSwitch()”. This allows for implementations where the switch is not “flipped,” such as push-button. (I’m not really a stickler for English semantics, but I suppose it’s debatable whether or not a rotary switch’s operation would be a “flip.”)

Now you’re all set. Not only does your overhead lamp operate with several different kinds of switches, but you’re following the Open/Closed Principle. Marketing can come in and demand a toggle switch, a fancy touchpad, or even a contraption that you smack with a hammer, and you handle it by writing and unit-testing a new class. Everything looks good.

Except in the next iteration, those crafty marketing people realize that a switch could operate other kinds of electronics, like fans, appliances, and space heaters. So they tell you that they want the switch now to be able to turn on and off computers as well as overhead lamps. That’s a challenge, but you’re up to it. You have your interface, so you’ll just add some more polymorphs and refine the abstraction a bit:

public interface ISwitchableAppliance
{
    bool IsOn { get; }

    void OperateSwitch();
}

public class RockerOperatedLamp : ISwitchableAppliance
{
    public bool IsOn { get; private set; }
    public bool IsUp { get; private set; }

    public void OperateSwitch()
    {
        IsUp = !IsUp;
        IsOn = !IsOn;
    }
}

public class PushButtonOperatedLamp : ISwitchableAppliance
{
    public bool IsOn { get; private set; }
        
    public void OperateSwitch()
    {
        IsOn = !IsOn;
    }
}

public class RotarySwitchOperatedLamp : ISwitchableAppliance
{
    public bool IsOn { get; private set; }
    public bool IsToTheLeft { get; private set; }

    public void OperateSwitch()
    {
        IsOn = !IsOn;
        IsToTheLeft = !IsToTheLeft;
    }

}

public class RockerOperatedComputer : ISwitchableAppliance
{
    public bool IsOn { get; private set; }
    public bool IsUp { get; private set; }

    public void OperateSwitch()
    {
        IsUp = !IsUp;
        IsOn = !IsOn;
    }
}

public class PushButtonOperatedComputer : ISwitchableAppliance
{
    public bool IsOn { get; private set; }

    public void OperateSwitch()
    {
        IsOn = !IsOn;
    }
}

public class RotarySwitchOperatedComputer : ISwitchableAppliance
{
    public bool IsOn { get; private set; }
    public bool IsToTheLeft { get; private set; }

    public void OperateSwitch()
    {
        IsOn = !IsOn;
        IsToTheLeft = !IsToTheLeft;
    }

}

Alright, that code is going to work, but you’re a little leery of the fact that, after renaming IOverheadLamp to ISwitchableAppliance, the new classes you created were simply a result of copying and pasting the lamp classes and changing “lamp” to “computer.” You should be leery. That’s a design/code smell (duplication–don’t repeat yourself!) But whatever–you’re behind schedule and people are giving you a hard time. You can refactor it later.

Now the next iteration starts, and marketing is wildly pleased with your computer/light switch. They want to be able to control any sort of appliance that you can imagine–the aforementioned space heaters, ceiling fans, refrigerators, plug-in light sabers, whatever. Oh, and by the way, computers don’t necessarily turn on when you flip the switch for the outlet that they’re plugged into, so can you have the computer not turn on when you turn the switch on, but turn off when you turn the switch off? Oh, and remember that hammer-operated switch? They want that too.

Well, you’re hosed. You realize that you’re going to have to copy and paste your three (four, with the hammer thing) classes dozens or hundreds of times, and you’re going to have to change the behavior of some of them. All of the computer ones, for instance, don’t automatically turn on when you activate the switch. But clients of your code don’t know that, so they’re now going to have to try to cast the ISwitchableAppliance to one of the classes ending in Computer to account for its special behavior. This just got ugly, and fast.

So, What to Do?

In terms of realizing what you should have done or what can be done, the first important thing to realize is that you’re dealing with two distinct concepts rather than just one. Consider the following two diagrams:

Before
Our current object model

After
Another way of looking at things

The first diagram is what we were doing. Conceptually, every appliance consists not only of the appliance itself, but also of the switch that turns it on or off (or does something to it, more generally). In the second diagram, we’ve separated those concerns, realizing that the appliance itself and the switching mechanism are two separate entities capable of varying independently.

At this point, I’ll introduce the Bridge pattern in earnest, in a UML diagram, compliments of Wikipedia:

Wiki bridge

In looking at this version of it, we see some new concepts introduced: abstraction and implementor. I’ll explain the theory behind this in the next section, but suffice it to say for now that our abstraction is the switch and our implementor is the appliance. As the diagram depicts, our clients are going to deal with the abstraction, and they’re going to do so by handing it a reference to the implementor that they want. More concretely, our clients are going to instantiate some switch and tell it what device they want it to control.

By way of code, let’s consider what we had before marketing buried us with the latest barrage of requirements–three switch types and two appliances. The only new requirement that we’ll consider up front is the one suggesting that computers need to behave differently than other appliances when the switch controlling them is toggled. First, we’ll define the API for the switch (abstraction) and the appliance (implementation):

public interface ISwitch
{
    bool IsOn { get; }

    IAppliance Appliance { get; set; }
        
    void OperateSwitch();
}

public interface IAppliance
{
    bool HasPower { get; }
    bool IsOn { get; }
    void TogglePower();
    void ToggleOn();
}

Notice that because our implementation up until this point has been pretty simple, the interfaces look almost identical (minus the HasPower, TogglePower() in IAppliance, which we’ve added with our new requirement in mind). Both the appliance and the switch have the concept of on and off, more or less. This similarity was what allowed us, up until now, to operate under the (faulty) assumption that these two concepts could easily be combined. But we ran into difficulty when we saw that the abstraction and the implementation needed to vary separately (more on this later).

Where we got into trouble was with the concept of toggle power and distinguishing between having power and being on. That makes sense for an appliance (is it turned off or unplugged?) but not for a switch, which only knows that it has two positions and that it’s in one of them. So, with the introduction of this new requirement, we can no longer operate under even the pretense that mashing these two concepts together is a reasonable thing to do.

The key thing to notice here is that ISwitch has a reference to an IAppliance. This means that clients instantiating a switch can hand it an appliance on which to operate. But we’ll look at client code later.

Now let’s consider the implementors of IAppliance:

public class OverheadLamp : IAppliance
{
    public bool HasPower { get; private set; }
    public bool IsOn { get; private set; }

    // Supplying power to lamps automatically turns them on, and removing it turns them off
    // (well, probably only if their onboard switch is in that position, but that's tangential to the example)
    public void TogglePower()
    {
        HasPower = !HasPower;
        ToggleOn();
    }

    public void ToggleOn()
    {
        IsOn = !IsOn;
    }
}

public class Computer : IAppliance
{
    public bool HasPower { get; private set; }
    public bool IsOn { get; private set; }

    // Toggling power for computer just turns it off if it was on
    public void TogglePower()
    {
        HasPower = !HasPower;
        if (!HasPower)
        {
            IsOn = false;
        }
    }

    public void ToggleOn()
    {
        IsOn = !IsOn;
    }
}

Here, notice the distinction in the behavior of TogglePower(). For lamps, supplying or removing power supplies and removes power but also turns the lamp on and off, respectively. For computers, removing power turns the computer off, but supplying power does not turn it on. (Some other client of the API will have to do that manually, ala real life.) Now that we’ve decoupled the actual implementation of the concept of appliances being on and off from the abstraction of initiating that implementation, our appliances can change how they behave when power is supplied or removed. We could introduce a new appliance, “BatteryPoweredAlarmClock,” that didn’t turn off when power was cut (or, more accurately, kicked off some long running timer that would turn it off at some point later).

Here are the implementations of the ISwitch interface:

public class Rocker : ISwitch
{
    public bool IsOn { get; private set; }
    public IAppliance Appliance { get; set; }
    public bool IsUp { get; private set; }

    public void OperateSwitch()
    {
        IsUp = !IsUp;
        IsOn = !IsOn;
        if (Appliance != null)
        {
            Appliance.TogglePower();
        }
    }
}

public class PushButton : ISwitch
{
    public bool IsOn { get; private set; }
    public IAppliance Appliance { get; set; }

    public void OperateSwitch()
    {
        IsOn = !IsOn;
        if (Appliance != null)
        {
            Appliance.TogglePower();
        }
    }
}

public class Rotary : ISwitch
{
    public bool IsOn { get; private set; }
    public IAppliance Appliance { get; set; }
    public bool IsToTheLeft { get; private set; }

    public void OperateSwitch()
    {
        IsOn = !IsOn;
        IsToTheLeft = !IsToTheLeft;
        if (Appliance != null)
        {
            Appliance.TogglePower();
        }
    }
}

Notice that the individual implementors still retain their own unique properties. Rocker still has up or not up, and Rotary still has its position. But the things that all share are implementations of the OperateSwitch() method, the IsOn property (it might be more accurate to rename this “IsInOnPosition” to avoid confusion with the appliance On/Off state, but I already typed up the code examples), and the IAppliance property. In addition, all of them operate on the appliance’s TogglePower() method.

This last distinction is important. Switches, in concept, can only supply power to an appliance or take it away–they don’t actually switch it on and off. It is up to the appliance to determine how it behaves when power is supplied or removed. As this implementation is continued, it is important to remember this distinction. I could have omitted ToggleOn() from the appliances’ interface if this code were in a vacuum because the switch has no use for it. However, assuming that we’re modeling something a little broader (like, say, my home automation pet project), we clearly want people in houses to be able to turn on their computers and televisions. The switch is unlikely to be the only consumer of IAppliance.

Finally, let’s consider how we would use this thing:

public class Client
{
    public IAppliance WireUpAComputerAndFlipTheSwitch(ISwitch switchToUse)
    {
        var mySwitch = switchToUse ?? new Rocker(); //If the switch passed in is null, use a rocker by default
        mySwitch.Appliance = new Computer(); //Wire the switch up to a new computer
        mySwitch.OperateSwitch(); //Operate the switch

        return mySwitch.Appliance; //Return the appliance in whatever state the switch operation put it
    }
}

Here’s an example application, cutting out any considerations like factory classes or methods. We have some method that takes a switch as input and returns a computer in the state the method put it in. Conceptually, this is pretty simple–we’ve done all the hard work. You just take your switch, set it to operate some appliance, and then operate away.

A More Official Explanation

Earlier, I mentioned the notion of decoupling an abstraction from its implementation. This is the backbone of this pattern, but it might be a little confusing in terms of what it’s actually trying to communicate. I’d imagine some reading will think, “Isn’t decoupling an abstraction from its implementation what an interface contract does? Why the separate pattern?”

To answer that first question, I’ll say, “yes.” Defining an interface says, “Any implementors of this interface will define a method that takes these parameters and returns this type of value, and the details are up to the implementor to sort out. The client doesn’t care how–just get it done.” So, in a manner of speaking, the method signature is the abstraction and the implementation is, well, the implementation.

The problem is that this is a code abstraction rather than a modeled abstraction. That is, a method signature is a contract between one developer and another and not between two different objects. A switch isn’t an interface to a device in C#–it’s an interface to a device in the real world. A switch has its own properties, operations, and state that needs to be modeled. It can’t be reduced in code to a method signature.

So what are we getting at when we say that we want to decouple an abstraction from an implementation? Generally speaking, we’re saying that we want to decouple a thing of some sort from operation performed on that thing. In our example, the thing is an appliance, and the operations performed on it are supplying or removing power. The switch (abstraction) is a separate object with its own properties that needs to be modeled. And what’s more, we can have different kinds of switches, so long as all of the switches perform the needed operation on appliance.

In general, the Bridge pattern represents a scenario like a simple sentence with subject, verb, object: Erik eats apple. We could code up Erik and code up an apple. But then maybe Erik eats orange. So we define a fruit base class or interface and model the world with “Erik eats fruit.” But then maybe Joe also eats fruit, so we need to define a person class and further generalize to “Person eats fruit.” In this case, our abstraction is person, and our implementation is fruit. Person has a fruit property and performs “Eat” on it. The one thing that never changed as we continued generalizing was “eat”–it was always “A eats B.” Going back to our switch/appliance paradigm, we notice the same thing: “A toggles power to B.”

The decoupling allows us to have different subjects and for different objects to behave differently during the course of the verb operation. So if I use the Bridge pattern to model “Person eats Fruit,” it isn’t hard to specify that some fruits leave a pit or a core and some don’t following the eat operation. It isn’t hard to have some people get indigestion as a result of eating fruit. And neither one of those new requirements merits a change to the other one. Fruit doesn’t change if it gives people indigestion, and a person isn’t changed when a piece of fruit they eat has a pit.

Other Quick Examples

The Bridge pattern has as many uses as you can conceive of “A verb B” pairs that might have some variance in the A and B, so I’ll list a handful that lend themselves well to the pattern.

  1. You have images stored in different formats on disk (bmp, jpg, png, etc) and you also have different ways of rendering images (grayscale, inverted, etc)
  2. You’re performing a file operation on a file that may be a Windows, Mac, or Linux file
  3. You have different types of customers that can place different types of orders
  4. You have a GUI that displays buttons, text boxes, and labels differently depending on different user themes

A Good Fit–When to Use

The Bridge Pattern makes sense to use when you have two objects participating in an action and the mechanics of that action will have different ramifications for different types of the participating objects. But, beyond that simple distinction, it makes sense when you are likely to need to add participants. In our example, different appliances behaved differently when power was supplied or removed, and different switches had different behaviors and properties surrounding their operation. Additionally, it seemed pretty likely after the first round or two of marketing requests that we’d probably be adding more “subjects” and “objects” in perpetuity.

This is where the Bridge pattern really shines. It creates a situation where those types of requirements changes mean adding a class, rather than changing existing ones. And, it obviates duplicating code with copy and paste.

I’d summarize here by saying that the Bridge pattern is a good fit when you are modeling “A action B,” when A and B vary in how the action affects each one, and when you find that coupling A and B together will result in duplication. Conversely, it might be a good pattern to look at when you’re faced with the prospect of a combinatorial explosion of implementations as requirements change. That is, you can tell that A and B should be decoupled if you find yourself with classes like A1B1, A1B2, A2B1, A2B2.

Square Peg, Round Hole–When Not to Use

Don’t use this pattern if A and B are really appropriately coupled. If, in your object model, switches were actually wired to appliances, our effort would be unnecessary. Conceptually, it wouldn’t be possible to use one appliance’s switch on another–each appliance would come with one. So you define the different types of switches, give each appliance a concrete switch, and define “TurnOn” and “TurnOff” as methods on the appliance. The Bridge pattern is meant to be used when real variance occurs between the actors involved, not to be used any time one thing performs an operation on another.

There’s always YAGNI to consider as well. If the requirements had stayed as they were early in our example–we were only interested in lights–the pattern would be overkill. If you’re writing a utility specifically to model the overhead lights in a house, why define IAppliance and other appliances only to let them languish as dead code? Apply the bridge when you start getting actual variance in both objects, not when you just think it might happen at some point. In the simplest application, having to supply Switch with your only appliance, “OverheadLamp,” is wasteful and confusing.

Finally, Bridge has a curious relationship with Adapater, which I covered earlier. Adapater and Bridge have conceptual similarities in that they both link two objects and allow them to vary independently. However, Adapter is a retrofit hack used when your hands are tied, and Bridge is something that you plan when you control everything. So, don’t use (or try to use) Bridge when you don’t control one of the participant hierarchies. If, say, “RockerSwitch” et. al. were in some library that you didn’t control, there’s no point bothering to try a bridge. You’d need to adapt, rather than bridge, the switches to work in your implementation.

So What? Why is this Better?

So, why do all this? We’ve satisfied the requirement about computers behaving differently when the switch is flipped, but was it worth it? It sure was. Consider how the new requirements will now be implemented. Marketing wants 100 new appliances and a new switch. Sure, it’s a lot of work–we have to code up 101 new classes (100 for the appliances and 1 for the switch). But in the old, mash-up way, we’d have to code up those 100 new appliance classes, copy and paste them 3 times each, code up a new switch class, and copy and paste it 102 times, for a total of 403 new classes. And what if we made a mistake in a few of the appliance classes? Well, we’d have to correct each one 4 times because of all the copy/pasted code. So, even if the idea that not duplicating your work doesn’t sell you, the additional development and maintenance should.