Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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: