понедельник, 16 августа 2021 г.

[prog.thoughts] И снова на тему исключений. На этот раз с подачи Вальтера Брайта

На HackerNews появился и обсуждается плач Ярославны Вальтера Брайта на тему исключений. Он там перечислил с десяток причин своей нелюбви к исключениям. Желающие могут ознакомиться сами.

Я же выделю два пункта из списка Брайта:

5. it is hard to write exception-safe code

6. very few understand how to write exception-safe code

Уже многократно говорил в своем блоге, но вынужден повторить еще раз: меры по написанию надежного и устойчивого кода в присутствии исключений точно такие же, как и при использовании кодов возврата.

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

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

И, как показывает практика, у многих программистов (включая меня самого) не очень хорошо с предсказанием последствий такого преждевременного выхода. В этом-то как раз и есть корень зла. Мы, люди, не особо хорошо справляемся с перебором возможных вариантов "а что, если здесь случится какая-то херня?" Это и есть основополагающая штука. А не throw, return или goto err.

У хейтеров исключений существует иллюзия о том, что если они будут писать код в стиле:

r = do_something();
if(-1 == r) {
  revert_changes();
  return -1;
}

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

По моим наблюдениям это, мягко говоря, не так.

Во-первых, большинство программистов очень плохо справляется с написанием кода, в котором требуется скрупулезное внимание к деталям. Плюс написанный в таком стиле код запросто может стать слишком объемным. Пример можно увидеть вот в этом моем посте шестилетней давности. А объем кода -- это дополнительные трудозатраты при сопровождении. Потребовалось добавить какую-то операцию, требующую отката в случае ошибки, и... И нужно вручную просматривать и модифицировать все места, в которых этот откат может потребоваться.

Да, я знаю, что идиома goto err сильно облегчает жизнь. Но это именно что средство для уменьшения боли, а не ее устранения.

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

Так что не буду спорить со всем перечнем претензий Брайта к исключениям, но вот эти два пункта -- это явно какая-то херня. При всем моем уважении к тов.Брайту.

3 комментария:

Сергей Скороходов комментирует...

Проблема не исключения. Проблема — бездумно бросаемые исключения, особенно если в обработчике нужны переменные из try-блока))))

Сергей Скороходов комментирует...

PS ненавижу тех, кто так делает!!!)))))

XX комментирует...

С использованием АТД "коды возврата" заиграют новыми красками и практически лишатся перечисленных недостатков.