2012-12-04 10 views
8

Poszukując a project, który używa Common.Logging dla .NET, zauważyłem, że niektóre klasy deklarują instancję rejestratora jako statyczny element klasy. Na przykład:W języku C# powinien mój rejestrator Common.Logging być członkiem instancji lub statyczne?

public class HelloJob : IJob 
{ 
    private static ILog _log = LogManager.GetLogger(typeof(HelloJob)); 

    public HelloJob() 
    { 
    } 

    public virtual void Execute(IJobExecutionContext context) 
    { 
     _log.Info(string.Format("Hello World! - {0}", System.DateTime.Now.ToString("r"))); 
    } 
} 

A w innych klasach rejestrator jest zadeklarowana jako członek przykład:

public class SimpleExample : IExample 
{ 
    public virtual void Run() 
    { 
     ILog log = LogManager.GetLogger(typeof (SimpleExample)); 

     log.Info("------- Initializing ----------------------"); 

     // etc 
    } 
}  

Czy istnieje powód do preferowania jednego lub drugiego podejścia?

W jakich przypadkach zalecane jest każde podejście? Czy ma to związek z bezpieczeństwem wątków?

Czy byłby to problem, gdybym właśnie ogłosił klasę "Logger" ze statycznym "loggerem" i całym projektem (oprócz problemu, który w praktyce miałbym zmienną globalną)?

Odpowiedz

9

Większość rejestratorów jest bezpieczna dla wątków, a tworzenie ich wystąpień ma bardzo mały wpływ, zarówno pod względem czasu, jak i pamięci. Tak więc prawdziwe pytanie musi brzmieć sensownie z punktu widzenia programowania i konserwacji.

Z jednej strony, ponieważ rejestrator jest koncepcyjnie przywiązany do swojej klasy, a nie na przykład klasy, wiele osób woli zachować to statyczne. To jest całkowicie poprawny argument. Na przykład, jeśli HelloWorldJob rozszerza HelloJob, myślę, że większość ludzi oczekiwałaby, że komunikat dziennika napisany przez kod w HelloJob zostanie powiązany z klasą HelloJob, nawet jeśli masz bardziej specyficzną instancję podklasy. Fajnie jest też mieć dostęp do rejestratora za pomocą metod statycznych, co nie byłoby możliwe, gdyby nie było na statycznym polu.

Z drugiej strony, nie ma żadnego powodu, dla którego Twój HelloJob powinien być odpowiedzialny za uzyskanie własnej instancji rejestratora. Wiele się mówi o używaniu zastrzyku zależności (testowalność jednostki, dodatkowa konfigurowalność i prostszy kod). Tak więc osobiście sugeruję, aby twój logger został wstrzyknięty przez strukturę DI, w którym to przypadku musiałby zostać przywołany w polu dla każdej instancji.

public class HelloJob : IJob 
{ 
    private readonly ILog _log; 

    public HelloJob(ILog log) 
    { 
     _log = log; 
    } 
    ... 
} 

Twój ramy DI można skonfigurować rejestrator w oparciu o szczegóły to wie w czasie wykonywania, lub można podać fałszywe lub wyśmiewany rejestratora w badaniach jednostkowych, aby upewnić się, że oczekiwane komunikaty dziennika są produkowane. Zwróć uwagę, że nawet jeśli odwołujesz się do pola każdej instancji, możesz nadal używać instancji klasy (lub nawet pojedynczej) - to tylko szczegóły, które nie muszą być częścią tej klasy dotyczyć.

+0

'LogManager.GetLogger' jest prawdopodobnie wewnętrznie implementowany poprzez wtrysk zależności; oznacza to, że zależność jest zarządzana w ramach programu rejestrującego. Nie chciałbym, aby moje rejestratory były przechowywane jako "pole dla instancji" i uzyskiwanie tego narzutu dla każdej utworzonej instancji. Statyczne przechowywanie go raz, gdy klasa jest załadowana po raz pierwszy, działa dla mnie. –

+2

@ChrisSinclair: To prawda, że ​​szczegóły * tworzenia * są obsługiwane przez LogManager.GetLogger, a ja lubię tę Commons.Logging zapewnia wspólny interfejs logowania, pozostawiając ci swobodę przełączania podstawowych struktur, konfiguracji itp. Jednak jest to przykład wzoru fabrycznego, a nie iniekcji zależnej. Wzorzec fabryczny ma wiele zalet w porównaniu do ręcznego tworzenia instancji, ale iniekcja Dependency nadal ma dodatkowe zalety. Twój framework DI może wciąż być skonfigurowany do ponownego użycia pojedynczego rejestratora dla każdego typu, a narzut jest praktycznie niezmierzony w 90% przypadków. – StriplingWarrior

+0

Dokumentacja Common.Logging stwierdza, że ​​publiczne statyczne LogManagers są bezpieczne dla wątków, ale metody instancji nie są, co wydaje się być sprzeczne z tą odpowiedzią. http://netcommon.sourceforge.net/docs/2.0.0/api/html/Common.Logging~Common.Logging.LogManager.html – coderjoe

Powiązane problemy