amarao: (Default)
amarao ([personal profile] amarao) wrote2025-01-28 08:44 am

Инжинерность

Я сейчас случайно увидел, что делает powershell, если указать несуществующую команду.

Это выглядит неприятно. Но, кроме "неприятно", что ещё можно сказать? Оно не хорошо спланировано.

Один из принципов инженерности, это правильная обработка sad path (vs bad path).

Сама идея: в программе есть три пути: happy path (что сказали, то сделали, получили результат), sad path (поведение при невозможности получить результат) и bad path (то, что случается, если результат нельзя получить, но никто не предусмотрел что делать).

Десятилетиями операционные системы и языки программирования давали свою интерпретацию "что делать если всё плохо". Первые версии просто игнорировали "всё плохо" (вот этот мем немного утрирует, но справа показано полное отсутствие обработки ошибок). В реальности, полное отсутствие обработки ошибок, это UB (undefined behavior) и процессор продолжает исполнять что-то, что уже не оригинальная программа. На практике это всегда заканчивается зависанием.

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

Сверху добавили трейсы и т.д.

Это работа по превращению bad path в sad path с точки зрения ОС и языка программирования (точнее, среды исполнения, которую предоставляет компилятор).

Однако, это не отменяет необходимости делать такую же работу со стороны программиста. Программа на питоне, которая выдаёт трейс "не могу открыть файл" (вместо сообщения об ошибке "не могу открыть файл") - это пример bad path (который sad path с точки зрения питона). Полагаться на обработчик ошибок уровнем ниже - это неинжинерно.

В тот момент, когда программа отдаёт ошибку "наверх" (трейс, exception), она отказывается от своего домена и проблема перефомулируется на языке уровнем ниже.

Не "input file not found" (программа знает, что это input file), а "file not found exception at line xxx". В этот момент язык программирования не знает, является ли ошибка ожидаемой или нет, ошибка программы это (например, опечатка в имени файла) или ошибка отсутствия файла как параметра.

Язык программирования не знает, bad path это для программы или sad path. Отсутствие обработки ошибки, стирает её смысл.

К чему я это всё? На самом деле я не про sad/bad path. Я про инжинерность. Обработка ошибок - это один из признаков инжинерности, когда программа сохраняет свой понятийный домен (язык, на котором описывается, что делает программа) во всех ситуациях.

Сохранение семантического домена - это сохранение инварианта. Если программа А работает, то она всегда взаимодействует в рамках этого домена.

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

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

[personal profile] permeakra 2025-01-30 12:31 pm (UTC)(link)
Вот тут у нас глубокое несогласие. При передаче ошибки вверх по стеку вызовов не должно происходить потери информации. Даже если это означает протекание подлежащих абстракций. Да, ошибку можно и нужно аннотировать смысловым контекстом на всех уровнях стека вызовов, и неплохо бы дать комментарий для человека не в теме, но отбрасывать информацию снизу - нельзя.

[personal profile] permeakra 2025-01-30 01:04 pm (UTC)(link)
В данном случае стек-трейс должен быть где-то сохранен с возможностью обращения по ID, после чего распилен на части, которые будут отправлены разным адресатам согласно зоне ответственности. Очень грубо
- простой rejected - подошедшему клиенту.
- "сервер вернул ошибку при обработке транзакции" + описание транзакции - оператору терминала
- детали ошибки - администратору терминала
- Детальные отчет об ошибке супервизора базы + железячной ошибке - администратору базы данных.

Можно обсуждать что и кому показывать, но потери информации быть не должно. В идеале. На практике, понятно, возможны варианты, когда приходится скрипя зубами что-то обрезать.
Edited 2025-01-30 13:06 (UTC)

[personal profile] permeakra 2025-01-30 01:50 pm (UTC)(link)
*хмыкнув* К моему большому счастью, нехватка ресурсов на обработку ошибок - это не про те случаи, с которыми я имею дело. Но если ты все это понимаешь, то зачем переупрощаешь до уровня "пороть фигню"?

[personal profile] permeakra 2025-01-30 02:16 pm (UTC)(link)
Не нет, а да. То, что ты описываешь, это не повод никогда не отдавать трейс. Это причина делать инфраструктуру по отдаче трейсов настраиваемой, а то и самонастраиваемой. Это немного не то же самое, что не отдавать трейс вообще.

[personal profile] permeakra 2025-01-30 02:22 pm (UTC)(link)
Ты это сказал на двацать каком-то уровне вложенности и сразу же забыл. Я-то это запомнил, почему и спросил - зачем ты переупрощаешь до уровня очевидной глупости.