вторник, 23 февраля 2010 г.

Класс-геренатор исключаний

Уже не малое время я программирую на С++, было пересмотрено масса кода, разнообразных библиотек и фреймворков. Соответственно пришлось повидать много вариантов реализации системы обработки ошибок: классическое возвращение кода ошибки, генерация разнообразных типов исключений, кидание исключения как строковый класс и так далее. Так же в процессе работы над своим проектом я искал наиболее удобный для себя способ генерации и обработки ошибок. Первоначально опробовал генерацию кода, оказалось несколько неудобно, далее использовал генерацию исключений. Как то, в очередной раз копаясь в stl обратил внимание на систему классов-исключений, которая в нём применялась, это и натолкнуло меня на идею, реализацией которой я уже не один год пользуюсь.
В stl используются классы-исключения, в которых находится текстовая строка с сообщением об ошибке. От базового класса наследуются специализированные классы, например: ошибка времени выполнения или ошибочный параметр.
Собственно система из stl мне не подошла, стиль кода отличается от того, что используется в движке. Был создан собственный класс исключение:
class TBaseException
{
protected:
wstring Mess;
public:
TBaseException() throw ();
TBaseException(const wstring &NewMess) throw ();
virtual ~TBaseException() throw ();

wstring GetMess() const;
};
Всё достаточно просто.
Далее, в процессе использования неудобно постоянно писать конструкции типа:
if(Name != L"Domochewsky"){
throw TBaseException(L"какое то сообщение, описывающее причину ошибки");
}
Запись не лаконичная, особенно если надо проверить большое количество значений, и был придуман и реализован класс-генератор исключений:
class TExceptionGenerator
{
protected:
wstring MessPrefix;
public:
TExceptionGenerator();
TExceptionGenerator(const wstring &Prifix);
virtual ~TExceptionGenerator();

void operator() (const TBaseException &Ex) const;
void Run (const TBaseException &Ex) const;

void operator() (const wstring &Mess,const bool &SetPref=true) const;
void Run (const wstring &Mess,const bool &SetPref=true) const;

void operator() ( const bool &Check,const wstring &Mess,
const bool &SetPref=true) const;

void Run ( const bool &Check,const wstring &Mess,
const bool &SetPref=true) const;

void SetPrefix(const wstring &Val);
};

Суть его работы достаточно проста, так как любое логическое условие (A>B, Pointer==NULL и так далее) возвращает true или false, то у класса были сделаны методы, которые кидают сообщение, если условие ложное. Вышло некоторое подобие asset-а.
Далее префикс используется для записи места возникновения ошибки, например это тип класса, который использует генератор. Так же для тех случаев, когда условие каким то образом не выполняется, была сделана возможность просто кинуть исключение.
Примеры использования:
1.
HINSTANCE Instance = GetModuleHandle(NULL);
Exception(Instance!=NULL,L"in CreateWinWindow() cant't get Instance");
2.
Exception(ElemEventActions!=NULL,L"in InitQueue(...) ElemEventActions is NULL");
3.
Exception(L"in ToCreateAction(...) Action is NULL");

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