Thursday, January 15, 2009

Falling into the pit of success, by design.

Jeff doesn't care about resource cleanups. And I can agree to some part,but the problem is that his solution "forget it and write an article making fun of overzealous disposers" seems a bit, well, short sighted. The thing is that I agree on the point that it's silly that our best mainstream "solution" to disposal thusfar is "using". Now, come on the best we could do was invent sugar so that our try finally blocks looks prettier? Let us have a quick look at the problem using File instead of SqlConnections, the semantics are the same but it's possible to illustrate something that people actually do with fewer lines using it. It seems that Jeff thinks that we should be fine with doing this:
public void JeffIsWingingIt()
{
    var target = File.CreateText("output.file");
    target.WriteLine("Very important stuff.");
}
The sad part here is that code like this often *seems* to be working but in reality quite often you'll end up with truncated output and a long hunt to find the responsible party. So the correct version looks like this:
public void CorrectButNoFun()
{
    using(var target = File.CreateText("output.file2"))
        target.WriteLine("Very important stuff.");
}
Sadly that not at all as appealing, but at least we get all the data written to disk and the file handle reclaimed in an orderly matter. But I would say the API is to blame in this case, it encourages us to do the wrong thing (forgetting to Dispose when done). There's quite easy to fix this and make it like this instead.
public void DesignedForSuccess()
{
    FileUtil.Write("output.file3",
        target => target.WriteLine("Very important stuff."));
}

static class FileUtil
{
    public static void Write(string path,
    Action<TextWriter> action)
    {
        using(var file = File.CreateText(path))
            action(file);
    }
}
Here resource handling and work are cleanly separated and abstracted. Using a similar approach you can easily and safely work with SqlConnection,SqlCommand,SqlDataReader and a huge varaity of other error prone but Disposable classes. Once and only once. Don't repeat yourself. It applies to resource handling to.

No comments:

Post a Comment