Утверждение, исключение, ошибка во время выполнения или неопределенное поведение?
Я работаю над библиотекой конечных автоматов с этими публичными методами:
template <typename STATE_T>
void add_state(); // allocate STATE_T on heap - STATE_T must derive from state
template <typename FROM_STATE_T, typename TO_STATE_T>
void link_state(std::function<bool()> cond, unsigned int priority);
// search for base state pointer that can be dynamically caste d to STATE_T* type, set this state as the beginning state
template <typename STATE_T>
void begin_state();
void execute();
//STATE_T must be a user defined state class that inherits from the base state class.
Я выбрал реализацию во время выполнения, а не во время компиляции, потому что интерфейс был бы более сложным при использовании переменных параметров шаблона для состояний. Однако есть ограничения, которые я хочу применить, чтобы программист не вносил ошибок при реализации своего конечного автомата.
Вот ограничения, которые я хочу применить:
- Невозможно добавить повторяющиеся состояния (т.е. добавление двух одинаковых производных типов)
- Невозможно связать несуществующие состояния (например, тип состояния, отсутствующий в списке состояний fsm)
- Штаты должны иметь точку входа / быть достижимой
- Начальное и конечное состояние должно существовать
- execute не может быть запущен несколько раз одновременно
Утверждение прерывает программу и четко придерживается этих ограничений, но является ли это правильным выбором?
Возможно нарушение 1,2,3, и fsm по-прежнему находится в допустимом состоянии (просто ничего не делать), но мне не нравится идея неявной обработки их, потому что она вводит ложное чувство безопасности, скрывая ошибки программиста.
Если я выбрасываю исключения для 1,2,3, и программист их перехватывает, тогда fsm все еще может находиться в допустимом состоянии, позволяя запустить некорректно сформированный fsm.
5 это то, что не должно быть сделано. я должен обработать это, или оставить это как UB?
Какой механизм будет наиболее подходящим для этих ограничений?
1 ответ
Это довольно типичная проблема обработки ошибок. Ответ обычно зависит от затрат. Какова стоимость проблемы, оставшейся незамеченной? Какова стоимость программы, которая прерывается из-за исключения?
В большинстве случаев стоимость сбоя программы не так велика. Пользователь просто перезапустит его. В этом случае вы должны пойти на необработанное исключение. Таким образом, вы быстро заметите ошибки, исправите их и в итоге получите лучшую программу.
Существует гибридный подход: в сборке DEBUG обработайте ошибку с помощью окна сообщения "Ошибка подтверждения" (обычно это делается с помощью макроса ASSERT()), но в сборке выпуска обработайте ошибку без вывода сообщений. Это, однако, позволяет проблеме оставаться незамеченной на клиентских компьютерах, часто вызывая другие ошибки, которые трудно найти.
Наконец, о ваших заботах, что программист может обработать исключение: это не то, о чем вы должны думать. Вы указали на фатальную ошибку, если программист игнорирует ее, это его вина.