Constructor embedding - is it normal to use a new null object if the constructor does not specify?

Imagine that I have a bunch of classes that can do logging, so I created a logging interface and a couple of implementations (writing to a file, to stdout, db, etc.), but sometimes I don’t care about logging these messages, so I made an implementation that simply ignores all posts.

Now this helps to avoid if and just use $this->logger->write($message) , but I still have to enter a dummy logger every time.

So will this have any harm in creating things like: $this->logger = $logger ? $logger : new DummyLogger() $this->logger = $logger ? $logger : new DummyLogger() in the constructor.

I do not work in the constructor at all, but this kind of thing does not seem too dangerous.

Would you choose this approach?

+6
source share
2 answers

Before answering your question, I would suggest reviewing your Logger architecture. Logging is always the same. You write a message somewhere. The only thing that is different is the part somewhere, so it makes sense to split your Logger into a common Logger and various Writers. This allows you to increase flexibility, for example, you can use the Composite template for recording to multiple registrars at once.

Regarding your question: in general, you want to avoid hard-coding dependencies in the code, because this will directly affect testability and reuse, for example. your Logger can only be used with this particular NullWriter. If you intend to distribute Logger, you will also have to distribute Writer.

However, assuming that you will still be distributing Logger with the entire Writers package, and you are also providing ctor injection tools, I don't see a big problem. You can still change the text of the Writer, if necessary, so everything is fine.

This is slightly different when we talk about interdependent dependencies. You will want to avoid this, for example. your classes in the Database package should not depend on the classes in the Logger package.

An alternative to assigning NullWriter from within Logger would be to use a LoggerFactory, which creates a Logger and the specified Writer, inserts Writer and returns a Logger.

+1
source

I would not choose this approach because it is a complex dependency and an additional class. There are templates to avoid these problems - and solve your dilemma.

You can implement an observer template version, for example:

 class Loggable { protected $aLoggers = array(); public function addLogger(Logger $oLog) { $this->aLoggers[] = $oLog; } public function invokeLoggers($sMessage) { foreach($this->aLoggers as $oLog) { $oLog->write($sMessage); } } } 

These functions must be in a separate class, so any class that uses registrars can extend this functionality. Now you can refuse to add registrars and thus the call will do nothing - or not extend the source class at all.

 class SomeClass extends Loggable { public function doSomething() { // Some code $this->invokeLoggers(); } } $oSomeClass = new SomeClass(); $oSomeClass->addLogger(new FileLogger()); $oSomeClass->addLogger(new DatabaseLogger()); $oSomeClass->addLogger(new EmailLogger()); $oSomeClass->doSomething(); 
+1
source

Source: https://habr.com/ru/post/902737/


All Articles