Recently I have been told that static class/methods are evil.
Take for example my class Logger:
class Logger{
private static $logs = array();
public static function add($msg){
self::$logs[]=$msg;
}
public static function echo(){
print_r(self::$logs);
}
}
I can use whenever i want in my appliaction like this:
Logger::add('My log 1');
But reading this developers:
That Logger class doesn't seem so good.
So: Can I use it statically or I should avoid it at any cost?
Loggers should be declared to be static and final. It is good programming practice to share a single logger object between all of the instances of a particular class and to use the same logger for the duration of the program.
You can use dependency injection in a static class using method or property injection. However, you cannot use constructor injection in a static class because the constructor of a static class cannot accept any parameters.
Logging classes are the exception.
Since they rarely contain much logic, you don't have the same testing concerns.
Logging is a perfect example of a GOOD place to use static classes.
Think of your alternatives:
The above are much worse than using static
for logging.
Avoid it. I've seen quite some posts of you now struggling with the issue and people giving you bad advice. I'll repeat what I said in some of my answers/comments.
The way you use static in your logger class is to use it as a globally access point. Whenever you need to logg something you call Logger::log().
1) You will not be able to tell from looking at your class definition that it depends on the Logger class. Change in code thus becomes an adventure: 'I hope I will not break some hidden dependency when I change this tiny little ... OOPS!'.
2) It IS harder to test. You can't realiably test a class that sends a message to the Logger with Logger::log(). When a test fails how will you know it is not because the Logger fails? You would know if you could replace it with a mock, but in your case it is not mockable.
An alternative to explore:
Use the observer pattern and make the Logger an observer, the classes that need logging can be observables. They send messages like $this->observers->nofify('test succeeded').
You could use some other form of events too or dependency injection (automatic or manual). But please please don't call Logger::log() in a method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With