Bringing this class in line with the dependency inversion principle

The Wikipedia definition for DI says:

but. High-level modules should not be dependent on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.

I am trying to apply this principle to my code:

class Printer{ private $logger; function __construct(Zend_Log $logger){ $this->logger=$logger; } function print(){ //Some code $this->logger->log('Logger in action ;)'); } } 

Now, since the Printer class depends on Zend_Log , which is neither an abstract class nor an interface, I violate the principle of dependency inversion.

How can I fix this, knowing that Zend_Log does not extend the abstract class and does not implement the interface?

+7
source share
2 answers

The easiest approach is to use an interface adapter, for example. create the API that your printer should use in the interface, and then implement this interface in the adapter for the Zend_Log component. Pass the concrete adapter to the printer. Then the printer will depend on PrinterLog, and not on a specific Zend_Log.

 interface PrinterLog { public function log($whatever); } class ZendPrinterLogAdapter implements PrinterLog { private $logger; public function __construct(Zend_Log $logger) { $this->logger = $logger } public function log($whatever) { // delegate call to $this->logger } } class Printer { private $logger; function __construct(PrinterLog $logger) { $this->logger = $logger; } } $printer = new Printer(new ZendPrinterLogAdapter(new Zend_Log)); 
+5
source

Here are some alternatives for using the same API .. so this will be the default setting:

 interface Printerish // couldn't think of a good ajective { public function print(); } interface CanLogStuff // couldn't think of a good ajective { public function log( $text ); } class Printer implements Printerish { public function print() { // do something } } 

And this will be a loggable printer:

 class LoggedPrinter implements Printerish { protected $logger; protected $pritner; public function __construct( Printerish $printer, CanLogStuff $logger ) { $this->logger = $logger; $this->printer = $printer; } protected function print() { $this->logger( 'I can print, I can print !!' ); $this->printer->print(); } } 

In this case, the following precedent is used: if in the real world you want to start controlling the use of a real printer (the intern was printing the Internet again). Then you will not make another printer. You would try to add external control.

In programming, this refers to the Open / closed Principle .

Keep in mind that this is just an idea, and you should carefully study this before trying to use it in production code.

+2
source

All Articles