Предотвращение нескольких операторов переключения - PullRequest
0 голосов
/ 30 января 2020

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

  • Создание заказа
  • Обновление заказа
  • Покупка товара
  • Статус получения
  • et c ..

Этот метод возвращает один объект 'Event', в котором объединена вся необходимая информация журнала, например, LogLevel, Message, UserId и другие, и записывает это в базу данных. .

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

  1. ActionName - На каком этапе моего процесса происходит событие журнала, называемое
  2. ActionOrigin - это записанное событие журнала из моей интерфейсной или серверной системы ...

Оно также основано на объекте, где находятся необходимые значения журнала, например, идентификатор заказа , предоставляются.

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

Первое, что пришло в мой Разум создавал оператор switch и создавал сообщения, основываясь на правильном регистре. Но это объединило бы 2 утверждения переключателя и быстро начало выглядеть как беспорядок.

Я провел некоторое исследование и нашел образец стратегии. Я не совсем уверен, может ли это помочь мне? Есть еще идеи или примеры?

Ответы [ 3 ]

2 голосов
/ 30 января 2020

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

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

Вот простой пример. В этом случае регистратор принимает любой тип LoggableEvent и вызывает его метод Serialize(), чтобы выяснить, как он добавляется в общий журнал. Само событие отвечает за знание того, как сериализовать себя.

abstract class LoggableEventBase
{
    public string ActionName { get; }

    public string ActionOrigin { get; }

    public LoggableEventBase(string actionName, string actionOrigin)
    {
        ActionName = actionName;
        ActionOrigin = actionOrigin;
    }

    public virtual string Serialize()
    {
        return string.Format("{0} {1}", ActionName, ActionOrigin);
    }
}

class CreateOrderEvent : LoggableEventBase
{
    protected readonly List<Item> _items;
    protected readonly int _orderId;

    public CreateOrderEvent(string origin, int orderID, List<Item> items) : base("CreateOrder", origin)
    {
        _orderId = orderID;
        _items = items;
    }

    public override string Serialize()
    {
        return base.Serialize() + string.Format(" {0} {1}", _orderId, string.Join(",", _items.Select(item => item.SKU)));
    }
}

Теперь фактические логи логирования c довольно просты - никаких операторов switch или чего-либо еще, что должно знать, что это за событие :

class Logger : ILogger
{
    public void Log(LoggableEventBase eventToLog)
    {
        Write(eventToLog.Serialize());
    }

    protected virtual void Write(string message)
    {
        //Write the message to a log file
    }
}

Чтобы добавить дополнительные типы событий, вам просто нужно определить новый класс (и переопределить Serialize()). Вам никогда не придется go назад и изменять класс Logger. Это более соответствует принципу Open-Closed , чем ваше существующее решение.

1 голос
/ 30 января 2020

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

Пример (я сделаю все возможное, чтобы написать C#, пожалуйста, исправьте любые ошибки или недостатки):

class Logger {
    // If you want personalized messages for different actions or origins, define their template constants and create different methods for building them. 
    public const string ORDER_PROGRESS_MSG_TMPL = "Action:{0}, Origin:{1}, OrderId:{3}";
    void log_order_progress(string actionName, sting actionOrigin, string orderId){
        Console.WriteLine(
            ORDER_PROGRESS_MSG_TMPL, actionName, actionOrigin, orderId
        );
    }
}

Заказ

class Order {
    ...
    void create(int orederId){
        Logger.log_order_progress(ActionEnum.CREATING, OriginEnum.BACK_END, orderId)
        // Do some stuff here to create order
        Logger.log_order_progress(ActionEnum.UPDATING, OriginEnum.BACK_END, orderId)
        // etc
    }
}

Это a способ сделать это, вы могли бы больше модульно, имея шаблоны в своем классе. Также вы можете создать (или лучше: использовать существующую структуру ведения журнала), чтобы дифференцировать уровень ведения журнала (отладка, информация, ошибка), как описано @Sandeep Sharma.

0 голосов
/ 30 января 2020

Вы можете создать несколько методов в своем классе Logger, каждый для определенного сценария c. Методы могут быть:

  • info () = для регистрации некоторой информации.
  • debug () = для отладки.
  • error () = для регистрации события ошибки.

Допустим, вы хотите зарегистрировать событие покупки предмета, и когда пользователь действительно совершает покупку, вы может передавать информацию методу logger.info (). Если вы столкнулись с ошибкой или не было выполнено определенное действие или условие, вы можете передать данные в метод error (), который будет регистрировать ошибку в вашем случае. Для сообщений: 1. Имя действия - Вы можете передать имя метода или путь маршрута, который был вызван действием пользователя. 2. Action Origin - укажите такие данные, как имя пользователя, полный путь, тип действия и т. Д. c. Вы также можете поддерживать такие поля, как 'timestamp' и некоторые 'unique-identifier' для лучшей регистрации событий.

...