Правильная регистрация в контексте ООП - PullRequest
8 голосов
/ 17 сентября 2008

Вот проблема, с которой я боролся с тех пор, как впервые начал изучать объектно-ориентированное программирование: как реализовать регистратор в «правильном» ООП-коде?

Под этим я подразумеваю объект, у которого есть метод, к которому мы хотим, чтобы каждый другой объект в коде имел доступ; этот метод будет выводить на консоль / файл / что угодно, что мы будем использовать для регистрации - следовательно, этот объект будет объектом регистратора.

Мы не хотим устанавливать объект регистратора как глобальную переменную, потому что глобальные переменные плохие, верно? Но мы также не хотим, чтобы объект logger передавался в параметрах каждого метода, который мы вызываем, в каждом объекте.

В колледже, когда я рассказал об этом профессору, он не мог дать мне ответ. Я понимаю, что на самом деле есть пакеты (например, Java), которые могут реализовать эту функцию. Однако в конечном итоге я ищу знания о том, как правильно и ООП реализовать это самостоятельно.

Ответы [ 16 ]

13 голосов
/ 17 сентября 2008

Вы делаете хотите установить регистратор как глобальную переменную, потому что глобальные переменные не плохие. По крайней мере, они не плохие по своей сути. Регистратор является отличным примером правильного использования глобально доступного объекта. Читайте о шаблоне проектирования Singleton, если вам нужна дополнительная информация.

4 голосов
/ 17 сентября 2008

Есть несколько очень хорошо продуманных решений. Некоторые включают обход ОО и использование другого механизма (АОП).

Ведение журнала на самом деле не слишком хорошо для ОО (что хорошо, не все). Если вам нужно реализовать это самостоятельно, я предлагаю просто создать экземпляр «Журнал» в верхней части каждого класса:

личный конечный журнал = новый журнал (это);

и все ваши звонки в журнале будут тривиальными: log.print ("Эй");

Что делает его намного проще в использовании, чем синглтон.

Пусть ваш регистратор определит, в каком классе вы проходите обучение, и используйте его для аннотирования журнала. Так как у вас есть экземпляр журнала, вы можете делать такие вещи:

log.addTag ( "Bill");

И журнал может добавлять счет тегов к каждой записи, чтобы вы могли реализовать лучшую фильтрацию для вашего дисплея.

log4j и бензопила - идеальное готовое решение - если вы не просто учитесь, используйте их.

2 голосов
/ 27 октября 2008

Глобально доступный регистратор - трудность для тестирования. Если вам нужна «централизованная» функция ведения журнала, создайте ее при запуске программы и внедрите в классы / методы, которые требуют ведения журнала. Как вы тестируете методы, которые используют что-то вроде этого:

public class MyLogger 
{
    public static void Log(String Message) {}
}

Как заменить его на макет?

Лучше:

public interface ILog 
{
    void Log(String message);
}

public class MyLog : ILog 
{
    public void Log(String message) {}
}
1 голос
/ 17 сентября 2008

Я всегда использовал шаблон Singleton для реализации объекта регистрации.

0 голосов
/ 28 августа 2010

Чтобы избежать глобальных переменных, я предлагаю создать глобальную РЕГИСТРАЦИЮ и зарегистрировать там ваши глобальные переменные.

Для ведения журналов я предпочитаю предоставлять одноэлементный класс или класс, который предоставляет некоторые статические методы для ведения журналов.

На самом деле, я бы использовал одну из существующих платформ журналирования.

0 голосов
/ 09 апреля 2010

Еще одно возможное решение - иметь класс Log, который инкапсулирует процедуру регистрации / хранимой процедуры. Таким образом, вы можете просто создать new Log(); в любое время, когда вам это нужно, без использования синглтона.

Это мое предпочтительное решение, потому что единственная зависимость, которую вам нужно внедрить, - это база данных, если вы регистрируетесь через базу данных. Если вы используете файлы потенциально, вам не нужно вводить какие-либо зависимости. Вы также можете полностью исключить глобальную или статическую запись в класс / функцию.

0 голосов
/ 17 сентября 2008

Я решил эту проблему в прошлом, добавив экземпляр класса ведения журнала в базовый класс (ы) (или интерфейс, если это поддерживает язык) для классов, которым требуется доступ к ведению журнала. Когда вы что-то регистрируете, регистратор просматривает текущий стек вызовов и определяет из него вызывающий код, устанавливая правильные метаданные об операторе журналирования (метод источника, строка кода, если она доступна, класс, который регистрируется и т. Д.). Таким образом, минимальный В ряде классов есть регистраторы, и регистраторы не нуждаются в специальной настройке с метаданными, которые могут быть определены автоматически.

Это добавляет значительных накладных расходов, так что это не обязательно разумный выбор для ведения журналов производства, но аспекты логгера могут быть условно отключены, если вы спроектируете его таким образом.

Реально я большую часть времени использую регистрацию в общем достоянии (я много работаю в Java), но есть некоторые аспекты дизайна, которые я описал выше, которые я считаю полезными. Преимущества наличия надежной системы ведения журналов, которую кто-то уже потратил на отладку значительного времени, перевесили необходимость того, что можно считать более чистым дизайном (это, очевидно, субъективно, особенно с учетом отсутствия подробностей в этом посте).

У меня были проблемы со статическими регистраторами, вызывающие проблемы с памятью permgen (по крайней мере, я думаю, * в этом проблема ), поэтому я, вероятно, скоро вернусь к регистраторам.

0 голосов
/ 17 сентября 2008

Возможно, вставка логирования прозрачным способом скорее будет относиться к идиоме аспектно-ориентированного программирования. Но мы говорим о дизайне ОО здесь ...

Шаблон Singleton может быть наиболее полезным, на мой взгляд: вы можете получить доступ к службе ведения журнала из любого контекста через открытый статический метод класса LoggingService.

Хотя это может показаться очень похожим на глобальную переменную, это не так: она должным образом инкапсулирована в одноэлементном классе, и не каждый имеет к ней доступ. Это позволяет вам изменить способ ведения журналов даже во время выполнения, но защищает работу журналирования от кода «vilain».

В системе, над которой я работаю, мы создаем несколько «синглетонов» ведения журнала, чтобы можно было различать сообщения от разных подсистем. Они могут быть включены / выключены во время выполнения, фильтры могут быть определены, запись в файл возможна ... Вы называете это.

0 голосов
/ 17 сентября 2008

используется статический класс, он имеет наименьшие накладные расходы и доступен для всех типов проектов в пределах простой ссылки на сборку

обратите внимание, что синглтон эквивалентен, но включает в себя ненужное распределение

если вы используете несколько доменов приложений, учтите, что вам может понадобиться прокси-объект для доступа к статическому классу из доменов, отличных от основного

также, если у вас несколько потоков, вам может потребоваться заблокировать функции журналирования, чтобы избежать чересстрочного вывода

ИМХО только одной регистрации недостаточно, поэтому я написал CALM

удачи!

0 голосов
/ 17 сентября 2008

(ИМХО) то, как происходит «ведение журнала», не является частью дизайна вашего решения, это скорее часть любой среды, в которой вы работаете - например, Система и Календарь в Java.

Ваше «хорошее» решение - это такое решение, которое настолько слабо связано с какой-либо конкретной реализацией ведения журнала, насколько это возможно, поэтому подумайте об интерфейсах. Я бы проверил след здесь для примера того, как Sun взялась за него, поскольку они, вероятно, придумали довольно хороший дизайн и выложили все это, чтобы вы могли поучиться!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...