Software Mechanics
Why do we even have that lever?

Resolving a Singleton? Here's how...

January 23, 2009 18:01 by chris

A user posted a question on the Unity Codeplex forum a couple of days ago. He wanted to configure Unity through the configuration file to resolve a singleton object. My first thought was "of course, that's easy". Then I read the actual question and it got a bit more interesting. I thought I'd put my response here instead of the forum because I thought it was an interesting discussion, and I'd like it to still be around the next time it came up.

The thing was, the object in question was an actual singleton, along these lines:

public class MySingleton : IMySingleton { 
    private MySingleton() { }
    public static MySingleton Instance { 
        get { return instance; } 
    } 
    private static MySingleton instance = new MySingleton(); 
} 

He wanted to configure Unity to, essentially, return the Instance property of this singleton class during resolution. That's not so easy.

So, how do you fit something like this into the container? You could write an extension or custom config node to special case it, but that's just asking for trouble. Plus, it encourages use of singletons, which are pretty well understood to be Not A Good Thing these days.

Unfortunately, many times the singleton behavior is forced upon you by libraries or frameworks. Or you may have lots of other code that isn't using a container that you want to leave unchanged. So what do you do?

Luckily in this case, the singleton has an interface on it. So what I'd do is start by creating a new class that has a public constructor, implements the singleton interface, and defers all the methods to the underlying singleton.

public class MySingletonWrapper : IMySingleton {
    public void MyMethod() {
        return MySingleton.Instance.MyMethod(); 
    }
}

Something along those lines.

Next, I'd configure the container to inject the wrapper when asked to resolve IMySingleton. The nice thing about this is that you get simple integration with the code you currently have, and your new classes which you build up through the container are ignorant of both the singleton class and the wrapper; they just use the interface.

You could stop there. That's the nice thing about proper refactoring: at each step you could stop and still leave your system in a working state. But why? Why not get rid of the singleton and let the container manage the object instances? This is pretty easy through more refactorings.

The first thing to do is change the type of the Instance property on the singleton to return the interface type rather than the concrete type. This should be pretty transparent to the callers, and your compiler will tell you if any edits are required.

The next step is to move the guts of the interface implementation out of the MySingletonClass and into the MySingletonWrapper class. Then change the instance the singleton manages to an instance of MySingletonWrapper instead. Finally, change the methods on the interface to delegate to the wrapper instance instead.

public class MySingletonWrapper : IMySingleton
{
    public void MyMethod() {
        DoStuffHere();
    }
}

public class MySingleton : IMySingleton
{
    public IMySingleton Instance {
        get { return instance; }
    }

    private static IMySingleton instance = new MySingletonWrapper();

    // interface implementation now delegates to instance
    public void MyMethod() {
        instance.MyMethod();
    }
}

At this point, all your code should still be running, through the container or not. You should definately change the name of MySingletonWrapper to something a lot more descriptive at this point. That'll be very easy since the only places that use this class name are your container configuration and the MySingleton class.

From here, the next thing I'd probably do is remove the interface implementation from the MySingleton class. This class now has only one responsibility: managing the lifetime of that inner instance.

Now, as you go forward, you should be able to remove references to the explicit singleton and replace them with objects injected from the container. Over time, you should be able to remove all the reference to MySingleton without affecting your code's behavior at all. When the last reference is gone, you delete the singleton class.

And that's how I'd resolve a singleton.


Currently rated 3.5 by 2 people

  • Currently 3.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Agile | Unity
Actions: E-mail | Permalink | Comments (3) | Comment RSSRSS comment feed

Working offline with TFS

February 28, 2008 18:09 by Chris

At p&p, we use Microsoft Team Foundation Server for work item tracking and source code control. This comes as a surprise to exactly zero people I'm sure. Laughing

TFS did take some getting used to, but after working with it for a while it's gotten pretty comfortable. At least while I'm in the office. There's one nagging problem with it; when I go home, or out of the office, I've got to have corpnet access to work on the project. TFS tracks on the server which files you're editing, which means that even working on a local copy without doing a checkin requires access to the TFS server.

While I do have remote access, it's a pain, it's slow (I live about three miles beyond the borders of civilization, apparently, and my home can't get real broadband service), and at times unreliable. I've resorted to turning all the read-only bits off locally, editing away, then using the Team Foundation Power Tools uu and online commands to get synced back up.

This worked, but I hate working without a net. I still want source control, even just for local projects. And the tfpt commands get really confused if you delete files, so I needed a way to track that somehow, other than a pad of paper.

I just came up with an idea that I'm trying out, and thought I'd share.

I've been playing for a few months with a new open source source control system called Bazaar. It's intended as a distributed version control system where people ship patches to each other and it help manage the merges and whatnot (kind of like GIT). It's highly portable and plays nicely on Windows (unlike GIT). You do need to be comfortable at the command line, but that's not a problem for me. One of the nicest things for my purposes is that there's no server to set up. Each working tree is it's own working repository. You just type "bzr init ." and you've got source control on that directory. No need to set up a Subversion server, for example. And sharing my branches are as easy as emailing a file. Not that I've done that yet; this was just for me.

Anyway, back to the point. Here's what I'm doing. First, I made my TFS workspace into a bazaar repository as well. This means that as I make changes in TFS, bazaar will treat them as changes to the working copy, and I can check them into bazaar too. Second, I created a separate bazaar branch for my offline work. This gives me local source control; as long as I'm working in my local branch, I don't need to be connected to TFS at all.

Here's the money shot. Bazaar supports easy merging between branches. When I'm ready to commit to TFS, I push my changes from my local branch back to the TFS bazaar branch. Then I check that into TFS. Similarly, I can do a "get latest" in TFS, check into the master bazaar branch, then merge those changes into my local copy.

It's not quite seamless (I still need to play with tfpt to get the checkouts set up right) but so far it's working out a LOT better than working completely disconnected from source code control. Having local source code control makes this work a lot more agile; I can freely delete and modify stuff locally, check in or even branch some more, and I don't have to push back up to the server until I'm ready.

So far this system has been in use for about four hours, but so far so good. I'll update later once I've got more experience with it.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5