внутренние маркеры ошибок

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

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

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

Один из способов, о котором я думаю, - это перечисление ошибок, но как убедиться, что они никогда не используются более чем в одном месте?

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

(Примечание 2: рассматриваемая программа будет приложением командной строки, работающим в системе пользователя. Но опять же, это только моя ситуация.)

(Примечание 3: целевой язык — D и Я очень хочу погрузиться в метапрограммирование. Приветствуются ответы на другие языки!)

(примечание 4: я явно хочу НЕ использовать фактические местоположения кода, а скорее какие-то символические имена для ошибок. Это потому, что, если код изменяется практически каким-либо образом, местоположения кода меняются.)


person BCS    schedule 25.11.2008    source источник


Ответы (3)


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

person Ned Batchelder    schedule 25.11.2008
comment
Хороший откат, но я бы предпочел, чтобы такая ошибка сломала сборку или более быструю обратную связь. - person BCS; 25.11.2008
comment
@BCS: затем запустите проверку как часть сборки, а не как часть модульных тестов: D - person Jonathan Leffler; 26.11.2008

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

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

В PHP для этого очень полезна функция debug_backtrace(). Я уверен, что есть эквивалент для вашей платформы.

Также не забудьте отправить соответствующие заголовки http: возможно: HTTP/1.1 500 Internal Server Error

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

person rebra    schedule 25.11.2008
comment
Кроме того, рассмотрите такие вещи, как регистратор в памяти, который входит в этот файл. - person S.Lott; 25.11.2008
comment
К сожалению, у меня нет системы трассировки в языке :( - person BCS; 25.11.2008

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

Я всегда считал, что сообщения о серьезных ошибках и внутренних ошибках должны быть максимально полезными для разработчика, чтобы определить проблему и быстро ее исправить. Большинство пользователей даже не будут смотреть на это сообщение об ошибке, но очень искушенные конечные пользователи (возможно, сотрудники службы технической поддержки) часто получают довольно хорошее представление о том, в чем проблема, и даже придумывают новые обходные пути, просматривая очень подробные сообщения об ошибках. Ключ в том, чтобы сделать эти сообщения об ошибках подробными, но не загадочными, и это больше искусство, чем наука.

Пример из программы Windows, использующей внешний COM-сервер. Если основная программа пытается создать экземпляр объекта с COM-сервера и завершается с ошибкой:

«ВНИМАНИЕ: невозможно создать экземпляр UtilityObject: ошибка« Класс не зарегистрирован »в« CoCreateInstance »»

99% пользователей увидят это и подумают, что это написано на греческом языке. Сотрудник службы технической поддержки может быстро понять, что им необходимо перерегистрировать COM-сервер. И разработчик будет точно знать, что пошло не так.

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

int someFunction()
{
  static const std::string loc = "someFunction";
  :  :
  if( somethingWentWrong )
  {
    WarningMessage(loc.c_str(), "Unable to Instantiate UtilityObject:  Error 'Class Not
    Registered' in 'CoCreateInstance);
  }
}

... который генерирует:

ПРЕДУПРЕЖДЕНИЕ [someFunction]: невозможно создать экземпляр UtilityObject: ошибка «Класс не зарегистрирован» в «CoCreateInstance».

person John Dibling    schedule 26.11.2008