Written June 13, 2007 at 11:19 MDT Tagged c sharp and patterns
Bil Simser had a post up the other day about Refactoring Dumb, Dumber, and Dumbest away. I had some small suggestions that I offered up and Bil implemented some of the changes that I had mentioned. Here is the code as it stands right now :
public class SegmentConfigurationFactory
{
/// <summary>
/// Gets the configuration given the values provided.
/// </summary>
/// <param name="cableSegmentCount">The cable segment count.</param>
/// <param name="segmentCount">The segment count.</param>
/// <param name="passesCount">The passes count.</param>
/// <param name="segmentIndex">Index of the segment.</param>
/// <param name="supplyVoltage">The supply voltage.</param>
/// <param name="voltageDrop">The voltage drop.</param>
/// <param name="segmentPercentage">The segment percentage.</param>
/// <returns></returns>
public ISegmentConfiguration GetConfigurationGiven(
int cableSegmentCount,
int segmentCount,
int passesCount,
int segmentIndex,
int supplyVoltage,
decimal voltageDrop,
decimal segmentPercentage
)
{
ISegmentConfiguration configuration = new DefaultSegmentConfiguration(1, supplyVoltage, voltageDrop);
if (segmentCount > 1)
{
if (cableSegmentCount == 1)
{
if (passesCount > 1 && (segmentIndex <= (segmentCount - 2)))
{
configuration = new MultiPassConfiguration(passesCount, supplyVoltage, voltageDrop, segmentPercentage);
}
else
{
configuration = new SinglePassConfiguration(cableSegmentCount, supplyVoltage, voltageDrop, segmentPercentage);
}
}
else
{
configuration = new MultipleCableCountConfiguration(cableSegmentCount, supplyVoltage, voltageDrop, segmentPercentage, passesCount);
}
}
return configuration;
}
I was then asked how I could potentially take the refactoring further. I had mentioned that there were a lot of 'magic numbers' in the code, to which Bil correctly replied that there are, but they were numbers that represented real business rules, and as such were not that 'magic'. Armed with the following set of rules that center around the messy if statement:
public class SegmentConfigurationFactory : ISegmentConfigurationFactory
{
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
{
if (new MultiPassSegmentConfigurationParametersSpecification().IsSatisfiedBy(parameters))
return new MultiPassSegmentConfigurationFactory().CreateUsing(parameters);
if (new SinglePassSegmentConfigurationParametersSpecification().IsSatisfiedBy(parameters))
return new SinglePassSegmentConfigurationFactory().CreateUsing(parameters);
if (new MultipleCableCountSegmentConfigurationParametersSpecification().IsSatisfiedBy(parameters))
return new MultiCableCountSegmentConfigurationFactory().CreateUsing(parameters);
return new DefaultSegmentConfigurationFactory().CreateUsing(parameters);
}
}
public ISegmentConfiguration GetConfigurationGiven(
int cableSegmentCount,
int segmentCount,
int passesCount,
int segmentIndex,
int supplyVoltage,
decimal voltageDrop,
decimal segmentPercentage
)
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
public interface ISegmentConfigurationFactory
{
ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters);
}
public class DefaultSegmentConfigurationFactory : ISegmentConfigurationFactory
{
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
{
return new DefaultSegmentConfiguration(1, parameters.SupplyVoltage, parameters.VoltageDrop);
}
}
public class MultiPassSegmentConfigurationFactory : ISegmentConfigurationFactory
{
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
{
return new MultiPassConfiguration(parameters.PassesCount, parameters.SupplyVoltage, parameters.VoltageDrop, parameters.SegmentPercentage);
}
}
public class SinglePassSegmentConfigurationFactory : ISegmentConfigurationFactory
{
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
{
return new SinglePassConfiguration(parameters.CableSegmentCount, parameters.SupplyVoltage, parameters.VoltageDrop, parameters.SegmentPercentage);
}
}
public class MultiCableCountSegmentConfigurationFactory : ISegmentConfigurationFactory
{
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
{
return new MultipleCableCountConfiguration(parameters.CableSegmentCount, parameters.SupplyVoltage, parameters.VoltageDrop, parameters.SegmentPercentage, parameters.PassesCount);
}
}
public interface ISegmentConfigurationParametersSpecification
{
bool IsSatisfiedBy(SegmentConfigurationParameters parameters);
}
public class MultiPassSegmentConfigurationParametersSpecification : ISegmentConfigurationParametersSpecification
{
public bool IsSatisfiedBy(SegmentConfigurationParameters parameters)
{
return parameters.SegmentCount > 1 && parameters.CableSegmentCount == 1 && parameters.PassesCount > 1 && (parameters.SegmentIndex <= (parameters.SegmentCount - 2));
}
}
public class SinglePassSegmentConfigurationParametersSpecification : ISegmentConfigurationParametersSpecification
{
public bool IsSatisfiedBy(SegmentConfigurationParameters parameters)
{
return parameters.SegmentCount > 1 && parameters.CableSegmentCount == 1 && parameters.PassesCount == 1;
}
}
public class MultipleCableCountSegmentConfigurationParametersSpecification : ISegmentConfigurationParametersSpecification
{
public bool IsSatisfiedBy(SegmentConfigurationParameters parameters)
{
return parameters.SegmentCount > 1 &&
parameters.CableSegmentCount > 1;
}
}
public interface ISegmentConfigurationSpecificationBasedFactory : ISegmentConfigurationParametersSpecification,ISegmentConfigurationFactory
{
}
public class SegmentConfigurationFactoryToTheMaxx : ISegmentConfigurationFactory
{
private IEnumerable<ISegmentConfigurationSpecificationBasedFactory> configurationFactories;
public SegmentConfigurationFactoryToTheMaxx(ISegmentConfigurationFactory defaultConfigurationFactory, IEnumerable<ISegmentConfigurationSpecificationBasedFactory> configurationFactories)
{
this.configurationFactories = configurationFactories;
}
public ISegmentConfiguration CreateUsing(SegmentConfigurationParameters parameters)
{
foreach (ISegmentConfigurationSpecificationBasedFactory factory in configurationFactories)
{
if (factory.IsSatisfiedBy(parameters)) return factory.CreateUsing(parameters);
}
throw new ArgumentException(
"There is no factory configured to create a configuration from the set of parameters");
}
}