vitus_wagner: My photo 2005 (Default)
vitus_wagner ([personal profile] vitus_wagner) wrote2017-03-15 09:37 am

Semantic locality

http://esr.ibiblio.org/?p=7421

Раймонд умный пост написал по поводу концепций, которые лежат под Unix way. Я эту мысль про семантическую локальность три дня думать буду.

[identity profile] amarao-san.livejournal.com 2017-03-16 11:08 am (UTC)(link)
Я давно про это думал. Удивительно или нет, но мне кажется, что единственное решение тут - это монады. Мы передаём на вход утилиты, ожидающей Just data, вывод утилиты, выдающей Maybe Data, и получаем ошибку прям от шелла со словами, который говорит "нельзя". Мы ставим между ними в пайп, конвертор, который знает, что делать когда дата не "Just", и у нас всё работает точно. Наверное, под нужды шелла можно написать и более выразительные монады.

[personal profile] anonim_legion 2017-03-16 07:23 pm (UTC)(link)
От слова "монада" перекосит тех, кто писал (и работает с) bash. Если у них уж скобки в if должны непременно отделяться пробелами, то какие уж тут монады...

На этом месте мне вспомнился чудовищных размеров флейм с КЫВТа, где люди (в том числе те, кто компиляторы пишут, а не энтерпрайз какой) спорили о сравнительном удобстве и производительности между передачей кодов ошибок, как в Golang и исключениями, как много где. В теории, исключения лучше, если они реализованы правильно, и особенно они хороши в случае вызовов с в 40 уровнями вложенности в стеке, когда программист попросту устанет передавать ошибку наверх руками.

В типичном же unixway вряд ли можно встретить цепочку, где вызывалось бы больше 5 утилит. Вдобавок, нет никакого механизма "исключений", которые летали бы между процессами (и слава богу, наверное).

Чего нет в типичных пайпах - так это общепринятых границ сообщений. Даже для потоковых данных может появиться смысл в передаче данных некими кусками, chunk'ами. В виндовых named pipes есть механизм передачи отдельных сообщений, в юниксах же, насколько мне известно, подобное есть только в d-bus. Самостоятельно сделать разбивку на сообщения несложно, но - каждый раз это все равно нужно делать, и всякий будет делать это по-своему.
slobin: (Default)

[personal profile] slobin 2017-03-17 09:05 am (UTC)(link)
Чего-то задумался над мировоззренческим вопросом, что мешает плохому программисту. Ну, в смысле, по сравнению с танцором.

... Наше будущее лучезарно как никогда ...

livelight: (Default)

[personal profile] livelight 2017-03-17 01:21 pm (UTC)(link)
Стек-трейсы придуманы для программистов команды поддержки и исходных разработчиков. Тех, кто показывает стек-трейс конечному пользователю без особой просьбы с его стороны, надо больно бить по рукам. Тех, кто сообщение для показывания пользователю выбирает от балды, - тоже.
livelight: (Default)

[personal profile] livelight 2017-03-17 08:41 pm (UTC)(link)
У нормального исключения есть внятный текст исходной ошибки для любого пользователя, тип исключения для продвинутого пользователя и стек-трейс для баг-репортов. Самые умные могут текст (например: "Connection to 10.11.12.13:1415 refused") и другие известные им поля исходного исключения преобразовывать в высокоуровневую ошибку для пользователя же (например: "Cannot connect to backend server"), оставляя опять же для баг-репортов всю иерархию исключений.
А вот криворукие программисты могут и такое делать, как выше сказано, да.

[personal profile] inkelyad 2017-03-18 08:14 am (UTC)(link)
Я так понял, проблема в том, что если из конструкции вида
foo[bar(..)]
нам прилетает какой-нибудь IndexOutOfBound, из за того, что внутри bar действительно ошибка есть(алгоритм неправильно написали), то мы не можем ничего разумного в текст написать, т.к. мы про этот факт не знаем и можем думать, что сами из foo неправильный индекс достать пытаемся.
А текст исходной ошибки в данном случае явно ничего умного не скажет.
livelight: (Default)

[personal profile] livelight 2017-03-18 11:04 am (UTC)(link)
Такой IndexOutOfBound можно для конечного пользователя превратить только во что-нибудь типа "500 Internal server error" (со складыванием стек-трейса туда, где его сможет забрать команда поддержки). А вот вышеприведённые примеры с банкоматами говорят в том числе о том, что: 1) не проведена внятная валидация ввода; 2) после чего случившуюся в глубинах ошибку ещё и не привели во внятный вид. Как минимум два повода надавать по шее тем программистам.

[personal profile] inkelyad 2017-03-18 12:08 pm (UTC)(link)
Имеется в виду, что foo[] и может быть той самой валидацией.
Из логики "индекса в массиве не нашлось, значит, пользователь неправильное значение ввел. Ловим исключение и по нему ругаемся."
А тут внезапно индекс не нашелся где-то глубже по вызовам и поэтому все сломалось.
livelight: (Default)

[personal profile] livelight 2017-03-18 12:15 pm (UTC)(link)
По возрастающей степени дебилизма способы валидации такие:

1. Проверяем индекс ("индекса в массиве не нашлось, значит, пользователь неправильное значение ввел"), и если он плохой - внятно ругаемся
2. "Ловим исключение и по нему ругаемся" -- опять же внятно.
3. Прокидываем исключение выше, там пишут 500 Internal Server Error
4. Показываем пользователю кишки системы, а также кровь, распидарасило и стектрейс

[personal profile] inkelyad 2017-03-18 12:26 pm (UTC)(link)
2. "Ловим исключение и по нему ругаемся" -- опять же внятно.
try
... = foo[bar()]
catch IndexOutOfBound
ShowMessage("У вас нет такого номера счета")

Мы вот решили поймать исключение при индексировании foo и внятно выругаться.
Семантика у foo такая, что если в нем чего-то нет, то пользователь не тот счет ввел
Вот только оказалось, что исключение прилетело не от нашего индексирования, а из глубин bar.
И все - при какой-то совершенно посторонней ошибке пользователю показывается "У вас нет такого счета".
А потом еще интефейс усовершенствовали, чтобы вводить ничего не надо, а надо выбрать из списка, но проверку оставили.
livelight: (Default)

[personal profile] livelight 2017-03-18 01:13 pm (UTC)(link)
То есть, предлагаете присвоить такому способу третий уровень идиотизма, а не второй? :)

[personal profile] inkelyad 2017-03-18 01:36 pm (UTC)(link)
А вот бы знать.
Это демонстрация того, как я понял утверждения хозяина журнала о потере контекста - что одно и то же исключение, которое бросилось тут и или там, нужно как-то различать , но это немного затруднительно.
livelight: (Default)

[personal profile] livelight 2017-03-18 01:46 pm (UTC)(link)
Пользователю нужно сообщение с бизнес-смыслом.
Исключение OutOfBounds не имеет никакого бизнес-смысла само по себе, откуда бы оно ни вылетело. Оно может обрести такой смысл только после анализа инцидента разработчиками.
Однако, во многих случаях и глубокоуровневый код имеет возможность выкинуть исключение с бизнес-смыслом. Хотя бы ValidationFailedOutOfBoundsException extends ArrayIndexOutOfBoundsException - кому надо, может его поймать особым образом с учётом его бизнес-смысла, а кто не может - тот обработает его как техническое ArrayIndexOutOfBoundsException. Контекстом в данном случае будет точный подкласс и дополнительные его поля.
livelight: (Default)

[personal profile] livelight 2017-03-18 06:32 pm (UTC)(link)
Идеальным разработчикам в вакууме вполне по силам проанализировать все возможные исключительные ситуации (включая поломки внешних и внутренних систем, протёкшие абстракции того уровня, на котором эти программисты как раз работают и корявые введённые данные) и краевые случаи во всех возможных комбинациях и предусмотреть внятную диагностику для пользователя и хорошие процедуры фейл-бэка (например, чтобы банкомат, прежде чем сказать "ой, всё", постарался отдать пользователю его карточку). В реальной же жизни у них случаются баги, которые требуют анализа уже постфактум - для чего уже нужны логи, стек-трейсы и т.д.
Edited 2017-03-18 18:42 (UTC)
yurikhan: (Default)

[personal profile] yurikhan 2017-03-19 04:25 pm (UTC)(link)
Идеальный банкомат должен говорить, сколько у него осталось каких денег, не пользователю, а банку в заббикс. Чтобы по алёрту прибежал админ и поменял оранжевый (сине-зелёный, фиолетовый, коричневый) картридж.