Являются ли когда-нибудь жесткие литералы приемлемыми? - PullRequest
15 голосов
/ 31 декабря 2008

База кода, над которой я сейчас работаю, завалена жестко закодированными значениями.

Я рассматриваю все жестко закодированные значения как запах кода и пытаюсь по возможности устранить их ... однако есть некоторые случаи, в которых я не уверен.

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

1. MyTextBox.Text = someCondition ? "Yes" : "No"
2. double myPercentage = myValue / 100;

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

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

Может кто-нибудь предложить подходящий способ справиться с таким жестким кодированием? И кто-нибудь может вспомнить места, где жесткое кодирование является приемлемой практикой?

Ответы [ 21 ]

17 голосов
/ 31 декабря 2008

А кто-нибудь может вспомнить места, где жесткое кодирование является приемлемой практикой?

  • Небольшие приложения
  • Проекты для одного человека
  • Бросай прочь
  • Недолговечные проекты

Короче говоря, все, что не будет поддерживаться другими.

Ну и дела, я только что понял, насколько сильно кодер-сопровождающий ранил меня в прошлом:)

16 голосов
/ 31 декабря 2008

Конечно, жесткое кодирование иногда приемлемо. Следование догмам редко бывает так полезно, как использование вашего мозга.

(Для примера, возможно, интересно вернуться к войнам goto. Сколько программистов, как вы знаете, поклялись всем святым, что goto - зло? взвешенное обсуждение предмета в Code Complete?)

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

Это не значит, что «самая простая вещь» не должна быть читаемым кодом. Это может иметь смысл, даже в броске, чтобы написать:

const MAX_CACHE_RECORDS = 50
foo = GetNewCache(MAX_CACHE_RECORDS)

Это не зависит от того факта, что за три итерации кто-то может попросить настроить число записей в кэше, и вы можете закончить рефакторинг константы.

Просто помните, если вы пойдете в крайности, как

const ONE_HUNDRED = 100
const ONE_HUNDRED_AND_ONE = 101

мы все придем на The Daily WTF и посмеемся над тобой. : -)

Подумайте! Вот и все.

15 голосов
/ 31 декабря 2008

Настоящий вопрос не в жестком кодировании, а в повторении. Если вы воспользуетесь превосходным советом, который можно найти в «Прагматическом программисте» , просто не повторяйте себя (СУХОЙ).

Принимая принцип СУХОГО, можно что-то жестко закодировать в любой точке. Однако, как только вы снова используете это конкретное значение, выполните рефакторинг, поэтому это значение будет жестко задано только один раз.

7 голосов
/ 31 декабря 2008

Это никогда не хорошо, и ты только что доказал это ...

double myPercentage = myValue / 100;

Это НЕ процент. Что вы хотели написать:

double myPercentage = (myValue / 100) * 100;

Или точнее:

double myPercentage = (myValue / myMaxValue) * 100;

Но эти жестко запрограммированные 100 перепутались с вашим умом ... Так что используйте метод getPercentage, предложенный Коленом:)

double getpercentage(double myValue, double maxValue)
{
   return (myValue / maxValue) * 100;
}

Также, как предположил ctacke, в первом случае вы окажетесь в мире боли, если вам когда-нибудь понадобится локализовать эти литералы. Добавить пару переменных и / или функций никогда не составит труда

6 голосов
/ 31 декабря 2008

Случай 1: Когда следует жестко кодировать вещи: когда у вас нет оснований думать, что они когда-нибудь изменятся. Тем не менее, вы должны НИКОГДА не разбирать жесткий код в строке. Потратьте время на создание статических или глобальных переменных или всего того, что дает вам ваш язык. Сделайте их в рассматриваемом классе, и если вы заметите, что два класса или области вашего кода имеют одинаковое значение по той же причине (то есть это не просто совпадение), укажите их в одном месте.

Случай 2: Для случая 2 вы правы: законы «процента» не изменятся (здесь разумно), поэтому вы можете жестко встроить код.

Случай 3: В третьем случае вы думаете, что ситуация может измениться, но вы не хотите / не имеете времени загружать ResourceBundles или XML или что-то еще. В этом случае вы используете любой возможный механизм централизации - ненавистный класс Singleton - хороший - и продолжайте в том же духе, пока вам действительно не понадобится решать проблему.

Третий случай сложен, однако: чрезвычайно сложно интернационализировать приложение, не выполняя его на самом деле ... поэтому вы захотите жестко закодировать материал и просто надеяться, что, когда парни из i18n постучат, ваш код не худший вкус кода вокруг:)

Редактировать: Позвольте мне упомянуть, что я только что закончил проект рефакторинга, в котором предыдущий разработчик поместил строки подключения MySql в более 100 мест в коде (PHP). Иногда они были прописными, иногда строчными и т. Д., Поэтому их было трудно найти и заменить (хотя Netbeans и PDT очень помогли). Есть причины, по которым он / она сделал это (проект под названием POG в основном вызывает эту глупость), но нет ничего, что кажется * на 1020 * меньше, чем хороший код, чем повторять то же самое в миллионах мест.

6 голосов
/ 31 декабря 2008

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

4 голосов
/ 31 декабря 2008

Лучший способ для вашего второго примера - определить встроенную функцию:

double getpercentage(double myValue)
{
   return(myValue / 100);
}

...

double myPercentage = getpercentage(myValue);

Таким образом, гораздо более очевидно, что вы делаете.

3 голосов
/ 31 декабря 2008

«Жесткое кодирование» - это не та вещь, о которой стоит беспокоиться. Дело не в том, есть ли специальные значения в коде или в конфигурационных файлах, дело в:

  • Если значение может когда-либо измениться, сколько это работы и как тяжело ее найти? Поместить его в одном месте и сослаться на это место в другом месте - это не много работы и, следовательно, способ обезопасить его.
  • Будут ли программисты сопровождения точно понимать, почему ценность такая, какая она есть? Если есть какие-либо сомнения, используйте именованную константу, которая объясняет значение.

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

  • вы действительно хотите поддержать клиентов, меняющих значения сами
  • никакое значение, которое может быть помещено в файл конфигурации, не может вызвать ошибку (переполнение буфера, кто-нибудь?)
  • процесс сборки и развертывания - отстой
3 голосов
/ 31 декабря 2008

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

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

Следует избегать жесткого кодирования, так как Дракула избегает солнца. Это вернется, чтобы укусить тебя в задницу в конце концов.

3 голосов
/ 13 января 2009

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

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

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

Я использую константы для сравнения с именами тестовых файлов.

...