Как вы организуете вход в свои приложения? Я имею в виду веб-приложения или приложения командной строки, или даже мобильные приложения. Могу поспорить, у вас есть глобальная переменная или синглтон, известный как Logger
, который имеет несколько методов, таких как info()
, error()
и debug()
. Вы настраиваете его при запуске приложения или настраиваете его через что-то вроде log4j.properties
и записывает все на консоль, в файл или даже в базу данных. Я делал именно это, или что-то очень похожее , много лет, пока, наконец, не осознал, насколько неправильным был этот подход. В одном из моих недавних приложений на Ruby я делал все по-другому, и с тех пор я гораздо счастливее, чем был раньше.
Что ж, если ваше приложение простое и почти не имеет модульных или интеграционных тестов, у вас все будет в порядке со статическим регистратором, который по сути является глобальной переменной. Однако, как мы уже говорили , глобальные переменные являются злом. Что может пойти не так, если мы используем статический регистратор? Или, другими словами, как говорил один из моих друзей, какую именно проблему мы собираемся решить? В основном, есть две проблемы:
- Во-первых, с помощью одного глобального регистратора вам будет сложно написать модульный тест, чтобы проверить, правильно ли ваше приложение регистрирует события. Даже если вы перехватите поток журнала, будет много шума от других потоков и других тестов. Это не решаемая проблема, но ее решение усложняет ваши тесты.
- Во-вторых, когда вы решите показать выбранную часть журнала конечному пользователю, вам придется много писать, чтобы разделить то, что принадлежит пользователю, а что нет, особенно в многопоточной среде. , Вам повезло, если это Java и у вас есть группы потоков, но в Ruby, например, такого нет, и вам придется найти обходной путь.
Чтобы преодолеть их оба, в Zold , приложении для командной строки Ruby, я решил передать log
как переменную всем классам, которые нуждаются в журналировании. В Ruby это проще, чем в Java, потому что они имеют необязательные параметры. Посмотрите на этот класс , например (это упрощенная версия, конечно):
01
02
03
04
05
06
07
08
09
10
11
12
13
|
class Zold::List def initialize(wallets:, log: Log::NULL) @wallets = wallets @log = log end def run @wallets .all.sort.each do |id| @wallets .acq(id) do |wallet| @log .info( "#{id}: #{wallet.balance}" ) end end end end |
Предполагается, что этот класс перечислит все кошельки в текущем каталоге и выведет их балансы в журнал, который в некоторых случаях будет консолью. Тем не менее, когда этот класс вызывается из веб-приложения, местом назначения для печати является временный файл, который позднее отображается на веб-странице. В модульных тестах это может быть что-то еще, что должно захватывать все, что отправляется в журнал, а затем доставляется в модульный тест.
Как видите, значением по умолчанию для log
является Log::NULL
, который является константой, которую я должен был определить сам, как регистратор по умолчанию, который нигде ничего не регистрирует. По умолчанию этот класс ничего не регистрирует. Он будет спокойно проверять все остатки всех кошельков и ничего не печатать. Ну, это будет печатать, но никто этого не увидит.
В модульном тесте я создаю объект с помощью нескольких методов, таких как debug()
, info()
и т. Д., И передаю его экземпляру класса Zold::List
, который я тестирую. Другими словами, это поддельная / фиктивная версия регистратора, которую я использую для захвата всего, что отправляет Zold::List
. Тогда я могу проверить, что там.
Я говорю очевидные вещи здесь? Если так, почему у нас все еще есть статические регистраторы повсюду в Java, Ruby, PHP, C # и т. Д.? В любом случае, я рекомендую вместо этого использовать инъекционную зависимость ведения журнала.
И да, к слову, я уверен, что вы заметили изменение в названии. Это больше не logger
, это log
. Я уверен, что ты знаешь почему .
Опубликовано на Java Code Geeks с разрешения Егора Бугаенко, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Ведение журнала без статического регистратора Мнения, высказанные участниками Java Code Geeks, являются их собственными. |