An Interface Segregation Challenge: Part 2

Chris Rodgers · 21 April, 2017

Yesterday I explained the problem I’d had with my extension to CsvHelper and my proposed solution. Today I continue by changing the underlying configuration interfaces.

The various configuration interfaces are designed to be inherited from each other and implemented by a single class. There are the usual interface segregation problems (for example, ICsvParser let’s you identify the delimiter to use, which isn’t needed when parsing from Excel) to be solved. Additionally, ICsvReaderConfiguration inherits from ICsvParserConfiguration, making it slightly more difficult.

I extracted the common members into a new interface called IParserConfiguration and changed the inheritance so that ICsvParserConfiguration inherits from ICsvReaderConfiguration which, in turn, now inherits from IParserConfiguration.

I then added a generic type argument to IParser, allowing you to specify the configuration type - this will allow continued access to all of the configuration members, as before. CsvWriter<> is then changed to have 2 type arguments, as you must specify the type of IParser (as before) and the type of IParserConfiguration, which is required for the IParser<>. The type arguments are defined as follows;

public abstract class CsvReader<TParser, TConfiguration>
    where TParser : IParser<TConfiguration>
    where TConfiguration : ICsvReaderConfiguration
{
}

Additionally, by constraining TConfiguration to a type inheriting from ICsvConfiguration I am ensuring the same configuration object as is used by the parser can be used by the reader. This also does away with the type check that was previously necessary.

It is a similar story for the ICsvSerializerConfiguration and ICsvWriterConfiguration, with the minor difference that the new ISerializerConfiguration interface is actually empty. I went through the effort of creating it though to match the pattern used by the reader/parser side of things.

Twitter, Facebook