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. Я про инжинерность. Обработка ошибок - это один из признаков инжинерности, когда программа сохраняет свой понятийный домен (язык, на котором описывается, что делает программа) во всех ситуациях.

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

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

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

[personal profile] kondybas 2025-01-28 07:30 am (UTC)(link)
Регекспі появляются, потому что императивно удобно программировать далеко не все. Иногда и декларативно приходится, или функционально, а то и FSA прикрутить.

И, собсно, не вижу причин делать дихотомию "программирование - регекспі". Регексп, вопреки бітующему мнению - єто НЕ паттерн :) Єто код, транслируемій в FSA, которій віполняет сравнение с неким паттерном. И в єтом коде есть макросі, бекреференсі, условніе операторі и прочее разное, что слабо укладівается в понятие паттерна. Регекспі - єто еще одна из разновидностей программизьма.
Edited 2025-01-28 09:35 (UTC)
juan_gandhi: (Default)

[personal profile] juan_gandhi 2025-01-28 11:43 am (UTC)(link)
О да. Вчера зафайлил в джиру баг. Одному сервису посылаешь запрос с отсутствующим джейсоном, а он такой в ответ: HTTP 500. ("да, мы охуели")

[personal profile] dedekha 2025-01-28 01:38 pm (UTC)(link)
Мне кажется что все деньги больше $100 тыс платят исключительно за обслуживание sad and bad paths. Happy path вам и зa 50 тыс сварганят (цифры где-то 10 летней давности).

[personal profile] permeakra 2025-01-29 04:04 pm (UTC)(link)
Скажи пожалуйста, как в домене "почтовый клиент" должна отражаться для клиента ситуация "отвалился доступ к примонтированной по сети файловой системе с sqlite базой с письмами" и как до этого должен додуматься разработчик клиента.
Edited 2025-01-29 16:04 (UTC)

[personal profile] permeakra 2025-01-30 09:56 am (UTC)(link)
>Сервер
Причем тут сервер, когда я спросил о почтовом клиенте?

Вот есть клиент, типа Thunderbird, который хранит скачанные письма и все прочие данные пользователя в локальной sqlite базе. Так сложилось, что в конкретной системе раздел с sqlite базой лежит на разделе, смонтированном по сети. Этот раздел отвалился. Что программа должна сказать пользователю? Конкретное сообщение. Причем все слова про раздел, базу, настройки - говорить нельзя, потому что это не входит в понятийный домен почтового клиента.

>Примерно так же, как и любая другая ситуация с нехваткой ресурса.

1) Пользователь почтовой программы не знает таких слов.
2) Здесь нет проблемы нехватки ресурса.

[personal profile] permeakra 2025-01-30 10:41 am (UTC)(link)
>Проблема недоступности nfs (или что за шайтан технология со стороны сервера - хоть лямбды поверх S3) - это всё "недоступность почтового сервера".

Ты путаешь почтовый сервер и сервер, раздающий файловую систему. В данном примере это РАЗНЫЕ машины. Почтовый сервер - это, например, машина где-то в облаке гугла, клиент обращается к ней по сетевому протоколу IMAP. Сервер с файловой системой - это машина, например, в офисе организации, о сущестсвовании которой почтовый клиент вообще не знает - он обращается к локальной с его т.з. файловой системе (для простоты предположим, что по сети смонтирован /home). Почтовый клиент скачивает письма с почтового сервера и сохраняет в своей локальной базе, которая в данном случае лежит на смонтированном по сети разделе /home в директории, например, ~/.thunderbird. Что должен сказать пользователю клиент, если при попытке прочитать письмо из локальной базы он получает ошибку EHOSTDOWN ?

И, кстати, твои затруднения в понимании - это показатель того, что в общем случае желаемое тобой невозможно.
Edited 2025-01-30 10:43 (UTC)

[personal profile] permeakra 2025-01-30 11:30 am (UTC)(link)
>А какая разница, где там ошибка?

В том, кто виноват и куда идти в попытке её пофиксить. Почтовый сервер в данном случае не виноват.

>Про нюансы я написал.

Не про те.


>Вот как проблему решает well-engineered браузер.

Современные браузеры ни в каком месте не well-engineered. Нельзя сделать что-то well-engineered, когда у тебя не только проект, но еще и стандарт делается по agile.

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

[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)
Ты это сказал на двацать каком-то уровне вложенности и сразу же забыл. Я-то это запомнил, почему и спросил - зачем ты переупрощаешь до уровня очевидной глупости.
yurikhan: (Default)

[personal profile] yurikhan 2025-01-31 09:29 am (UTC)(link)

в конкретной системе раздел с sqlite базой лежит на разделе, смонтированном по сети. Этот раздел отвалился. Что программа должна сказать пользователю?

Примерно то же, что она говорит при ошибке нахождения сектора дискеты из-за частичного размагничивания сервометок. Critical error reading drive A: — Retry/Abort/Ignore/Fail?

yurikhan: (Default)

[personal profile] yurikhan 2025-01-31 10:29 am (UTC)(link)

Я слышал про решения, когда поверх большого, но медленного HDD ставится маленький SSD-кэш. Возможно, аналогично можно ставить маленький локальный надёжный диск поверх большой ненадёжной сети.