Extreme ASP.NET Makeover: Singleton - Refactoring

Play Extreme ASP.NET Makeover: Singleton - Refactoring
Sign in to queue


Extreme ASP.NET Makeover: Death of a Singleton-Refactoring

Now that we have a new class, complete with functionality, we can start to refactor other parts of the application to use it instead of the AuthChecker singleton.  Like all the other refactorings we’ve done thus far in this article, it’s not that big of a deal.  As our example, we’re going to continue to refactor the AuthorizationServices class (see the previous Separation of Concerns article for the initial refactoring for this).  In AuthorizationServices, we want to eliminate the use of AuthChecker and, in its place, use an instance of AuthorizationChecker instead.

To do this, we first need to create a module level variable that provides the same capabilities as the AuthChecker singleton.  Earlier in this article, we created an IAuthenticationChecker interface that worked to enforce this for us.  Now is another time that we can use it.  As you can see in the code below, we now have created an instance of the AuthenticationChecker and assigned it to the module level variable:

public class AuthorizationServices
    private IAuthorizationChecker _authenticationChecker;

    public AuthorizationServices()
        authorizationChecker = new AuthorizationChecker();

Now that we have a way to access the authentication checking code, we just need to replace the AuthChecker calls in the RetrieveCurrentStatusFor method with calls to the module level variable.  As an example of these changes, here is what the first one would look like:

CanView = _authorizationChecker.CheckActionForPage(currentPage, 
    Actions.ForPages.ReadPage, currentUsername, currentGroups),

With that we have our AuthorizationServices class refactored and we’ve finished the first full round of changes that are required to eliminate the AuthChecker singleton.  If we take a look at the usages of the AuthChecker singleton instance, we’ll see that there are still a large number of places that it is being used.

Now that you’ve finished this first complete refactoring to use the new AuthorizationChecker class, you’ve also reached the first logical checkpoint in your refactoring exercise.  From here you can choose when you want to move from the AuthChecker singleton to an AuthorizationChecker instance class in any of the other places that AuthChecker is being used.  As you incrementally move through your changes from AuthChecker to AuthorizationChecker, you get closer and closer to the next step in this refactoring: deleting the AuthChecker singleton.

Once you have all of the usages of AuthChecker replaced with the AuthorizationChecker class you’re almost ready to remove the AuthChecker class from your code base.  Before we can do that, remember that we had the new AuthorizationChecker class delegating execution to the AuthChecker singleton.  To be able to get rid of AuthChecker completely, we need to move its logic into the new AuthorizationChecker class.  There are a couple of small things that we need to address in this refactoring, such as adding using statements.  

The main change we need is to address the code’s need for an ISettingsStorageProviderV30 typed object.  If we look into how that object is being passed into the AuthChecker singleton, we see that it’s actually being provided from another singleton named Settings:

AuthChecker.Instance = new AuthChecker(Settings.Instance.Provider);


Since this value is coming from a singleton, we can easily add a module level variable to AuthorizationChecker that can be used throughout its methods.  Assigning that variable is as simple as what you see below.  Also note that we no longer need the module level AuthChecker variable since we’ve now moved all of the AuthChecker code into this class.  Since it’s not needed, we’ve removed it and the code related to it in the constructor:

private ISettingsStorageProviderV30 _settingsProvider;
public AuthorizationChecker()
    _settingsProvider = Settings.Instance.Provider;

The result of this final refactoring is that the public methods on AuthChecker are no longer being executed anywhere in the code base.  If you were to do a Find Usages on AuthChecker, you’ll see that the only place it exists is in the StartupTools class where it was being initialized.  Since it’s not being used anywhere, there’s no need to initialize it, so we’ll just delete that line of code.  Now we’re completely free of any use of AuthChecker, so we can delete the class from the project.  With that, you’re free of your singleton past...or at least one part of it.

I realized what a ridiculous lie my whole life has been...

We’ve spent some quality time together on this article and have weaned you from a dependence on singletons in your code base.  Singletons often are seen as the “easy” way to code.  Just because you don’t have to “new up” a class to make use of its functionality, doesn’t mean that you’re not imposing a debt on your code base.  While singletons seem like the route of least friction at first, you quickly find out that they’re nothing more than a mirage on the way to software development bliss.  You see the ease of development that they offer, but every time that you move closer the goal is still just as far away as it was before.

Unless you truly need to ensure that one, and only one, instance of an object exists per application lifecycle, then you should be working to refactor singletons out of your code base.  Hopefully, the techniques in this article have pointed you in the right direction to be able to do that.

Other videos from this article

Read the full article at https://msdn.microsoft.com/magazine/ee343987.aspx



Download this episode

The Discussion

Add Your 2 Cents