Как стать автором
Обновить

10 Принципов отказоустойчивости (с примерами на Javascript)

Уровень сложностиСредний
Время на прочтение12 мин
Количество просмотров5K
Всего голосов 4: ↑0 и ↓4-4
Комментарии14

Комментарии 14

ЗакрепленныеЗакреплённые комментарии

Привет, пользователи Habr. Спасибо за критику. Я её учел и отредактировал публикацию: добавил больше примеров и уточнений и постарался сделать спорные моменты более однозначными и прозрачными

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

let data; try

{

data = this.getSomeData(); } catch(error)

{ data = this.getErrorData();

console.error(error); }

this.doSomething(data);

А ещё паттерн:

bool someFunc(Param * param)

{

if (nullptr == param) return false;

....

}

И ещё хорошо, если ошибку залогируют.

Возможно, если хорошо прищуриться, это может в каких-то редких случаях иметь смысл при разработке фронтенда на JS.

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

Самый разумный подход: это при обнаружении ошибки, которую вы не знаете как можно обработать - немедленно паниковать с сохранением достаточной информации (где и почему) запаниковало.

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

Включите в ваш набор инструментов аналог макроса assert (я предпочитаю комбинацию verify()/halt())который никогда не отключается, в том числе в релизной сборке.

Активно применяйте его для проверки входных данных, выходных данных, возвращаемых значений и промежуточных условий/утверждений.

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

Вы можете корректно и разумно обработать эти события? Обрабатывайте. Не можете или вам лень вот прямо сейчас писать код обработки? Ставьте verify().

Но вот если вам в функцию передали nullptr, и в спецификации функции не указано, что "вот этот параметр можно поставить null и поведение будет следующим ..." - паникуйте. Никогда, ни при каких условиях не надо пытаться "маскировать" ошибку.

console.error или даже весь поток process.stderr.write можно перехватить, разобрать и вывести на экраны. Вероятно, автор сохранил интригу для следующей статьи. Один retry чего стоит =)

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

let data; try

{

data = this.getSomeData(); } catch(error)

{ data = this.getErrorData();

console.error(error); }

this.doSomething(data);

Я с тобой согласен. Ме стоило добавить уточнение, когда такой паттерн действительно уместен. Например, при рискованных операциях на стороне браузера, которые могут выбросить ошибку — это браузерные API, которые пользователь может отключить, или ситуации с нехваткой времени или ресурсов, из-за чего вызов может завершиться с ошибкой (например, доступ к LocalStorage, запрос разрешения на камеру или микрофон). В таких случаях обработка через try/catch с запасным вариантом данных оправдана.
Я не вкладывал смысл в то, что его нужно использовать везде и всегда. Но там, где ошибка может возникнуть, но не может быть исправлена - он уместен (тот же пример с нехваткой памяти на стороне пользователя).

Самый разумный подход: это при обнаружении ошибки, которую вы не знаете как можно обработать - немедленно паниковать с сохранением достаточной информации (где и почему) запаниковало.

Подход с немедленной паникой при любой непредвиденной ошибке, безусловно, разумен. Но это совсем не про отказоустойчивость.
Мне кажется, что ты больше о стремлении писать код, о том как не допускать ошибки (допускать меньше). Это правильная цель — и я с ней полностью согласен. Но в статье я поднимаю немного другую тему: как сделать так, чтобы даже ошибки возникли система продолжала работать насколько это возможно, а пользователь не сталкивался с крашем, потерей данных или “горящим” интерфейсом и надеждой, что его починят как можно скорее. Идеального кода не бывает, а отказоустойчивость — это как раз про то, что делать, когда идеал дал трещину.

Твой подход зрелый. Но многое зависит от приоритетов в разработке
Подход “assert и немедленный краш” во главу угла ставит целостность системы и прозрачность ошибок
Отказоустойчивый подход во главу угла ставит пользовательский опыт и доступность функционала несмотря на ошибки
(И еще много-много разных подходов)

Универсального и правильного подхода нет

Вы можете корректно и разумно обработать эти события? Обрабатывайте

Это очень точное и правильное уточнение. В статье мне действительно стоило чётко обозначить это

Спасибо за критику — она по делу, уважительная и действительно мне помогает
Очень ценю такие замечания.

Но в статье я поднимаю немного другую тему: как сделать так, чтобы даже ошибки возникли система продолжала работать насколько это возможно, а пользователь не сталкивался с крашем, потерей данных или “горящим” интерфейсом и надеждой, что его починят как можно скорее. Идеального кода не бывает, а отказоустойчивость — это как раз про то, что делать, когда идеал дал трещину.

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

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

Например, разработчик текстового редактора (уровня OpenOffice/MS Word), если попробует "обходить" и "восстанавливаться" после проблем нехватки памяти - запросто может потерять часть документа. Или, например, вставленные рисунки. После чего пользователь этот документ сохраняет - и привет.

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

А вот если вы начали большую операцию, выделяете память мелкими кусочками по-объектно, и вот где-то в середине у вас обломалось выделение очередного мелкого объекта - вам кирдык.

Вы не сможете ни сообщить об этом пользователю, ни откатить операцию - так как памяти у вас вообще нет. А на сообщения и откат - сюрприз - нужна память.

Я такое проходил. Допустил утечку памяти, причём, малыми кусочками. За месяц непрерывной работы, память тупо кончилась вся. И дальше, так как программа именно была ориентирована на "продолжение работы" - начала терять функции интерфейса. Пункты из меню. Элементы интерфейса.

Что выглядело совершенным безумием для пользователя. Причём если бы она просто грохнулась - пользователь просто запустил бы её заново.

Понимаю твою позицию, но, кажется, ты говоришь про неудачную попытку «спрятать» ошибку - я же пишу о том, как грамотно её обработать, чтобы не навредить ещё больше.

Пример с текстовым редактором - отличный. Но он как раз в пользу отказоустойчивости: при нехватке памяти правильнее не крашиться, а остановить операцию, сохранить то, что уже есть, и честно сообщить об ошибке пользователю (например, показав всплывающее уведомление). Это не «маскировка», а забота о пользователе.

Отказоустойчивость - не про «продолжать несмотря ни на что» (даже ценой утечек), а про то, чтобы не усугубить ситуацию, когда что-то пошло не так

Надеюсь мне удалось лучше передать смысл этой публикации

К сожалению, сейчас даже самые топовые и популярные вебсайты плевать хотели с высокой колокольни. К примеру Ютуб. Тормозит - это проблемы твоего компа и скорости интернета. Нет, не мегатонны скачиваемого JS и браузера, который жрёт как Киберпанк на средних и плевать, что это всего лишь сайт с превьюшками. Не работает кнопка «три точки» и не показывает уведомления при нажатии на колокольчик? Не присылает уведомление о начале стрима, хотя ты прожимал просьбу? Сбрасывает твои настройки? Поиск бесполезен из-за ленивой загрузки? Бесит новый интерфейс? - да им насрать! Многие проблемы существуют не первый год и их никто не правит, даже после нескольких смен политик/дизайнов/интерфейсов. Так и живём...

Справедливое название статьи "За все хорошее против всего плохого". К сожалению, примерами, как было обещано, даже и не пахнет. Автор, попробуй другой промпт.

другой промпт

ок гугл: как застрелить ногу?

Ты прав, примеров и впрям мало, стоило добавить больше. В названии я хотел сделать акцент на том, что примеры будут именно на JavaScript, а не на их количество. Учту это на будущее и постараюсь делать материал более насыщенным

Даже не знаю пройдет ли этот комментарий тест Тьюринга :)

Расстраивает, что такой стиль общения присваивают ИИ. Забывая, что тот не изобрел его, а лишь подражает. Люди умели так писать и выражаться задолго до него. Словно мне следует, так же как и ты, в конце ставить “:)”, чтобы это делало меня “живее”. Я лишь стараюсь не впадать в негатив, сохранять уважительный тон и честно признавать ошибки. Это куда лучше, чем отвечать той же монетой

К тому же ИИ уже давно умеет общаться в разных стилях — в том числе с иронией, добавляя ":)" в конце.

Честно сказать, ничего не могу сказать...
Да, вы совершенно правы. Я был рад прочитать ответ на мой комментарий. Пожалуйста, пишите ещё, я всегда рад ответить!

Я так выражаюсь лишь из-за того, что переживаю. Это моя первая публикация за всю карьеру, и я боюсь оступиться, чтобы не получить “расстрела” от таких, как ты. Такой стиль дает мне чувствовать себя как за "броней". Даже если эта броня мнимая. В будущем мне будет легче выражаться проще

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

Привет, пользователи Habr. Спасибо за критику. Я её учел и отредактировал публикацию: добавил больше примеров и уточнений и постарался сделать спорные моменты более однозначными и прозрачными

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации