Страницы

Поиск по вопросам

вторник, 30 октября 2018 г.

Поиск удачного решения по обработке ошибок

В разрабатываемом приложении часть классов спроектированы таким образом, что статус выполнения функции либо возвращается, либо сохраняется в соответствующем поле. Эти классы связаны с обработкой файлов, xml-документов и т.п. После выполнения каждой операции приходится проверять статус выполнения, например:
if (xmlParser.hasError()) { log(...); return <ошибка выполнения>; // завершаем выполнение текущей функции, поскольку продолжать не имеет смысла. }
Таких проверок в теле функции может набежать довольно много. Собственно вопрос: есть ли возможность уменьшить код, направленный на проверку статуса выполнения, и сосредоточиться на непосредственно логике самой функции. Возможно, лучше будет использовать тогда исключения? Либо текущее решение вполне жизнеспособно?


Ответ

Используйте исключения, они специально придуманы для этой цели.
Либо, при возникновении ошибки переводите xmlParser в состояние, когда он ничего не делает, и приверяйте ошибку один раз после всех операций с ним, как это сделано в стандартных потоках ввода-вывода:
void f(std::istream& s, int& a, int& b) { s >> a >> b; bool eof = !s; ...
Текущий подход к проверке ошибок плох тем, что он никак не поощряет и не контролирует то, что все ошибки будут проверены. Очень легко не написать этот if (xmlParser.hasError()), или например по ошибке написать if (!xmlParser.hasError())
Если использовать возврат ошибок, то лучше возвращать ошибку из самой функции, которая выполняет действие приводящее к ошибке:
void parse(error_code& ec) { if (xmlParser.parse(ec)) return; }
либо можно использовать монады (в т.ч. optional), что является более современным подходом, но к сожалению пока мало библиотек реализующих типы Result, std::expected и т.п.
Result result = xmlParser.parse(); if (!result) return result.error();

Комментариев нет:

Отправить комментарий