C# – Should Application Configuration Interface Be Split to Reduce Feature Creep?

cconfigurationinterfaces

My windows service is neatly separated into 5 components – each with their own interface and pulled together by a bootstrapper. One of my requirements is to provide configuration options in my app.config for the different pieces of the application.

I started with the following interface:

public interface IConfiguration
{
    /// <summary>
    /// The amount of time database records are allowed to be in the system before they're removed.
    /// </summary>
    TimeSpan OldSignalValuePurgePeriod { get; }

    /// <summary>
    /// The lowest log level that will be written to the log file.
    /// </summary>
    LogSeverity MinimumLogSeverity { get; }

    /// <summary>
    /// The period of time to wait for a signal metadata response before re-requesting it.
    /// </summary>
    TimeSpan SignalMetadataRerequestPeriod { get; }
}

which I'd planned to pass a constructed instance of to each of my components requiring configuration. The thing is, each of the above properties is a configuration option for a different component. There's a very good chance I will be adding some more properties at a later date to this interface. Obviously I'm populating the properties of the interface in the implementing object's constructor by reading the app.config file.

What I'm struggling with is this: since each component doesn't care about the configuration options of the other components, how can I separate this interface into pieces specific to each component that isn't a pain to construct, and one that Jimmy will understand immediately?

I've thought of doing something like this:

public interface IRepositoryConfiguration
{
    TimeSpan OldSignalValuePurgePeriod { get; }
}

public interface ILoggingConfiguration
{
    LogSeverity MinimumLogSeverity { get; }
}

public interface IDataManagerConfiguration
{
    TimeSpan SignalMetadataRerequestPeriod { get; }
}

public class ConfigurationImplementation
    : IRepositoryConfiguration, 
      ILoggingConfiguration, 
      IDataManagerConfiguration
{

}

where each component takes an instance of their own configuration interface, but I feel like that is overkill and starts to get unmanageable.

Input?

Best Answer

As long as all your configuration options come from a file, using interfaces does not bring you any benefit, since your configuration file can only provide fixed values. Even if you have to deal with more than one option per service, I do not see any convincing reason for using interfaces. You can still utilize simple "data objects" for the configuration and create a configuration class like this one:

public class Configuration
{
     public Configuration()
     { /* logic for getting the values from config file */}

     public RepositoryConfiguration RepositoryConfiguration{get; private set;}
     public LoggingConfiguration LoggingConfiguration{get; private set;}
     public DataManagerConfiguration{get; private set;}
}

The data objects for the individual configurations of your services can simply look like this:

public class DataManagerConfiguration
{
    public TimeSpan SignalMetadataRerequestPeriod { get; private set;}
    // ... add more values here
}

The DataManager constructor will then look like this:

 public DataManager(IRepository repository, ILogger logger, DataManagerConfiguration dmc)
 {...}

As you see, still one additional parameter to the ctor, regardless of how many values are inside the class DataManagerConfiguration. And providing config values for testing purposes will typically result in less boilerplate code than creating a mock interface implementation.

Some remarks:

  • not coupling the different services to one big configuration class is probably a good idea, regardless of your decision for data objects or interfaces

  • if the data objects encapsulate just one integral type, you can even omit the "wrapping" data class as long as you do not really need it.

Related Topic