I have been practicing how to write clean code using SOLID. I have also been using DI in my code to remove coupling but only through constructor injection. In the many cases I have used DI, I have only used it to call methods. What I do not understand yet is how to decouple when you have a dependent class whose constructor takes an argument inside another class. If var obj = new A(month)
creates dependency and tight coupling inside class B, how do I decouple/abstract this? Is this where the interface with property comes in? If so, how do I use it here?
public class A
{
private string _month;
public A(string month)
{
_month = month;
}
}
public class B
{
public List<A> ListOfMonths;
public B()
{
ListOfMonths = new List<A>();
}
public List<A> SomeMethod()
{
string[] months = new []
{
"Jan",
"Feb",
"Mar"
};
foreach(var month in months)
{
var obj = new A(month); // If this is coupling, how do I remove it?
ListOfMonths.Add(obj)
}
return ListOfMonths;
}
}
If you want to decouple, you need to remove any reference to A from B and replace them by IA (interface similar to A) which is a placeholder for any class which would replace A.
In the constructor of B you then provide a factory able to create instances of IA. You go further by placing an abstract factory which means you provide an interface of a factory capable of creating instances of IA.
Here is a sample based on your code:
public interface IA
{
}
public interface IAFactory
{
IA BuildInstance(string month);
}
public class AFactory : IAFactory
{
public IA BuildInstance(string month)
{
return new A(month);
}
}
public class A : IA
{
public A(string month)
{
}
}
public class B
{
private readonly IAFactory factory;
public List<IA> ListOfMonths;
public B(IAFactory factory)
{
this.factory = factory;
ListOfMonths = new List<IA>();
}
public List<IA> SomeMethod()
{
string[] months = new[] {"Jan", "Feb", "Mar"};
foreach (var month in months)
{
var obj = factory.BuildInstance(month);
ListOfMonths.Add(obj);
}
return ListOfMonths;
}
}