Лучше использовать строки или int для ссылки на перечисления за пределами Java-части системы?

11

В моей работе обсуждалась возможность использования перечислений в Java.

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

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

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

Есть ли лучшая практика в отношении этой дискуссии, которая может мне помочь?

Изменить: Когда это возможно, мы используем само перечисление, поэтому весь наш код Java использует Enum. Под «ссылкой на перечисление» я подразумеваю: ссылку на значение в перечислении при обмене данными из JavaScript на сервер или при сохранении данных в базе данных.

И.С.Бах
источник
1
Что для вас "ссылка на перечисление"? Нормальное использование в исходном коде? Сериализация для хранения в базе данных? Выражение для использования в пользовательской документации? Выражение для использования в технической документации? Ответ будет совсем другим для всех тех.
Килиан Фот
Я отредактировал вопрос, и я надеюсь, что теперь он яснее: под «ссылкой на перечисление» я имею в виду ссылку на значение при обмене данными из JavaScript на сервер или наоборот или при сохранении значения в базе данных
JSBach
В API JavaScript я бы, конечно, использовал строки. В БД оба имеют свои преимущества. Некоторые базы данных имеют встроенную поддержку enum.
CodesInChaos

Ответы:

15

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

Итак, кроме Java, почему бы вам не использовать целое число? Возможно, у вас нет типов enum вне Java, хотя это не означает, что вы не можете продолжать использовать целое число для повышения производительности, верно? Да, это абсолютно верно, но подумайте, что происходит, когда вы добавляете новое значение перечисления. Если вы не добавите его в конец, все остальные значения перечисления после нового значения будут увеличены на единицу. Ну, мы просто укажем номер, чтобы он не мог измениться, или мы всегда добавим его в конец. Вы уверены, что ваши коллеги всегда будут поступать правильно? Мех? Вероятно? С надеждой? Может быть, вы не на все 100%. Имейте это в виду на секунду.

Ваш босс говорит вам, что на клиенте есть беспорядок, использующий ваше программное обеспечение после последнего обновления. Теперь все сущности X действуют так, как будто им присвоено значение перечисления Y, даже если им действительно присвоено значение Z. Вы проверяете репозиторий и да, кто-то добавил новое значение перечисления и не выполнил ваши рекомендации, как вы их просили. Теперь у вас есть дополнительное усложнение, что в базе данных написано 4, когда на самом деле должно быть 3, за исключением записей, которые были вставлены до обновления, которые действительно равны 4. Какое значение перечисления относится к 4 в любом случае? Разве это не Y? Вы не можете вспомнить. Вы должны проверить программу, чтобы проверить. Проще говоря, это беспорядок.

Если вместо этого в вашей базе данных написано «СЕРДЦЕ», «АЛМАЗЫ», «СПАДЫ», «КЛУБЫ», вы мало потеряли с точки зрения пространства и получили так много. Это правда, что мы говорим о незначительном падении производительности, но вам действительно не следует обращаться к базе данных, что часто имеет значение. Что касается места, оставьте это системным администраторам (не. Вашей. Проблеме.).

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

Нил
источник
2
Хорошие моменты, но вы забываете о случае, когда кто-то решает изменить имя одной из сущностей перечисления ( HEARTSна Heartили что-то в вашем примере), и вдруг все снова обрывается.
Скотт Уитлок
1
@ScottWhitlock Нет, если вы учтете это, хотя они могут решить переименовать его полностью. Они могут случайно удалить базу данных и удалить проект, но мы не можем объяснить все возможные инциденты здесь.
Нил
5
@Neil - правда, но мы пытаемся сыграть здесь. Я не знаком с перечислениями Java, но в C # я явно устанавливаю значения для перечислений, если значения должны иметь значение вне программы (например, в базе данных) (например, Hearts = 1, Diamonds = 2 и т. Д.) , Поскольку это не стандартный способ использования enum, он должен дать более позднюю паузу в редакторе. Плюс комментарий о том, где еще они используются, удобно.
Скотт Уитлок
1
@ScottWhitlock Это определенно лучший способ избежать подобных проблем. Хотя предположим, что вы это сделали, вы все равно видите 1, 2, 3, 4 в базе данных или сериализованы в каком-то файле. Не идеален с точки зрения обслуживания, как бы вы его ни разрезали.
Нил
2
Если можно добавить, если перечисление сериализовано как строка, и кто-то меняет имя перечисления, во время десериализации будет возникать ошибка во время синтаксического анализа. Если enum имеет тип int и кто-то меняет определение, ошибка будет дальше в процессе обработки, что будет сложнее диагностировать. CC @ ScottWhitlock.
Энди Тяхджоно
1

Я согласен с ответом Нейла, но только дополнение:

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

Это переживет и добавление / удаление / переупорядочение и изменение имени экземпляра enum. Но вам нужно будет написать логику сериализации / десериализации для перечисляемых полей вместо использования автоматического, доступного во многих инструментах. (Это легко, но это дополнительная работа).

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

user470365
источник
Да, мы пошли по этому пути, но мы используем hibernate, и нам пришлось добавить дополнительный код, чтобы иметь возможность анализировать значение в / из базы данных, и это казалось странным, поэтому мы решили использовать отношения .STRING и идти с именем enum.
И.С.Бах