Writing Testable Code Is About Managing Complexity

code, tdd 0 comments suggest edit

When discussing the upcoming ASP.NET MVC framework, one of the key benefits I like to tout is how this framework will improve testability of your web applications.

The response I often get is the same question I get when mention patterns such as Dependency Injection, IoC, etc…

Why would I want to do XYZ just to improve testability?

I think to myself in response

Just to improve testability? Isn’t that enough of a reason!

That’s how excited I am about test driven development. Testing seems enough of a reason for me!

Of course, when I’m done un-bunching my knickers, I realize that despite all the benefits of unit testable code, the real benefit of testable code is how it helps handle the software development’s biggest problem since time immemorial, managing complexity.

There are two ways that testable code helps manage complexity.

​1. It directly helps manage complexity assuming that you not only write testable code, but also write the unit tests to go along with them. With decent code coverage, you now have a nice suite of regression tests, which helps manage complexity by alerting you to potential bugs introduced during code maintenance in a large project long before they become a problem in production.

​2. It indirectly helps manage complexity because in order to write testable code, you have to employ the principle of separation of concerns to really write testable code.

Separating concerns within an application is an excellent tool for managing complexity when writing code. And writing code is complex!

The MVC pattern, for example, separates an application into three main components: the Model, the View, and the Controller. Not only does it separate these three components, it outlines the loosely coupled relationships and communication between these components.

Key Benefits of Separating Concerns

This separation combined with loose coupling allows a developer to manage complexity because it allows the developer to focus on one aspect of the problem at a time.

Martin Fowler writes about this benefit in his paper, Separating User Interface Code (pdf):

A clear separation lets you concentrate on each aspect of the problem separately—and one complicated thing at a time is enough. It also lets different people work on the separate pieces, which is useful when people want to hone more specialized skills. \

The ability to divide work into parallel tracks is a great benefit of this approach. In a well separated application, if Alice needs time to implement the controller or business logic, she can quickly stub out the model so that Bob can work on the view without being blocked by Alice. Meanwhile, Alice continues developing the business layer without the added stress that Bob is waiting on her.

Bring it home

The MVC example above talks about separation of concerns on a large architectural scale. But the same benefits apply on a much smaller scale outside of the MVC context. And all of these benefits can be yours as a side-effect of writing testable code.

So to summarize, when you write testable code, whether it is via Test Driven Development (TDD) or Test After Development, you get the following side effects.

  1. A nice suite of regression tests.
  2. Well separated code that helps manage complexity.
  3. Well separated code that helps enable concurrent development.

Compare that list of side effects with the list of side effects of the latest pharmaceutical wonder drug for curing restless legs or whatever. What’s not to like!?

Technorati Tags: TDD, Separation of Concerns, MVC, Loose Coupling, Design

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.



21 responses

  1. Avatar for Vijay SAnthanam
    Vijay SAnthanam November 13th, 2007

    I usually TAD, but I'm trying to do TDD more often.
    What test package do you personally use Phil? MSTest, Nunit, XUnit, HaackTest, JuniorInternTest?

  2. Avatar for Community Blogs
    Community Blogs November 13th, 2007

    Phil Haack today posted an article about Writing Testable Code Is About Managing Complexity . He says

  3. Avatar for Jacques Philip
    Jacques Philip November 13th, 2007

    Hello Phil
    I have been working on a project trying to apply these principles and it seems that using the Entity Framework or Linq to Sql, it is hard to have a loose coupling between the UI and the data layer.
    This would require the UI to talk only to interfaces so that the data layer's implementation can be changed easily.
    The designers are very nice, but they don't generate these interfaces, so I had to extract them from the generated classes and make the partial class declarations inherit from these interfaces; this almost looks like a haack.
    The interfaces then have to be kept in sync with the generated classes manually.
    The good thing I realized in this process is that this way, I can overcome the limitation of the designers to put custom attributes on the entities properties (for validation for example), by applying these attributes to the interface's property declaration.
    Or is there a better way to do this?

  4. Avatar for DotNetKicks.com
    DotNetKicks.com November 14th, 2007

    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  5. Avatar for AndrewSeven
    AndrewSeven November 14th, 2007

    I'm not sure testability helps manage the actual complexity, but it definitely helps deal with the reality of the complexity.
    Your codebase and system will still become complex, but you have a good safety mechanism for avoiding regressions.

  6. Avatar for Travis Illig
    Travis Illig November 14th, 2007

    I might actually argue that design for testability doesn't help manage complexity. That is, the word "manage" is my sticking point, where "manage" means "to handle or direct with a degree of skill" (per MW Online Dictionary).
    Design for testability generally causes interface explosion, which just adds to the number of moving parts and, thus, increases the complexity rather than helping you with it, regardless of the fact you have tests. It also has generally adverse effects on encapsulation, which is problematic if API is a deliverable.
    Managing complexity, to me, sort of implies that it helps you to keep complex things simple, or more controlled, or at least more intelligible, and that's totally not what actually happens.
    Maybe it's semantics, but I think it's more accurate to say that designing for testability helps you maintain complexity. That is, your code may be complex, but you'll be more easily able to verify when things break as the complexity grows.
    (For the record, I'm all about testing code, but generally the stuff I work on can't afford the lack of encapsulation or the interface-for-nearly-every-object design that common code designed for testability creates. How easy would the .NET framework be to pick up and use if they designed it like that?)

  7. Avatar for Evan
    Evan November 14th, 2007

    Great post! I'm really looking forward to wrapping MVC in some unit tests.. ;-)
    And I couldn't agree more about the use of unit tests in managing a complex code base..

  8. Avatar for Jay Flowers
    Jay Flowers November 14th, 2007

    @Travis and Phil,
    I often hear Travis position, though usually not as well stated.
    Travis you say " How easy would the .NET framework be to pick up and use if they designed it like that?"
    I would guess that the ASP.Net MVC framework is a great opportunity to answer that question.
    Phil, what do you have to say?

  9. Avatar for Jay Flowers
    Jay Flowers November 14th, 2007

    Hmm "managing complexity". Do you mean that unit tests (as in the definition that includes isolation and working with very small portions of code) can expose issues of complexity that impair maintainability early? Early = while the design is still fresh and malleable. So that you are more likely to know that you are building a death trap?
    Is that what you mean?

  10. Avatar for Oran
    Oran November 14th, 2007

    Windows Communication Foundation uses this design style all over the place, and I'm guessing they chose it primarily to manage complexity, not because they were TDD-driven (TDDD??). There is pretty much an interface or mockable class for everything, and even though they don't use a generic dependency injection framework to wire up instances that implement the interfaces, they accomplish pretty much the same thing through their own config system, similar to most DI frameworks.

  11. Avatar for Haacked
    Haacked November 14th, 2007

    @Travis: Manage can also mean:

    cope: come to terms or deal successfully with

    Note that I didn't say that TDD reduces complexity. I only meant that it helps cope with complexity. The side-effect of writing testable code, namely separation of concerns, breaks a large complex application into less complex components.
    Perhaps a better choice of words is to say that TDD helps deal with complexity.

  12. Avatar for Evan
    Evan November 14th, 2007

    "Perhaps a better choice of words is to say that TDD helps deal with complexity."
    Ironically enough, I find this true for both real and imaginary complexity.
    When walking into part of a codebase that doesn't have a safety net of unit tests, I find a little red mental flag goes up. There's a slight bit of fear that if I don't fully grok the part of the app that I'm about to change, I'll write myself into a nice little hole (which usually shows up in Production).
    The safety net of unit tests let me ignore the fact that there might be ungrokked complexity there (regardless if it really exists or not). I can feel confident that if I break it, it will show up in the Unit Test Runner.

  13. Avatar for Evan Hoff, Professional Code J
    Evan Hoff, Professional Code J November 14th, 2007

    Here's a comment from Phil's testability post : "I have been working on a project trying

  14. Avatar for Oran
    Oran November 14th, 2007
  15. Avatar for Christopher Steen
    Christopher Steen November 14th, 2007

    WPF Three Ways To Create Dynamic Menus [Via: Omer van Kloeten ] More updates to Woodstock [Via: Josh...

  16. Avatar for Christopher Steen
    Christopher Steen November 14th, 2007

    Link Listing - November 14, 2007

  17. Avatar for Erik Lane
    Erik Lane November 14th, 2007

    Great post Phil. You've given me some talking points for my next code review. :-)

  18. Avatar for Vitaly Gorn
    Vitaly Gorn November 15th, 2007

    Good post, Phil! However, IMHO testability does not affects complexity. Complexity is solved by employing good OOD. In fact you are making things more complex yourself in this post. TDD is for testability and, thus, for finding mistakes in your code. OOD is for broad range of good things and managing complexity is one of them.
    Also, in order to support TDD code sometimes becomes more complex. Sometimes. Isn't it?

  19. Avatar for Jeffrey Palermo
    Jeffrey Palermo November 15th, 2007

    Amen. Testability requires so many other things that it's a great measure of maintainability.

  20. Avatar for Haacked
    Haacked November 16th, 2007

    More complexity isn't always a bad thing if some of that complexity is automatically handled for you and helps you manage the complexity better.
    Consider that MVC is more complicated that simply throwing a bunch of code together into a single component in the simplest way that works.
    But MVC helps decompose and manage complexity at the cost of adding a slight bit of complexity.

  21. Avatar for Ed Kirwan
    Ed Kirwan December 2nd, 2007

    Hmm, well, I think unit-tests kick ass when it comes to reducing code complexity - and I really don't care how, "Managing complexity," is interpreted (even if it's interpreted correctly).
    I would point out, however, that unit-testing - fabulous though it is - should not go head-to-head with the mathematically proven (though for a tiny family of systems) benefits of encapsulation, for the latter of which see the following link (or for the instant-gratifiers, see the following+1 link, which shows how a type of complexity is minimised with respect to encapsulation):
    In other words, practicals and theory are powerful tools used in combination.
    Ed Kirwan