Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use static class for my Logger?

Tags:

oop

php

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:

  • http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/

That Logger class doesn't seem so good.

So: Can I use it statically or I should avoid it at any cost?

like image 952
dynamic Avatar asked May 16 '11 23:05

dynamic


People also ask

Should a logger be static?

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.

Can we use static class in dependency injection?

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.


2 Answers

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:

  • A global instance of a logging object?
  • A singleton logging object?
  • Pass the logging object around to every single method/class (via in a constructor)?

The above are much worse than using static for logging.

like image 104
Byron Whitlock Avatar answered Sep 18 '22 14:09

Byron Whitlock


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.

like image 23
koen Avatar answered Sep 20 '22 14:09

koen