I am trying to understand what really defines tight coupling. I have read a number of posts on the subject but one thing still doesn't sit right with me.
I understand that classes should be injected into other classes using their interfaces rather their concrete implementations. I also understand that if a class adheres to an interface then any class which uses the injected interface can call the public functions defined in the interface and expect similar functionality.
interface iFormatter()
{
public function format(array $order): array
}
public class OrderFormatter implements iFormatter
{
public function format(array $order): array
{
// ...
return $formattedArray;
}
}
public class OrderGenerator implements iGenerator
{
private $formatter;
public function __construct(iFormatter $formatter)
{
$this->formatter = $formatter;
}
public function generate()
{
// ...
return $this->formatter->format($order);
}
}
So I think in the case where only the formatter changes, this would be defined as loosely coupled;
$example = new OrderGenerator(new CarOrderFormatter);
$example->generate();
$example = new OrderGenerator(new VanOrderFormatter);
$example->generate();
What I don't quite get though is when you abstract responsibilities away from each other but those classes are still closely tied to each other. Something like
$example = new CarOrderGenerator(new CarOrderFormatter);
$example->generate();
$example = new VanOrderGenerator(new VanOrderFormatter);
$example->generate();
Yes you could pass in a different formatter to these generators, but surely more often that not some error would occur within the format
function if it is expecting certain data from the generate
function in the XXXOrderGenerator
concrete class?
So I believe I have abstracted the responsibilities to their own classes in the last example above and although interfaces have been used i'm not sure if this is still tightly coupled or is technically loosely coupled? Or if I have missed the point entirely...