?

Log in

No account? Create an account
об ошибках - По делам сюда приплыл, а не за этим [entries|archive|friends|userinfo]
Anatoly Vorobey

[ website | Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| English-language weblog ]

об ошибках [мар. 1, 2009|02:36 am]
Anatoly Vorobey
tema пишет: "При разработке интерфейсов крайне полезно на любое сообщение об ошибке задать вопрос "Почему?". Тогда половина сообщений об ошибках перестанет быть сообщениями об ошибках.", и приводит несколько примеров.

Это интересная мысль - спрашивать "почему" и настаивать на осмысленном объяснении ошибки. Мне она, в такой форме общего принципа, не приходила в голову, хотя на практике я неоднократно так поступал (в роли программиста).

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

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

Скажем, ты находишься в графическом редакторе, и сохраняешь файл. В зависимости от того, где ты его сохраняешь, это может быть жесткий диск твоего компьютера или сетевая папка на сервере. Графический редактор не должен об этом ничего знать - он всего лишь пытается записать записать файл, а уже другие модули в операционной системе решают, послать этот файл на местный диск или по сети на другой компьютер. Теперь предположим, что по какой-то причине сохранить файл не удалось и программа-редактор получила код ошибки. Не так уж легко спроектировать интерфейс между программой и операционной системой так, чтобы он содержал полезную информацию о такой ошибке во всех случаях, и вместе с тем сохранить информационный барьер между программой и драйверами диска/сети, не заставлять программу что-то о них знать. Может, файл не записался оттого, что неожиданно свалился роутер, находящийся между твоим компьютером и сервером. Твое приложение не знает, что такое "роутер" и сетевые неполадки и не умеет объяснить это тебе внутри своего интерфейса, с ограничениями своего дизайна, понятным тебе языком. Ему (и его программистам) вообще ничего не хочется знать о сети, а только о том, как картинки редактировать. Оно всего лишь хотело записать файл, и это не удалось. Вот оно и пишет "Operation failed" или еще что-то в этом роде.

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

Comments:
Страница 1 из 2
<<[1] [2] >>
From: (Anonymous)
2009-03-01 01:23 am
>настаивать на осмысленном объяснении ошибки

любопытно, насколько востребованы такие объяснения. варианты действий после объявления об ошибке, пожалуй, были бы конструктивней. try again later - мне кажется много полезней, чем указание на крайнего.
(Ответить) (Thread)
[User Picture]From: 3d_object
2009-03-01 01:30 am
Совершенно не согласен. try again later я и сам могу сообразить, а вот узнать, отчего произошел сбой - полезно.

(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: igorlord
2009-03-01 01:37 am
I think you are describing the thinking that was more applicable a few decades ago than now, when resource bean-counting (be it RAM bytes or bytes sent over a network) was very important. Today, these considerations may remain only in embedded devices and wireless networks (and their paramount importance is diminishing even there).

For today, this sounds like a cope-out rather than an attempt to fix a problem.

I would like to split this problem into two parts:

1. Informational (provide accurate and detailed error reports).

2. Functional (provide information necessary for some higher layer to automatically correct the problem).

The solution to the Informational problem actually seems simple. We already have a Universal informational data structure: a text string. We should also respect module layering as the prevalent system organization, with each higher layer providing a more "user-friendly" abstraction. Hence, I'd propose a List of Text Strings. Each higher-level layer is able to append a more user-friendly error description, while retaining the root cause error.

Since the data structure of "a list of strings" is brain-dead simple, all modules can expect to adhere to this simple convention.

That way, your editor's Top error may be something like:
"Save operation failed". Then, GUI would give an option: "more information", which would unfold the next error: "Network error". "More information" here would unfold: "Foreign host xyz.com unreachable". Depending on the network stack implementation (and no one higher up should care), it may have even more information: "some trace route information".


2. The "Functional" problem seems a bit harder, since it needs information that can be parsed by a computer, which necessities a predefined shared structure/API specification. It seems that here, the best thing we can do is introspective, backward-compatible APIs. That's a lot more fragile and cumbersome. :(
(Ответить) (Thread)
From: saccovanzetti
2009-03-01 05:16 am
there is often not enough information even to manually fix the problem, without diving into assembler codes.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: psilogic
2009-03-01 01:41 am
У меня в Bard-е все на модулях сделано, но с ошибками, тем не менее, проблем нет.

Схеима такая:

1. Объект x класса X, который что-то делает, и может "делать" с ошибками.
2. Абстрактный базовый класс ErrorHandler, у которого виртуальная функция 'erro' (на входе - текст ошибки и код).
3. Отнаследованные от ErrorHandler классы, показывающие ошибки так или эдак (в консоли, в окне, в логе и т.п.)

Допустим, некий модуль использует объекты разных классов, которые могут генерировать ошибки. Перед использованием модуль создает (или берет откуда-нибудь) объект ErrorHandler - такой, какой ему нужен, в зависимости от того, как хочет показывать ошибки. ErrorHandler назначается всем объектам, генерящим ошибки. Объект x в случае ошибки формирует текст ошибки и вызывает 'erro'. Он знает все о причинах ошибки (поскольку сам выполнил "ошибкоопасные" действия) но не знает ничего о том, как она будет показана юзеру.

И фсе работает :)


(Ответить) (Thread)
[User Picture]From: alexeybobkov
2009-03-01 02:15 am
А почему метод называется 'erro'? Что (или кто), собственно, имеется в виду?
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: msh
2009-03-01 03:39 am
Это очень интересный вопрос. Я считаю, что выдать наиболее точное и подробное "почему" - это не цель. Цель - выдать ту информацию, которой я могу воспользоваться.

Пара примеров:

1. Компилятор когда не может что-то скомпилировать должен давать максимум информации почему. Оптимально - ссылку на нарушенное правило из стандарта языка. Я смогу прочитать и воспользоваться.
2. У меня дома стоит газовая отопительная печка. Если она не запускается, то я могу прочитать код ошибки (она передает его миганием лампочки). Кодов этих уйма, но доступных мне реакций на них только три - попробовать выключить и включить, проверить подачу газа, вызвать ремонтника. Подробный код мне совершенно не нужен и трех лампочек бы хватило вполне.

Из этих соображений на устройстве, которое мы делаем, есть лампочка "соединение с интернетом работает" - лампочка горит, а сайт не открывается - проблема с тем сайтом, лампочка не горит - звоните в свой "интернет" ;-)
(Ответить) (Thread)
[User Picture]From: meshko
2009-03-01 04:21 am
Она мигает не только для Вас, но и для этого ремонтника.
Моя плита вот вообше показала номер телефона, по которому надо было звонить, чтобы пришел ремонтник. Ну и кодовый номер ошибки показала. Пришел ремонтник, впечатал код ошибки в гугл, нашел номер детали, который надо было заменить, сказал, что мне будет выгодней самому купить и поставить, взял 50 зеленых и ушел. Вот я теперь думаю: хорошо что она мне номер телефона дала или нет? Если бы помалкивала, у меня было бы на 50 больше...
(Ответить) (Parent) (Thread) (Развернуть)
(Удалённый комментарий)
[User Picture]From: _rowan_tree_
2009-03-01 03:57 am
NullPointerException :-)
А всего-то надо спускать сверху информацию, добавляя на каждом уровне, чтобы потом, если надо, собрать ее в сообщение об ошибке.
(Ответить) (Thread)
[User Picture]From: pargentum
2009-03-01 04:18 am
Мне кажется, описанная проблема могла бы быть относительно легко решена, если бы вместе с кодом ошибки подсистема выдавала бы текстовое сообщение, соответствующее этой ошибке. А вышележащая подсистема добавляла бы к этому сообщению текст о том, что она пыталась сделать, когда пришла эта ошибка.

То есть отвал сетевого диска выглядел бы как:
"ошибка при сохранении файла h:\mypicture.bml: no route to host". И пользователю было бы достаточно вспомнить, что у него диск h: сетевой.
(Ответить) (Thread)
[User Picture]From: zanuda
2009-03-01 04:49 am
С точки зрения последующей интернационализации это не очень хорошо. Но в принципе, подход для больших систем, наверное, правильный.

В продуктах нашей конторы есть такой файл message.dat, в котором хранятся все возмодные мессаджи и сообщения об ошибках. И к каждой ошибке девелопер должен добавлять возможную причину (или несколько причин) и как с ними бороться. Не очень хорошо, если по идее ошибка вообще не должна возникать (тогда надо писать, что-то вроде, "проблема с вашей инсталляцией нашего софта, обратитесь в службу поддержки".
(Ответить) (Parent) (Thread) (Развернуть)
From: qaraabayna
2009-03-01 04:59 am
В C++ задача решается каскадом try catch throw оборотов. Try элементарную операцию, catch ошибку, тут же сообщил на низком уровне, throw дальше. Все это обернуто в другой try, который выдает более общее сообщение об ошибке в контексте вызова элементарной операции и так далее.

Пример: сообщения make. Никто же не ругается на сообщения об ошибках makе...

У сообщения об ошибках есть две крайности: сказать сам дурак, или абсолютно точно заметить, что накрылся блок 3 в функции 5 модуля 7. Как не езди между двумя крайностями, либо юзеру будет непонятны технические детали, либо неопределенность сообщения опять таки сделает сообщение об ошибке невразумительным. Можно запросто скомбинировать и то и другое.

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


(Ответить) (Thread)
From: qaraabayna
2009-03-01 05:03 am
Собственно об этом и писал _rowen_tree_

http://avva.livejournal.com/2046108.html?thread=59199388#t59199388
(Ответить) (Parent) (Thread)
[User Picture]From: meshko
2009-03-01 05:08 am

логи, логи, логи

У меня очень мало опыта написания софта, с которым имеет дело конечный пользователь, но мой опыт написания серверного софта и системного администрирования говорит, что самое главное (и вполне осуществимое) -- это чтобы в случае возникновения внештатной ситуации профессионалу было легко понять, что случилось. А значит нужно писать логи. Много подробных логов с подробным отчетом об ошибке на всех уровнях, которые она затронула. И ещё эти логи должны быть сделаны так, чтобы их можно было найти.
На самом деле это сработает и в примере с сохранением файла на сетевой диск. На самом деле что ты тут пользователю не говори, а девочка-дизайнер не должна вообще быть в курсе, что её домашняя директория находится не на её компьютере, а на сервере. Но вот когда она звонит своему сисадмину и просит помочь, он должен сразу видеть в каком-нибудь application event log, что
failed to write h:\work\logo.png;
failure while accessing network drive h: mapped from \\fs4\homedirs\lisa
WINS resolution for fs4 failed;
failed to resolve hostname: 'fs4';
timed out while waiting for DNS query response from 192.168.1.2

после чего он сразу видит, что DNS сервер указа неверно, и все будет решено в 5 минут. Ещё раз: нет такого сообщения об ошибке, которое помогло бы конечному пользователю в этой ситуации.
(Ответить) (Thread)
[User Picture]From: alon_68
2009-03-01 06:34 am
У меня очень мало опыта написания софта, с которым имеет дело конечный пользователь...

Имхо, речь тут именно и идет о сообщениях, понятных конечному пользователю, далекому от программирования. Понятно, что профессионал имеет много путей разобраться, но ведь на каждый сбой его не навызываешься.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: white_lee
2009-03-01 05:45 am
>Мне кажется, одна из важных причин, что мешают сообщениям об ошибках быть понятными - модуляризация в программировании

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

И есть еще одна распространенная проблема - людям часто лень писать множество подробных сообщений, когда можно обойтись одним общим. Типа "Проверьте, нет ли в названии файла запрещенных символов: ! @ # $ % ^ & * ( ) < >" вместо того, чтоб сказать конкретно, какой запрещенный символ найден.
(Ответить) (Thread)
[User Picture]From: alon_68
2009-03-01 06:38 am
+1
Они часть дизайна и должны писаться теми же, кто пишет меню, расставляет элементы GUI... А то ведь иногда в пользовательской программе видишь что-то типа "Virtual function unresolved". И куда с этим бедному бухгалтеру или статистику? :)
(Ответить) (Parent) (Thread)
From: anonymous8216
2009-03-01 05:58 am
если бы все хотя бы пользовались strerror (3), так ведь и этого не дождешься...
(Ответить) (Thread)
[User Picture]From: gruimed
2009-03-01 08:06 am
Ни один маркетолог не пропостит в продукте сообщение об ошибке с пояснением "почему". И будет прав, ибо среднему пользователю это пояснение ничем не поможет, скорее еще больше напугает.

Рассчитывать на то, что сообщение об ошибке будет не только подробным, но еще и будет каким-то образом автоматически анализоривано и даст пользователю конкретные рекомендации, например "перезапусти ADSL router" наивно, это слишком сложно.

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

Продвинутым пользователям это было бы полезно, но их меньшенство.
(Ответить) (Thread)
From: anonymous8216
2009-03-01 09:02 am
если пояснение скрыть за кнопкой «подробности», никакой маркетолог не придерется.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: s1m
2009-03-01 08:42 am
"Networking error" гораздо инофрмативнее, чем "no ACK received from router XXX:XX". Какая разница почему не удалось доставить? Главное, что не удалось. Более детально имеет смысл рапортовать только ошибки, которые пользователь может починить: "No paper in the printer", "File is read only", etc.

Что делать полезно, так это давать пользователю возможность что-то сделать. Добавление кнопки "Report Error" к диалогу об ошибке ведет к магическому сокращению звонков в службу поддержки ;)
(Ответить) (Thread)
[User Picture]From: avva
2009-03-01 10:14 am
Я не предлагаю говорить пользователю "no ACK received from router XXX:XX", я предлагаю сказать ему как минимум "you lost your connection to the Internet", если это можно определить, или "the site xyz.com is not functioning at the moment", если это можно определить (а вместе - это 90% таких ошибок).
(Ответить) (Parent) (Thread)
(Удалённый комментарий)
[User Picture]From: avva
2009-03-01 10:02 am
Да, а что, разве это выглядит странным? Если вам банкомат скажет не "у вас на счету не осталось денег", а "ошибка 314897", какие слова вы в сердцах захотите сказать тому, кто спроектировал этот банкомат?
(Ответить) (Parent) (Thread) (Развернуть)
(Удалённый комментарий)
[User Picture]From: b0rg
2009-03-01 09:08 am
Вот интересно зачем детальные сообщения о неконтролируемых ошибках, если 90% пользователей хватит: we love you, try again.

Для продвинутых юзеров, возможно и понадобится детальное "module xxx can't reach the host yyy using protocol zzz" и стак трейс на сто строк, но что-то я сомневаюсь.
(Ответить) (Thread)
[User Picture]From: avva
2009-03-01 10:09 am
Поясняю еще раз на примере. Я пытаюсь зайти на сайт, мне выдает ошибку "cannot reach host". В 99% случаев эта ошибка вызвана одной из двух причин: либо у меня нет интернета вообще, либо вина того сайта, и я ничего не могу сделать. Причем try again почти всегда не помогает. Для меня, пользователя, важно знать, какая из двух причин верна, потому что первую я могу исправить, и кроме того, она мешает мне гораздо больше, чем вторая. Информацию о том, какая из двух причин верна, можно было бы мне представить, но сеть спроектирована так, что она теряется к тому моменту, когда браузер должен мне что-то написать. Это не есть хорошо. "we love you, try again" тут не поможет. Единственное, что поможет - совет "попробуйте открыть другой сайт, например гугль, и посмотреть, открывается ли он - если нет, скорее всего проблема у вас". Это нетривиальная инструкция для кого-то, кто не разбирается в техническом устройстве интернета, потому что это ему не нужно. Притом а) это нигде не написано, юзеры должны до этого дойти сами или научиться друг у друга; б) браузер, хотя мог бы это сделать за меня в фоновом режиме и сообщить мне что-то полезное, не делает.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: vodianoj
2009-03-01 12:16 pm
В блоге у Тёмы я ответил так:
http://tema.livejournal.com/286569.html?thread=125312873#t125312873
У тебя я не могу позволить подобной нездоровой лексики :-)
Приведённой мной пример ни в коем разе не претендует на полноту, но помоему он позволяет почувствовать, где должна проходить гранца между тем что можно, и что нельзя показывать пользователю в сообщениях об ошибках.

Т.е. если ворд не может записать на твой локальный харддиск, то он должен (и может) сообщить очень подробно почему он это не смог сделать. При этом, если он записывает на сетевое устройство, то часто единственное, что он должен (и обычно может сообщить) - это то, что устройство недоступно. Разумеется он может (и опять таки должен)предложить бейсик траблшутинг, типа, проверьте ваше подсоединение к интернет, и т.п., но вполне естественно, что в 90% случаев прийдётся позвонить в IT.
(Ответить) (Thread)
Страница 1 из 2
<<[1] [2] >>