Исправить ошибки в коде библиотеки или отказаться от них? - PullRequest
12 голосов
/ 04 октября 2010

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

class Physics
{
    public static Float CalculateDistance(float initialDistance, float initialSpeed, float acceleration, float time)
    {
        //d = d0 + v0t + 1/2*at^2
        return initialDistance + (initialSpeed*time)+ (acceleration*Power(time, 2));
    }
}

Примечание: Пример и язык являются гипотетическими

Я не могу гарантировать, что исправление этого кода не нарушит кого-либо.

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

Должен ли я создать 2-ю функцию:

class Physics
{
    public static Float CalculateDistance2(float initialDistance, float initialSpeed, float acceleration, float time) { ... }

    //Deprecated - do not use. Use CalculateDistance2
    public static Float CalculateDistance(float initialDistance, float initialSpeed, float acceleration, float time) { ... }
}

На языке, на котором нет способа формально осудить код , могу ли я доверять всем, чтобы переключиться на CalculateDistance2?

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

Должен ли я исправлять ошибки или отказываться от них?

Смотри также

Ответы [ 6 ]

3 голосов
/ 04 октября 2010

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

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

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

Итак, я бы честно сказал, чтобы исправить это.

2 голосов
/ 04 октября 2010

Другой вариант - исправить ошибку, но оставить старый код как метод LegacyCalculateDistance, который доступен, если кому-то это действительно нужно.

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

2 голосов
/ 04 октября 2010

Хороший вопрос. Я с нетерпением жду некоторых других ответов. Вот мои 2 цента по этому вопросу:

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

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

(Если ваш класс является компонентом COM, общепринятым было бы создание нового интерфейса ICalculateDistance2, который делает исходный интерфейс устаревшим, но сохраняет его для обратной совместимости.)

2 голосов
/ 04 октября 2010

Однажды я несколько дней боролся с каким-то кодом MFC, который вел себя совершенно неожиданно.Когда я наконец понял, что это ошибка в поставляемой Microsoft библиотеке, я проверил базу знаний.Это было задокументировано как (приблизительно) «это известная ошибка, которую мы нашли 2 версии ОС назад. Мы не исправляем ее, потому что кто-то, вероятно, зависит от нее».1003 *

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

1 голос
/ 04 октября 2010

Просто ради аргумента, давайте предположим, что вашим гипотетическим языком был C ++ (хотя он больше похож на Java).В этом случае я бы использовал пространства имен для создания форка, с которым (разумно) легко иметь дело с точки зрения как нового, так и устаревшего кода:

namespace legacy {
class physics { 
    Float CalculateDistance(float initialDistance, float initialSpeed, float acceleration, float time)
    {
    // original code here
    } 
}
}

namespace current { 
class physics {
    Float CalculateDistance(float initialDistance, float initialSpeed, float acceleration, float time)
    {
    // corrected code here
    } 
}

Оттуда у вас есть несколько вариантов:выбирая между двумя.Например, существующий код может добавить директиву using: using legacy::physics;, и они продолжат использовать существующий код без каких-либо дальнейших изменений.Новый код может добавить using current::physics; вместо этого, чтобы получить текущий код.Когда вы это сделаете, вы (вероятно) осудите класс legacy::physics и запланируете его удаление по истечении определенного периода времени, количества ревизий или чего-либо еще.Это дает вашим клиентам возможность проверить свой код и переключиться на новый код упорядоченным образом, при этом пространство имен legacy не будет слишком загрязнено старым мусором.

Если вы действительно хотите получить подробные сведенияпри этом вы даже можете добавить схему нумерации версий в свои пространства имен, поэтому вместо просто legacy::physics это может быть v2_7::physics.Это учитывает возможность того, что даже когда вы «исправляете» код, удаленно возможно, что все еще может быть ошибка или два осталось, так что вы можете в конечном итоге пересмотреть его, и кто-то может в конечном итоге зависеть откакая-то произвольная версия, не обязательно просто оригинал или текущая версия.

В то же время это ограничивает «осведомленность» о версии, которая будет использоваться для одной (довольно) небольшой части кода (илипо крайней мере небольшая часть каждого модуля) вместо того, чтобы распространяться по всему коду.Это также дает довольно безболезненный способ для того, чтобы кто-то скомпилировал модуль с использованием нового кода, проверил наличие ошибок, переключился на старый код, если это необходимо, и т. Д., Без необходимости иметь дело непосредственно с каждым отдельным вызовом рассматриваемой функции.1016 *

1 голос
/ 04 октября 2010

Как вы уже описали, это компромисс между удовлетворением двух разных групп пользователей:

  • Существующие пользователи, которые создали свое программное обеспечение на основе ошибки в вашей библиотеке
  • Новые пользователи, которые будут использовать вашу библиотеку в будущем

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

Я думаю, вы должны спросить себя

"Имеет ли функция какое-либо значение с существующей в данный момент ошибкой?"

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...