Как добавить регистратор ошибок в класс - PullRequest
0 голосов
/ 14 октября 2010

Я хотел бы использовать универсальный обработчик сообщений об ошибках, чтобы я мог легко GetLastError и SetError для любого класса.Я придумал эту схему.Но у меня есть пара вопросов.Обратите внимание, что эта реализация только для тестирования.Но я хочу получить базовый дизайн правильно.

#include <iostream>
#include <stdarg.h>

class ErrorHandler
{
    public:
        virtual void SetError(const char* zFormat, ...)
        {
            va_list args;
            va_start (args, zFormat);
            vsnprintf (z_ErrorBuf, sz_MaxBufSize, zFormat, args);
            va_end (args);
        }

        const char* GetError() const
        {
            return z_ErrorBuf;
        }

        virtual ~ErrorHandler(){}

        explicit ErrorHandler(const size_t szMaxBufSize = 1024)
        {
            z_ErrorBuf = malloc(sizeof(char)*szMaxBufSize);
            sz_MaxBufSize = szMaxBufSize;
        }

        void ResizeBuffer(const size_t szMaxBufSize)
        {
            z_ErrorBuf = realloc(z_ErrorBuf, szMaxBufSize);
            sz_MaxBufSize = szMaxBufSize;
        }

    protected:
        char* z_ErrorBuf;
        size_t sz_MaxBufSize;
};

class MyClass;

//Worker can be just an interface if needed. So, can't use friend.
class Worker
{
    public:
        void Work(MyClass& oGod);
};

void Worker::Work(MyClass& oGod)
{
    //Work
    //OnError
    oGod.GetErrorHandler().SetError("Save me %s", "not");
}

class RecordingErrors
{
    public:
        const char* GetLastError() const
        {
            return oErrorHandler.GetError();
        }

        //GetErrorHandler is public
        ErrorHandler& GetErrorHandler()
        {
            return oErrorHandler;
        }

    private:
        ErrorHandler oErrorHandler;
};

class MyClass : public RecordingErrors
{
    public:
        bool GetThingsDone(Worker& me)
        {
            me.Work(*this);

            //on Error
            return false;
        }
};

int main()
{
    MyClass oL;
    Worker w;
    if(!oL.GetThingsDone(w))
    {
        std::cout << oL.GetLastError() << std::endl;
    }
}
  1. Могу ли я переопределить эту функцию в дочернем классе?virtual void SetError(const char* zFormat, ...).
  2. Могу ли я покончить с классом RecordingErrors?Я чувствую, что тогда MyClass придется унаследовать от ErrorHandler, что я не считаю хорошим.Я прав или нет?Это еще один вопрос о композиции по наследству.РЕДАКТИРОВАТЬ: я не имею в виду имя, но идея?
  3. Любые возможные сценарии, что этот подход потерпит неудачу?
  4. Есть ли лучший способ реализовать журнал ошибок?Слово здесь. Что это?)

1 Ответ

3 голосов
/ 14 октября 2010

Обработчик ошибок и регистратор - это два разных объекта. Обработчик ошибок решает, что делать с ошибками. Должны ли они быть немедленно отправлены в логгер, сохранены ли они в базах данных или просто сохранены в каком-то буфере, пока кто-нибудь не спросит.
Регистратор решает, как зарегистрировать данное сообщение. Должен ли он отображаться на консоли или сохраняться в файле на диске, в каком формате он должен отображаться.

Имейте в виду особенности регистратора.
1) Это должен быть независимый класс. Его поведение не должно зависеть от других классов.
2) Логгер наиболее предпочтительным должен быть синглтоном. Вам не нужно много объектов, плавающих вокруг, чтобы сделать то же самое. Но тогда у синглтон-классов есть свои головные боли, когда дело доходит до многопоточности. Так что я знаю, что это спорный вопрос.
3) Он должен и должен иметь возможности асинхронного ведения журнала. Это означает реализацию производителя и потребителя. (Ведение журнала является операцией ввода-вывода и, следовательно, дорогостоящей по своей природе. Вы не хотите, чтобы ваша основная обработка зависала от этого. Но, опять же, вы, возможно, не захотите использовать потоки для удаления этой операции.)

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

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