Hacker News new | past | comments | ask | show | jobs | submit login

I know I'm pulling out raganwald's argument from one of his posts, but I'm honestly curious: is there anything other than anecdotal evidence that “there's huge correlation between testability and maintainability”? In particular, here we're talking about unit testability. I don't agree or disagree—I've done both TDD and not, but I'm still not sure I've created more maintainable code when testing than when not.



Replying to both of you so replying to myself -- I know all of the arguments for why testing improves maintainability; that has nothing to do with what I'm asking. It was my mistake for muddying my question with my own anecdote.

I'm asking: is there scientific proof (i.e., in a study) that testing and maintainability are at least positively correlated in a reasonably universal fashion?


Maintainability is not just about you changing your code later on; it's about someone else trying to understand what you were thinking when you write it.. and then change it. Tests make that process way easier. You can add your new feature without wasting time to understand everything else and still make sure it's working. If it's your own project, meh, you know your stuff. You even know all the hack you did to gain time. I see tests as a documentation that shows me what's working. Reading tests (high level ones) is usually the first thing I do when starting on a new project. Comments change over time.. documents aren't updated.. people leave.. but tests remain. If the test passes, it doesn't mean everything is perfect, but at least you know that these things work.


Please note that the grandparent post specifically asks about unit testing and unit testability, while you speak in much broader terms.

Automated regression tests can be created in may ways, including UI-level tests that don't require any changes in coding practices at all.


Testable code is loosely coupled, because it has to interact with mocks. Untestable code tends to have things like hard-wired http clients, because it was "easier" to just inline the constructor. When you go back to upgrade the current version of your http client later, you'll appreciate that you didn't hardwire it.


Frameworks and generic APIs definitely should not have important functionality hardwired. However, changing something from a "hardwired" object property to dependency-injected object property is trivial when you have the control over the code.

If you write client code and don't need to mutate an object, having it "hard-coded" significantly improves readability and makes your program much simpler.

The most trivial example I can come up with. Compare:

        public void SomeMethod()
        {
            string config = File.ReadAllText("bal.conf");
            //etc
        }
with this:

        string config; 

        public Something(string newConfig)
        {
            config = newConfig;
        }

        public void SomeMethod()
        {
            //etc
        }
To understand what the first method does, you only need to look at the method. To understand what the second block of code does, you need to know about the method, the property, the constructor, and even with all that knowledge you have no idea where that string really came from. If it always comes from the same file, it's added complexity with no tangible benefit.

It's the side of dependency injection that people don't like to speak about. Client code doesn't always need to be perfectly flexible. You can make it flexible when and where it's needed.


In a more flexible language (or with overloading), you can get the best of both worlds.

    // yay, scala
    def someMethod(config: String = File.ReadAllText("bal.conf")) = {
        //etc
    }




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: