If you don't fix the root cause of the complexity, you can make life easier by adding another layer of abstraction to keep the dirt under the rug, but you'll have to add other hacks. You'll end up with something slightly more maintainable, but the technical debtThis will still be thereease maintaining the code base until you get time to refactor it (or move to a new one :) ).
If you don't fix the root cause of the complexity, you can make life easier by adding another layer of abstraction to keep the dirt under the rug, but you'll have to add other hacks. You'll end up with something slightly more maintainable, but the technical debt will still be there.
If you don't fix the root cause of the complexity, you can make life easier by adding another layer of abstraction. This will ease maintaining the code base until you get time to refactor it (or move to a new one :) ).
As you said, the existing code has design problems as it is. First, having methods and constructors with so many (different!) parameters is a design smell.
If you don't fix the root cause of the complexity, you can make life easier by adding another layer of abstraction to keep the dirt under the rug, but you'll have to add other hacks. You'll end up with something slightly more maintainable, but the technical debt will still be there.
- Make classes for the passed parameters (Param1, Param2, Param3).
- [Hack] Add a common interface (say IParameter) for the 3 classes.
- It's a hack because the interface is not really common, but if you want to have only one switch in your Factory, that's a solution (the one I could find).
- Create a factory for the IParameter interface. The factory itself decides what to build based on the parameters it is set.
- [Hack] In the constructors of the existing classes, add a switch statement based on the concrete class type of the IParameter object.
- It's a hack because this is not what interfaces should be used for. Interfaces should provide an abstraction for common behavior.
DonNet Fiddle with working example: https://dotnetfiddle.net/NoChOk
The code for perusal:
using System; public class Program { public void Main() { IHandler first = HandlerFactory.CreateInstance( HandlerType.Handler1, ParamBuilder.start().withOne("x").withTwo("y").build()); IHandler second = HandlerFactory.CreateInstance( HandlerType.Handler2, ParamBuilder.start().withAlpha(1).withBeta(new DateTime()).build()); IHandler third = HandlerFactory.CreateInstance( HandlerType.Handler3, ParamBuilder.start().withMickey(":)").withMouse(1L).build()); first.DoStuff(); second.DoStuff(); third.DoStuff(); } class HandlerFactory { public static IHandler CreateInstance(HandlerType type, IParam param) { switch (type) { case HandlerType.Handler1: return new Handler1(param); case HandlerType.Handler2: return new Handler2(param); case HandlerType.Handler3: return new Handler3(param); default: throw new NotSupportedException(); } } } enum HandlerType { Handler1, Handler2, Handler3 } interface IHandler { void DoStuff(); } class Handler1 : IHandler { private Param1 numbers; private Param2 letters; private Param3 disney; public Handler1(IParam param) { if (param is Param1) numbers = (Param1) param; if (param is Param2) letters = (Param2) param; if (param is Param3) disney = (Param3) param; } public void DoStuff() { Console.WriteLine("I am alive - Handler 1");} } class Handler2 : IHandler { private Param1 numbers; private Param2 letters; private Param3 disney; public Handler2(IParam param) { if (param is Param1) numbers = (Param1) param; if (param is Param2) letters = (Param2) param; if (param is Param3) disney = (Param3) param; } public void DoStuff() { Console.WriteLine("I am alive - Handler 2");} } class Handler3 : IHandler { private Param1 numbers; private Param2 letters; private Param3 disney; public Handler3(IParam param) { if (param is Param1) numbers = (Param1) param; if (param is Param2) letters = (Param2) param; if (param is Param3) disney = (Param3) param; } public void DoStuff() { Console.WriteLine("I am alive - Handler 3");} } interface IParam { string One { get; } string Two { get; } // first param class int Alpha { get; } DateTime Beta { get; } // second param class string Mickey { get; } long Mouse { get; } // third param class } class ParamBuilder { private string one, two; private int? alpha; private DateTime? beta; private string mickey; private long? mouse; public static ParamBuilder start() { return new ParamBuilder(); } public IParam build() { if (!string.IsNullOrEmpty(one) && !string.IsNullOrEmpty(one)) { return new Param1(one, two); } if (alpha.HasValue && beta.HasValue) { return new Param2(alpha.Value, beta.Value); } if (!string.IsNullOrEmpty(mickey) && mouse.HasValue) { return new Param3(mickey, mouse.Value); } throw new NotSupportedException(); } public ParamBuilder withOne(string one) { this.one = one; return this; } public ParamBuilder withTwo(string two) { this.two = two; return this; } public ParamBuilder withAlpha(int alpha) { this.alpha = alpha; return this; } public ParamBuilder withBeta(DateTime beta) { this.beta = beta; return this; } public ParamBuilder withMickey(string m) { this.mickey = m; return this; } public ParamBuilder withMouse(long m) { this.mouse = m; return this; } } class Param1 : IParam { public string One { private set; get; } public string Two { private set; get; } public int Alpha { get {throw new NotImplementedException();} } public DateTime Beta { get {throw new NotImplementedException();} } public string Mickey { get {throw new NotImplementedException();} } public long Mouse { get {throw new NotImplementedException();} } public Param1(string one, string two) { One = one; Two = two; } } class Param2 : IParam { public int Alpha { private set; get; } public DateTime Beta { private set; get; } public string One { get {throw new NotImplementedException();} } public string Two { get {throw new NotImplementedException();} } public string Mickey { get {throw new NotImplementedException();} } public long Mouse { get {throw new NotImplementedException();} } public Param2(int alpha, DateTime beta) { Alpha = alpha; Beta = beta; } } class Param3 : IParam { public string Mickey { private set; get; } public long Mouse { private set; get; } public string One { get {throw new NotImplementedException();} } public string Two { get {throw new NotImplementedException();} } public int Alpha { get {throw new NotImplementedException();} } public DateTime Beta { get {throw new NotImplementedException();} } public Param3(string mi, long mo) { Mickey = mi; Mouse = mo; } } }