In general, it has been told to me that dependencies should be injected. That concerns should be separated. That control should be inverted. But why?
For example, what if we use separation of concerns but don't do inversion of control. Why is it so wrong? i.e. see code below for discussion..
class BusinessFunctionality
{
public $motor;
function doStuff()
{
//i.e. at creation time we are not injecting data
//into motor. We create empty motor then set data to it later
$this->motor = new Motor();
//motor loads data into itself
$this->motor->loadMotor();
}
}
class Motor
{
public $motorData;
function loadMotor()
{
$motorData = new MotorData();
//MotorData is another class created to
//separate concerns of Motor functionality
//from database details
//we load up data acquired by MotorData, into Motor
$this->motorData = $motorData->loadMotor();
}
}
class MotorData
{
function loadMotor()
{
//mock Database
$type = "industrial";//$db->query("SELECT... FROM .. ");
return $type;
}
}
//invocation
$business = new BusinessFunctionality();
$business->doStuff();
print "Motor type is " . $business->motor->motorData;
Question: What are the problems that will make the approach above prone to issues?
DataMapper Pattern
For comparison purposes, a more advocated way ios if I use dependency injection and inversion of control and separation of concerns, I have implemented a DataMapper
pattern to look something like this:
//business object
class MyMotor
{
private $data;
function __construct(MotorDataType $data)
{
$this->data = $data;
}
function getType()
{
return $this->data->getType();
}
}
//data mapper object
class MyMotorMapper
{
function getMotorWithData()
{
//get data. i.e from whatever source
$data = (new DatabaseMock())->getData();
//inject data into the object
$motor = new MyMotor($data);
//return motor to the caller
return $motor;
}
}
class MotorDataType
{
private $motorType;
function getType()
{
return $this->motorType;
}
function setMotorType($type)
{
$this->motorType = $type;
}
}
//database object
class DatabaseMock
{
function getData()
{
$data = new MotorDataType();
$data->setMotorType("industrial");
return $data;
}
}
//invocation
$motor = (new MyMotorMapper())->getMotorWithData();
print "Motor type is " . $motor->getType();
Not entirely sure I like the way it turned out, but it demonstrates the principles I am trying to show (DI, SOC, IofC)