Skip to content

Latest commit

 

History

History
88 lines (72 loc) · 2.7 KB

solid.md

File metadata and controls

88 lines (72 loc) · 2.7 KB

SOLID

The only SOLID principle needed is Dependency Inversion and its implementation through dependency injection, which helps achieve Low Coupling.

The main goal of the Dependency Inversion principle is to reduce the coupling between classes.

interface FileContract 
{
    public function getDocumentBody(): string;
}

class Bill implements FileContract 
{
    public function getDocumentBody(): string
    {
        # some logic
        return "Bill sum";
    }
}

class Report implements FileContract 
{
    public function getDocumentBody(): string
    {
        # some logic
        return "Report data";
    }
}

class Printer 
{
    public function execute(FileContract $file) 
    {
        // printing logic
    }
}

class PrintBill 
{
    public function execute() 
    {
        $printer = new Printer();
        
        $bill = new Bill();
        $printer->execute($bill);
    }
}

class PrintReport 
{
    public function execute() 
    {
        $printer = new Printer();
        
        $report = new Report();
        $printer->execute($report);
    }
}

The Printer class depends on the FileContract interface, which needs to be implemented. This approach allows the Printer class to be used for printing anything. The only problem is that if the Printer class also takes another object in its constructor, for example, PrinterSettings, then PrintReport and PrintBill will also depend on the PrinterSettings class, even though it is only used for setting up the Printer.

We can turn to the tool that solves the dependency problem. The unnecessary dependency can be removed using Dependency Injection, which provides inversion of control from the principles of OOP. By configuring the class once using an abstraction, it can be used in other implementations without dragging unnecessary dependencies into the class. There are implementation examples in the vendor packages php di, symfony and laravel.

class PrintReport 
{
    private Printer $printer;

    public function __construct(Printer $printer)
    {
        $this->printer = $printer;
    }
    public function execute() 
    {
        $report = new Report();
        $this->printer->execute($report);
    }
}

$printReport = $container->get(PrintReport::class);
$printReport->execute();

The $container variable is initialized in the core and is global throughout the application. It is executed through a facade/singleton or other means. In Laravel, this is the app() function, while in Symfony, the ContainerBuilder class is responsible for obtaining the configured object.