Applying Interface Segregation to Configuration Files

In .NET, it’s very easy to set up custom configuration section handlers to handle your application or component’s configuration needs.  As my previous post shows, it’s also very easy to configure these with attributes that enforce required fields and other validation.  However, over time it’s very easy to create fairly large configuration sections that violate the Interface Segregation Principle, which states that classes shouldn’t be forced to depend on things they don’t need.

Consider this relatively simple configuration section:

I’ve intentionally made it a bit more verbose than needed (obviously the database settings could be combined into a connection string, etc), but the intent is to show that my relatively generic Settings section has completely lost its cohesion.  Let’s look at an interface that we’ve created to support these settings (because we don’t want to have an Insidious Dependency On Our Configuration File in our code):

From the comments I’ve included in this interface, it’s clear that there are four different kinds of settings grouped together by this interface.  With only 8 properties, it has already become an example of a “fat” interface.  Now let’s look at one of the clients of this interface, a simple AboutPage file (that isn’t an ASP.NET page, but could be):
 

This class takes advantage of Dependency Injection to eliminate a direct dependency on the ConfigurationSettings class/file, through the use of the IConfigurationSettings interface.  However, it’s still depending on a much larger interface than it needs, and thus is violating ISP.  Fortunately, there’s a very easy fix for this that will let us ensure this class only depends on what it needs, without breaking anything else in our application.  The refactoring involves creating a new interface for AboutPage to depend upon, that is more cohesive and only includes things AboutPage (and perhaps other classes that require the same things) requires.  First, we need to identify these settings and come up with a name for the new interface:

Next, we need to modify the IConfigurationSettings interface so that it no longer has these settings, but inherits them from the newly created IApplicationIdentitySettings interface:

Finally, the AboutPage class can be modified to use the new, more focused interface.  In its default constructor, though, it can still use the ConfigurationSettings.Settings class, as this implements IConfigurationSettings, which now automatically implements IApplicationIdentitySettings:

Summary

The Interface Segregation Principle states that classes should not be forced to depend on things they do not use.  By refactoring “fat” interfaces into smaller, more focused and cohesive interfaces defined by the clients that use them, we can reduce the coupling in our code.  This results in code that is easier to change, maintain, and test, not to mention being much more fun to work with.  Be breaking up the fat interface but using interface inheritance to ensure the original interface remains unchanged, this refactoring can be done to existing codebases without requiring extensive changes that spider through every class that touches the original interface.

  • Real World Monitoring and Tuning ASP.NET Caching

    First off, let me direct you to a great article on monitoring your ASP.NET cache API behavior .  Go read that first, then come back here. Done?  Good, so let’s make the advice from Simon’s blog a bit more concrete with some real-world examples

  • Use Interfaces for Metadata and Comments

    If you’re using XML Comments for intellisense purposes, or are making heavy use of attribute-based metadata in your classes, you’ve likely found that these have a tendency to bloat your code and make it more difficult to follow.  For example, consider