Зафиксировать общие библиотечные функции или отказаться затем?

Предположите, что у меня есть функция с ошибкой в нем:

Псевдокод:

void Foo(LPVOID o)
{ 
   //implementation details omitted
}

Проблемой является переданный пользователь null:

Object bar = null;

...

Foo(bar);

Затем функция могла бы отказать из-за нарушения прав доступа; но это, могло также оказаться, хорошо работало. Ошибка - то, что функция должна была проверять на недопустимый случай передачи null, но это просто никогда не делало. Это никогда не была проблема, потому что разработчикам доверяли для знания то, что они делают.

Если я теперь изменяю функцию на:

Псевдокод:

void Foo(LPVOID o)
{
   if (o == null) throw new EArgumentNullException("o");

   //implementation details omitted
}

затем люди, которые счастливо использовали функцию и произошли с, но не, получают нарушение прав доступа, теперь внезапно начнет видеть EArgumentNullException.

Я продолжаю позволять людям, использующим функцию неправильно и создавать новую версию функции? Или я фиксирую функцию для включения то, что она должна была первоначально иметь?


Таким образом, теперь мораль dillema. Вы когда-либо добавляете новые проверки работоспособности, проверки безопасности, утверждения к вырезанию кода? Или Вы вызываете старую функцию, от которой отказываются, и имеете новую?


Считайте ошибку столь распространенной, что Microsoft должна была зафиксировать ее для разработчиков:

 MessageBox(GetDesktopWindow, ...);

Вы никогда, когда-либо хотите сделать модель окна против рабочего стола. Вы запрете систему. Вы продолжаете позволять разработчикам запереть компьютер пользователя? Или сделайте Вы изменяете функцию на:

 MessageBox(HWND hWndParent, ...)
 {
    if (hWndParent == GetDesktopWindow)
       throw new Exception("hWndParent cannot be the desktop window. Use NULL instead.");

    ...
 }

В действительности Microsoft изменила Менеджер окон для автозафиксированного плохого параметра:

 MessageBox(HWND hWndParent, ...)
 {
    if (hWndParent == GetDesktopWindow)
       hWndParent = 0;

    ...
 }

В моем составленном примере нет никакого способа исправить функцию - если мне не дали объект, я не могу сделать то, что я должен сделать на нем.

Вы рискуете взламывать существующий код путем добавления проверки параметра? Вы позволяете существующему коду продолжить быть неправыми, получая неправильные результаты?

5
задан Ian Boyd 18 March 2010 в 17:47
поделиться

6 ответов

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

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

Конечно, это требует, чтобы вы задокументировали то, что ваша функция требует в качестве входных данных.

1
ответ дан 15 December 2019 в 06:22
поделиться

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

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

0
ответ дан 15 December 2019 в 06:22
поделиться

Это полностью зависит от вас, вашей кодовой базы и ваших пользователей.

Если вы являетесь Microsoft и у вас есть ошибка в вашем API, который используется миллионами разработчиков по всему миру, то вы, вероятно, захотите просто создать новую функцию и обновить документацию на старой. Если вы можете, вы также можете обновить компилятор, чтобы он также выдавал предупреждения. (Хотя даже в этом случае вы можете изменить существующую систему; помните, когда MS переключила VC на стандарт C ++, и вам пришлось обновить все ваши #include iostream и добавить с помощью std ] s, чтобы простые существующие консольные приложения снова работали?)

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


Если вы вы небольшая компания или независимый разработчик, тогда обязательно исправьте эту функцию.Если вам нужно только обновить себя или несколько человек о новом использовании, то исправление этого является лучшим решением, тем более что это даже не имеет большого значения, потому что все, что на самом деле требуется, - это добавленное примечание к документации для функции. например, не передавать NULL или , генерируется исключение, если hWnd является рабочим столом и т. д.

Другим вариантом компромисса может быть создание функции оболочки. Вы можете создать небольшую встроенную функцию, которая проверяет аргументы, а затем вызывает существующую функцию. Таким образом, вам действительно не нужно много делать в краткосрочной перспективе, и в конечном итоге, когда люди перейдут на новый, вы можете отказаться от него или даже удалить старый, перенеся код на новый один раз между проверками. {{1 }}


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

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

0
ответ дан 15 December 2019 в 06:22
поделиться

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

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

2
ответ дан 15 December 2019 в 06:22
поделиться

Два варианта:

  • Присвойте версии для проверки ошибок новое имя и исключите старую версию (в одной версии позже она начнет выдавать предупреждения (время компиляции, если возможно, время выполнения при необходимости), двумя версиями позже удалите).
  • [не всегда возможно] Поместите недавно введенную проверку ошибок таким образом, чтобы она срабатывала только в том случае, если неизмененная версия вызвала бы сбой или выдала неопределенное поведение. (Чтобы пользователи, которые заботились о своем коде, не получали неприятных сюрпризов.)
0
ответ дан 15 December 2019 в 06:22
поделиться

Именно здесь удобны автоматические тесты [модульное тестирование, интеграционное тестирование, автоматическое функциональное тестирование], они дают вам возможность изменять существующий код с уверенностью.

Внося подобные изменения, я бы посоветовал найти все способы использования и убедиться, что они ведут себя так, как вы думаете.

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

Итак, вносите изменения, запускайте модульные тесты, а затем автоматические функциональные тесты. Исправьте любые ошибки и ваш золотой!

0
ответ дан 15 December 2019 в 06:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: