Ponieważ moje obecne projekty Java stają się coraz większe, odczuwam również rosnącą potrzebę wstawiania wyników debugowania w kilku punktach mojego kodu.
Aby odpowiednio włączyć lub wyłączyć tę funkcję, w zależności od otwarcia lub zamknięcia sesji testowych, zwykle umieszczam private static final boolean DEBUG = false
na początku zajęć, które sprawdzają moje testy, i trywialnie używam go w ten sposób (na przykład):
public MyClass {
private static final boolean DEBUG = false;
... some code ...
public void myMethod(String s) {
if (DEBUG) {
System.out.println(s);
}
}
}
i tym podobne.
Ale to mnie nie rozśmiesza, bo oczywiście działa, ale może być zbyt wiele klas, aby ustawić DEBUG na prawdę, jeśli nie gapisz się tylko na kilka z nich.
I odwrotnie, ja (jak - myślę - wielu innych) nie chciałbym przełączać całej aplikacji w tryb debugowania, ponieważ ilość wysyłanego tekstu może być przytłaczająca.
Czy jest więc właściwy sposób na architektoniczną obsługę takiej sytuacji, czy najbardziej poprawnym jest użycie członka klasy DEBUG?
Odpowiedzi:
Chcesz spojrzeć na strukturę rejestrowania, a może na strukturę fasady rejestrowania.
Istnieje wiele ram rejestrowania, często z nakładającymi się funkcjami, do tego stopnia, że z czasem wielu ewoluowało, aby polegać na wspólnym interfejsie API, lub zaczęło być używanych przez strukturę elewacji, aby wyodrębnić ich użycie i umożliwić ich zamianę na miejscu Jeśli potrzebne.
Ramy
Niektóre ramy rejestrowania
Niektóre fasady z logowaniem
Stosowanie
Podstawowy przykład
Większość z tych frameworków pozwoli ci napisać coś w formie (tutaj używając
slf4j-api
ilogback-core
):Zwróć uwagę na użycie bieżącej klasy do stworzenia dedykowanego programu rejestrującego, który pozwoliłby SLF4J / LogBack sformatować dane wyjściowe i wskazać, skąd pochodzi komunikat rejestrowania.
Jak zauważono w podręczniku SLF4J , typowy wzorzec użycia w klasie to zwykle:
Ale w rzeczywistości jeszcze bardziej powszechne jest deklarowanie programu rejestrującego za pomocą formularza:
Pozwala to na użycie rejestratora również z metod statycznych i jest dzielony między wszystkie instancje klasy. Jest to prawdopodobnie preferowana forma. Jednak, jak zauważył Brendan Long w komentarzach, musisz mieć pewność, że rozumiesz implikacje i odpowiednio decydujesz (dotyczy to wszystkich ram rejestrowania następujących po tych idiomach).
Istnieją inne sposoby tworzenia instancji rejestratorów, na przykład za pomocą parametru ciągu w celu utworzenia nazwanego rejestratora:
Poziomy debugowania
Poziomy debugowania różnią się w zależności od frameworka, ale typowe są (w kolejności krytyczności, od łagodnych do złych gówno-nietoperzy i od prawdopodobnie bardzo powszechnych do, miejmy nadzieję, bardzo rzadkich):
TRACE
Bardzo szczegółowe informacje. Powinny być zapisywane tylko w dziennikach. Służy tylko do śledzenia przepływu programu w punktach kontrolnych.DEBUG
Dokładna informacja. Powinny być zapisywane tylko w dziennikach.INFO
Znaczące zdarzenia w czasie wykonywania. Powinny być natychmiast widoczne na konsoli, więc używaj oszczędnie.WARNING
Nieprawidłowości w działaniu i błędy, które można naprawić.ERROR
Inne błędy w czasie wykonywania lub nieoczekiwane warunki.FATAL
Poważne błędy powodujące przedwczesne zakończenie.Bloki i Strażnicy
Załóżmy, że masz sekcję kodu, w której masz zamiar napisać kilka instrukcji debugowania. Może to szybko wpłynąć na wydajność, zarówno ze względu na wpływ samego rejestrowania, jak i generowania wszelkich parametrów przekazywanych do metody rejestrowania.
Aby uniknąć tego rodzaju problemów, często chcesz napisać coś w formie:
Jeśli nie używałeś tego zabezpieczenia przed blokiem instrukcji debugowania, mimo że komunikaty mogą nie być wyprowadzane (jeśli na przykład twój program rejestrujący jest obecnie skonfigurowany do drukowania tylko rzeczy powyżej
INFO
poziomu),heavyComputation()
metoda nadal byłaby wykonana .Konfiguracja
Konfiguracja jest dość zależna od struktury rejestrowania, ale oferują one w większości te same techniki:
Oferują również w większości te same możliwości:
Oto typowy przykład konfiguracji deklaratywnej przy użyciu
logback.xml
pliku.Jak wspomniano, zależy to od twojego frameworka i mogą istnieć inne alternatywy (na przykład LogBack pozwala również na użycie skryptu Groovy). Format konfiguracji XML może również różnić się w zależności od implementacji.
Więcej przykładów konfiguracji można znaleźć (między innymi) w:
Trochę historycznej zabawy
Należy pamiętać, że Log4J widzi znaczącą aktualizację w tej chwili, przejście z wersji 1.x do 2.x . Możesz rzucić okiem na więcej historycznej zabawy lub zamieszania, a jeśli wybierzesz Log4J, prawdopodobnie wolisz korzystać z wersji 2.x.
Warto zauważyć, jak wspomniał Mike Partridge w komentarzach, że LogBack został stworzony przez byłego członka zespołu Log4J. Który został stworzony w celu wyeliminowania niedociągnięć platformy Java Logging. I że nadchodząca główna wersja Log4J 2.x sama teraz integruje kilka funkcji zaczerpniętych z LogBack.
Zalecenie
Podsumowując, pozostań oddzielony jak najwięcej, baw się z kilkoma i zobacz, co będzie dla Ciebie najlepsze. Ostatecznie jest to po prostu struktura rejestrowania . Z wyjątkiem przypadku, gdy masz bardzo konkretny powód, oprócz łatwości użycia i osobistych preferencji, każdy z nich byłby raczej w porządku, więc nie ma sensu się nad nim wisieć. Większość z nich można również rozszerzyć na Twoje potrzeby.
Mimo to, gdybym dzisiaj musiał wybrać kombinację, wybrałbym LogBack + SLF4J. Ale jeśli zapytałeś mnie kilka lat później, poleciłbym Log4J z logowaniem Apache Commons, więc miej oko na swoje zależności i rozwijaj się wraz z nimi.
źródło
static
, ponieważ oszczędza niewielką ilość pamięci, ale w niektórych przypadkach powoduje problemy: slf4j.org/faq.html#declared_staticużyj środowiska rejestrowania
przez większość czasu istnieje statyczna metoda fabryczna
następnie możesz wyprowadzić kod logowania na różnych poziomach:
wtedy będzie jeden plik, w którym możesz zdefiniować, które komunikaty dla każdej klasy powinny być zapisywane na wyjściu dziennika (plik lub stderr)
źródło
Właśnie do tego służą frameworki rejestrowania, takie jak log4j lub nowszy slf4j. Pozwalają na bardzo szczegółowe kontrolowanie rejestrowania i konfigurowanie go nawet podczas działania aplikacji.
źródło
Struktura rejestrowania jest zdecydowanie najlepszym rozwiązaniem. Musisz także mieć dobry zestaw testów. Dobre pokrycie testowe może często wyeliminować potrzebę debugowania danych wyjściowych łącznie.
źródło