Skip to content

Software Flexibility in C#

December 2, 2012

Software Architects have wonderful terms like scalability and flexibility but what do these mean in the real world and how do we start to put these into practice? I would like to start by looking at one of these terms; flexibility.

Software flexibility can mean a lot of things but when it is used to describe a whole system, it normally refers to the ability for the solution to adapt to possible or future changes in its requirements. When you design or build a solution, you should try to cater for these changes which inevitably arrive in the future. This flexibility should be catered for with the design of the system as a whole but there is also no reason not to also include it with the smaller aspects of the system.

The key to building highly flexible systems is the loose coupling of the components. For example, there is no point building a solution that is tightly integrated with active directory if this part could change down the line. This is not something you should do even if you don’t expect it to change in the future. Nothing is cast in stone in software and at some point you will find yourself in a situation where you will wish you had done it differently.

This whole concept of flexibility is probably best explained through an example. In this blog, I will build a small authentication sub-system. Starting with a nasty hard coded piece of code and slowly progressing to a configurable and flexible solution. Feel free to skip to the later steps if the early parts are obvious to you.

Starting out

For the purposes of simplicity, let’s assume that our application is a single threaded application. Threading adds some complexity that will detract from the core of the example. Error handling has also been kept to a minimum (actually, it’s pretty much non-existent) to remove any unnecessary clutter and no exceptions were harmed during the writing of this blog :).

In our example, let’s assume that our active directory implementation has the following; A LogOn method to verify a user name and password, a LogOff method to log the user off the system and a single property LoggedOnUser that returns the name of the user who is logged onto the system. The class would look something like this:

  class TestActiveDirectory
  {
    private string loggedOnUser = "";

    public void LogOff()
    {
      loggedOnUser = "";
    }

    public void LogOn(string userName, string password)
    {
      if ((userName != "ActiveUser") || (password != "password"))
        throw new TestSecurityException("Invalid User Name or Password!");
      loggedOnUser = "ActiveUser";
    }

    public string LoggedOnUser { get { return loggedOnUser; } }
  }

The developer creating the system would be quite impressed with themselves, having created a nice wrapper for all of the active directory logic. They would then start using this new shiny class throughout their application. Pretty soon the application would be riddled with calls to LogOn, LogOff and accesses to LoggedOnUser.

The big problem with this scenario is that eventually there will come a time when this code needs to be changed for a client that does not have active directory installed. Typically what happens then is that a new class is created that is almost identical previous class and a number of “if (…)” blocks are added.

This starts off being the easiest and quickest way to solve the problem but ends up as a maintenance nightmare. The new Oracle authentication class could look like this:

  class TestOracleAuthentication
  {
    private string loggedOnUser = "";

    public void LogOff()
    {
      loggedOnUser = "";
    }

    public void LogOn(string userName, string password)
    {
      if ((userName != "OracleUser") || (password != "password"))
        throw new TestSecurityException("Invalid User Name or Password!");
      loggedOnUser = "OracleUser";
    }

    public string LoggedOnUser { get { return loggedOnUser; } }
  }

Throughout the code we would have nasty unmaintainable titbits like this:

    private void tCheckStatus_Tick(object sender, EventArgs e)
    {
      string userName;
      if (activeDirectorySelected)
        userName = activeDirectory.LoggedOnUser;
      else
        userName = oracleAuthentication.LoggedOnUser;
      if (userName != "")
        statusLabel.Text = "User Name: " + userName;
      else
        statusLabel.Text = "";
    }

As more and more methods and properties are added to the existing authentication classes and new authentication classes are added this quickly descends into chaos.

You can download the code for this part from DependencyInjection_Part_1.zip

Decoupling

So how do we solve this mess? The first step in getting out of this mess is to add an authentication interface. This interface will abstract out the Oracle and Active Directory authenticators from the rest of the application.

So where do we start with the interface? The easiest thing to do is just extract out the common methods and properties (not ideal for interfaces but will do for this example) from the classes and add them to the new interface.

  interface ITestAuthentication
  {
    void LogOff();
    void LogOn(string userName, string password);
    string LoggedOnUser { get; }
  }

The interface should look something like the one above. It’s pretty easy to hook in the new interface to the two classes. The Active Directory class would look like this:

  class TestActiveDirectory : ITestAuthentication
  {
    private string loggedOnUser = "";

    public void LogOff()
    {
      loggedOnUser = "";
    }

    public void LogOn(string userName, string password)
    {
      if ((userName != "ActiveUser") || (password != "password"))
        throw new TestSecurityException("Invalid User Name or Password!");
      loggedOnUser = "ActiveUser";
    }

    public string LoggedOnUser { get { return loggedOnUser; } }
  }

Using the interface in the application is where you see the real differences. The code is much cleaner as all of the “if (…)” blocks are replaced with a single line of code. The interface variable would be declared like this (assuming our system defaults to Active Directory):

    private ITestAuthentication authentication = new TestActiveDirectory();

The code to creating the objects would look like this:

      if (chkActiveDirectory.Checked)
        authentication = new TestActiveDirectory();
      else
        authentication = new TestOracleAuthentication();

And using the interface in the code makes it look a lot cleaner than it previously did.

    private void tCheckStatus_Tick(object sender, EventArgs e)
    {
      string userName;
      userName = authentication.LoggedOnUser;
      if (userName != "")
        statusLabel.Text = "User Name: " + userName;
      else
        statusLabel.Text = "";
    }

All in all we have a much smarter solution for very little work. We have also started the process of breaking up our solution into loosely coupled components.

You can download the code for this part from DependencyInjection_Part_2.zip

Factories

This solution looks, at face value, like we have found the sweet spot, but it falls short in a couple of places. For one, every time we add a new authentication provider we need to rebuild our system. We also need to retest the entire application for each new provider, or at least the parts that interface with our authentication providers. To make matters worse, its not the easiest thing to use these components in other systems. So how do we take this forward? We create a factory. I find that I draw pictures better than I write so I will show a simple class diagram that includes our factory.

Factory

What I have done is start breaking up the components of the authentication system into different libraries; one library for the factory (more about this now), another for the ITestAuthentication interface and additional libraries for each of the authentication providers.

How the factory works is this. We only couple our application to the Authentication Factory and Authentication Interface. At the same time we couple the authentication providers to the Authentication Interfaces but there is no coupling between the application and providers themselves. The authentication providers are registered with the factory after they are loaded and the application asks the factory for the authentication provider by name, when it needs one. It’s important for the factory to be a singleton as both the application and the providers need to access the same instance of the factory class.

This blog is taking the factory a bit further by building a mini plug-in system to dynamically load our provider.

So what does this factory look like?

  public class AuthenticationFactory
  {
    private static readonly AuthenticationFactory instance = new AuthenticationFactory();
    private List<ITestAuthentication> authenticationEngines = new List<ITestAuthentication>();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static AuthenticationFactory()
    {
    }

    private AuthenticationFactory()
    {
    }

    public static AuthenticationFactory Instance
    {
      get { return instance; }
    }

    public void AddAuthenticator(ITestAuthentication authenticator)
    {
      authenticationEngines.Add(authenticator);
    }

    public ITestAuthentication AuthenticatorByType(string authenticationType)
    {
      foreach (var authenticator in authenticationEngines)
      {
        if (authenticator.AuthenticationType == authenticationType)
          return authenticator;
      }
      throw new TestSecurityException("Invalid Authentication Type");
    }
  }

You can ignore some of the code as that code is singleton code. Any robust singleton implementation will do. The important lines are 12, 29-32 and 34-42. These lines are responsible for getting and setting the provider. We put this factory into it’s own library. We also place our ITestAuthentication interface into a library. It’s necessary to add a new property to the authentication interface called AuthenticationType that we will use to give each provider a “Name”. This name is used to retrieve the selected authentication provider. This gives us a way of configuring the system through XML or another configuration system in the future.

We create a separate DLL for each provider and each of these providers references the interface library. We implement the new interface property in each of these providers and can then build them.

We add the following method to our main application so that it can dynamically load each of the authentication providers.

    void LoadLibrary(string libraryName)
    {
      Assembly loadedLibrary;
      loadedLibrary = Assembly.LoadFrom(libraryName);
      foreach (Type selectedType in loadedLibrary.GetTypes())
      {
        bool isAuthenticator = selectedType.GetInterfaces().Any(x => x == typeof(ITestAuthentication));
        if (isAuthenticator)
        {
          var instance = (ITestAuthentication) Activator.CreateInstance(selectedType);
          AuthenticationFactory.Instance.AddAuthenticator(instance);
        }
      }
    }

This block of code loads the library by its library (dll) name and then iterates through all of the types in the library to see if there are any that implement our authentication interface. If it finds one, it registers that type with the factory.

Lastly, we need to tell our application to load the two libraries by including a couple of calls to LoadLibrary. The last line of code sets our default authentication provider to the Active Directory one.

    public Form1()
    {
      InitializeComponent();
      LoadLibrary("ActiveDirectoryLibrary.dll");
      LoadLibrary("OracleAuthenticationLibrary.dll");
      authentication = AuthenticationFactory.Instance.AuthenticatorByType("ActiveDirectory");
    }

Accessing one of the authentication providers is as easy as calling a method on the factory and giving it the name of the authentication provider (AuthenticationType). For the Active Directory one it looks like this:

        authentication = AuthenticationFactory.Instance.AuthenticatorByType("ActiveDirectory");

and for the Oracle one it looks like this:

        authentication = AuthenticationFactory.Instance.AuthenticatorByType("Oracle");

At this point, it would probably be a good idea to open the project and look at the code. This type of solution adds significant flexibility to our previous effort. Yes there is a bit more code, but we are slowly starting to arrive at that word “flexible”. No longer is our application tied to the providers. We can happily build a brand new authentication provider and not even rebuild our application (if our configuration is working the way it should). Taking it a step forward, we also now have a solution where we can create a set of test packs for our providers and individually test and certify them. Any provider that passes the tests should work properly with our application(s). I have cheated in this example to make it easier for people to test the code. I have referenced the Active Directory and Oracle Authentication providers from the main application. This is not necessary and should not be done when using this approach in a real world situation but it will ensure that the DLL’s get copied to the application folder which we need to run the application.

You can download the code for this part from DependencyInjection_Part_3.zip

The next step

Where do we go to from here? It looks like we have the ideal solution. It’s not; there are still some enhancements that we can make to the existing solution. The big problem with this approach is that we are still duplicating code and there is more coupling than there needs to be. For every different provider type (authenticator, configuration adapter, etc.) we have another factory. There is also the problem that your application needs to know about two things, the authentication interface and the authentication factory. What would need to change if we switched from a single authenticator instance to a pool of authenticators to cater for threading? We would have to make some fairly big changes to our factory and also make some changes to the providers and the core application.

Wouldn’t it be nice to have a generic solution where we only need to create the interface? Think of it as a big all-purpose factory. But not just a factory, it’s a solution that caters for singletons, pools and pretty much any type of implementation that you would like. That’s where dependency injection comes in.

With dependency injection, an application will request a service or component from the dependency injection container and the container will be responsible for loading and configuring the requested service.

Looking at the existing example, what if I wanted to have a number of connections to the authentication provider at the same time? I would need to pull out the hammer and make a few modifications to my factory. Rather than do that, I will start with a new version, one that makes use of Dependency Injection.

The code that follows from this point onwards uses the Spring Framework. I have included the library in the example but I would advise you to download the full package and take a look. You can download it from http://www.springframework.net/. There are a number of dependency injection frameworks out there (such as Ninject) but I like the configuration system in Spring.NET.

So what do we need to switch across to Dependency Injection and the Spring.NET Framework? Well, the changes are actually quite minimal from our factory solution. First, we make a couple of boilerplate changes.

1) We remove the reference to our factory from the main application as it is no longer needed.

2) We need to add the Spring.Core and Common.Logging libraries to our references in our host application.

3) We add an app.config file to our host application that includes the configuration information for the spring framework regarding logging and our objects.

      <o name="ActiveDirectory" type="ActiveDirectoryLibrary.TestActiveDirectory, ActiveDirectoryLibrary">
      </o>
      <o name="Oracle" type="OracleAuthenticationLibrary.TestOracleAuthentication, OracleAuthenticationLibrary">
      </o>

I had to unfortunately change the name of the tags from “object” to “o” to get past WordPress. These two lines of code tell the spring framework about our authentication providers.

4) Lastly, we need to add a few lines of code to our application. We create a reference to the Context like this:

    IApplicationContext ctx = ContextRegistry.GetContext();

And we are then able to retrieve the authentication provider like this:

      authentication = (ITestAuthentication)ctx.GetObject("ActiveDirectory");

That’s it; our application is now using dependency injection. “ActiveDirectory” is the name of the provider as specified in the app.config file. As before, I have included unnecessary references to the two authentication providers to make sure the files are copied to the application folder.

You can download the code for this part from DependencyInjection_Part_4.zip

But wait, there’s more :).

If you remember above, I mentioned something about changing the lifespan of the classes (Singleton, etc.). In my example, let’s say that our interface to Oracle would only work as a single connection. All we would need to do is add the singleton=”true” attribute in the configuration. The framework will do the rest.

  <o name="Oracle" type="OracleAuthenticationLibrary.TestOracleAuthentication, OracleAuthenticationLibrary" singleton="true">
  </o>

So, what is the point of my last weak attempt at humour? The point is that switching to this sort of framework gives you far more flexibility in your solution and that’s what this blog is ultimately about. You can also do things like property injection. This lets us change properties through the xml configuration file. I added a new authentication type in this last step called a Dynamic Authentication Provider. This new provider is just a proxy onto one of the original two providers but it gets the name of this provider set through property injection. The provider code looks like this:

  class DynamicAuthentication : ITestAuthentication
  {
    private ITestAuthentication hostedAuthentication;

    public ITestAuthentication HostedAuthentication
    {
      get
      {
        return hostedAuthentication;
      }
      set
      {
        hostedAuthentication = value;
      }
    }

    public void LogOff()
    {
      hostedAuthentication.LogOff();
    }

    public void LogOn(string userName, string password)
    {
      hostedAuthentication.LogOn(userName, password);
    }

    public string LoggedOnUser { get { return hostedAuthentication.LoggedOnUser; } }

    public string AuthenticationType { get { return "Dynamic"; } }
  }

As you can see, it includes a new property called HostedAuthentication. This property is set through the app.config file like this:

  <o id="Dynamic" type="DependencyInjection_Part_5.DynamicAuthentication, DependencyInjection_Part_5">
    <property name="HostedAuthentication" ref="ActiveDirectory"/>
  </o>

So, by changing a single line of configuration xml, I can switch on Singleton’s or switch providers all together.

You can download the code for this part from DependencyInjection_Part_5.zip. The last download includes the source code for all of the projects.

More Information on Dependency Injection

There is a lot more to Dependency Injection than what I have covered in this blog. Constructor, Property, Method and Field injection are all valid forms of Injection. I also haven’t gone into the details of how it’s accomplished but rather just shown a glimpse of it. I would suggest doing some googling on the subject if you find it interesting.

Interface Design

Before I finish, there are a couple of important aspects of interface design that I should mention. The temptation is always there to take all of the methods and properties from a class and slap them in an interface. This will not necessarily solve the tight coupling problem. Why is this? Often people take functionality that is specific to a provider and add this to their interface. All that does is restrict your application to only use the provider in question.

For example, let’s say that Active Directory in our example above includes a neat function to send a user a sms when they log on. Including this SendSmsToUser option in our interface and application will pretty much force us to use Active Directory until we can mimic the behaviour in the other providers.

There are three approaches you can take to defining your interfaces:

1) The first is to look at the lowest common denominator and create an interface around that.

2) Secondly, you can try and create interfaces that include all of the functionality that you would like to use and then use some attributes or a function to tell the application which functionality is supported.

3) Finally, you can try and find a balance between the previous two. Use the lowest common denominator and add some of the more advanced functionality as optional features.

You can make use of multiple interfaces to cover the functionality. Think carefully when creating interfaces. These should be seen as a contract that you don’t break very easily.

Summary

In summary, things have definitely changed over time. In the old days, people used to clutter their code with “if (x) y;” statements, trying to cover all of the bases. A lot of modern systems use factories to provide a level of abstraction and the trend is now towards dependency injection.

Think flexibility when you design the solution and you will definitely arrive at a better solution.

This is the C# version of one of my previous blogs. It’s been on the cards for a while; I just didn’t make the time to complete it until now.

Advertisements

From → Coding Tips

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: