Насколько важны соглашения об именах для геттеров в Java?

Im огромный сторонник последовательности и, следовательно, конвенций.

Тем не менее, Im в настоящее время разрабатывает структуру на Java, где эти соглашения (в частности, соглашение о префиксе get/set), похоже, мешают читаемости. Например, некоторые классы будут иметь свойства id и name, а использование o.getId() вместо o.id() кажется совершенно бессмысленным по ряду причин:

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

Я получаю некоторое подтверждение от классов Java Collection (и других классов из библиотеки Java Platform), которые также нарушают соглашения JavaBean (например, они используют size вместо getSize и т.д.).

Чтобы устранить эту проблему: компонент никогда не будет использоваться как JavaBean, поскольку они не могут быть осмысленно использованы таким образом.

С другой стороны, я не опытный Java-пользователь, и я не знаю, что другие разработчики Java ожидают от библиотеки. Могу ли я следовать примеру классов Java Platform в этом или считается плохой стиль? Является ли нарушение соглашения get/set в классах библиотеки Java ошибочным в ретроспективе? Или вполне нормально игнорировать соглашения JavaBean, когда они не применимы?

(Соглашения Sun для Java не упоминайте об этом вообще.)

Ответ 1

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

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

Ответ 2

Я действительно ненавижу это соглашение. Мне бы очень повезло, если бы он был заменен реальным Java-инструментом, который предоставил бы методы accessor/modifier.

Но я соблюдаю это соглашение во всем моем коде. Мы не программируем в одиночку, и даже если вся команда соглашается на специальную конвенцию прямо сейчас, вы можете быть уверены, что будущим новичкам или будущей команде, которая будет поддерживать ваш проект, будет сложно в начале... Я считаю, что неудобства для get/set не так велики, как неудобство от нестандартного.


Я хотел бы затронуть еще одну проблему: часто программное обеспечение Java использует слишком много аксессуаров и модификаторов (get/set). Мы должны применять гораздо больше рекомендаций Сообщить, не спрашивайте. Например, замените геттеры на B "реальным" методом:

    class A {
      B b;
      String c;
      void a() {
        String c = b.getC();
        String d = b.getD();
        // algorithm with b, c, d
      }
    }

по

    class A {
      B b;
      String c;
      void a() {
        b.a(c); // Class B has the algorithm.
      }
    }

Этот хороший рефактор получает много хороших свойств:

  • B можно сделать неизменным (отлично подходит для потокобезопасности)
  • Подклассы B могут изменять вычисление, поэтому B не может требовать другого свойства для этой цели.
  • Реализация проще в B, которая была бы в A, потому что вам не нужно использовать getter и внешний доступ к данным, вы находитесь внутри B и можете воспользоваться деталями реализации (проверка ошибок, специальных случаях, используя кешированные значения...).
  • Будучи расположенным в B, с которым он имеет больше связей (два свойства вместо одного для A), скорее всего, рефакторинг A не повлияет на алгоритм. Для рефакторинга B это может быть возможность улучшить алгоритм. Таким образом, обслуживание меньше.

Ответ 3

Нарушение соглашения get/set в классах библиотеки Java, безусловно, является ошибкой. Я бы рекомендовал вам следовать за соглашением, чтобы избежать сложности понимания того, почему/когда соглашение не соблюдается.

Ответ 4

Джош Блох фактически борется с вами в этом вопросе в Эффективная Java, где он защищает вариант get без вариантов для вещей, которые aren 't предназначен для использования как beans, для удобства чтения. Конечно, не все согласны с Блохом, но он показывает, что есть случаи для и против демпинга get. (Мне кажется, что читать легче, поэтому, если YAGNI, нажмите get.)

Относительно метода size() из рамки коллекций; кажется маловероятным, что это просто "плохое" наследие, когда вы смотрите, скажем, на более новый класс Enum, который имеет name() и ordinal(). (Вероятно, это объясняется тем, что Блох является одним из Enum двух приписываемых авторов. ☺)

Ответ 5

Безрисковая схема используется на языке, таком как scala (и другие языки), с Единый принцип доступа:

Scala сохраняет имена полей и методов в одном и том же пространстве имен, что означает, что мы не можем назвать число полей, если метод называется count. Многие языки, такие как Java, не имеют этого ограничения, потому что они сохраняют имена полей и методов в разных пространствах имен.

Поскольку Java не предназначен для предоставления UAP для "свойств", лучше всего ссылаться на эти свойства с соглашениями get/set.

UAP означает:

  • Foo.bar и Foo.bar() совпадают и относятся к свойствам чтения или к методу чтения для свойства.
  • Foo.bar = 5 и Foo.bar(5) совпадают и относятся к настройке свойства или методу записи для свойства.

В Java вы не можете достичь UAP, потому что Foo.bar и Foo.bar() находятся в двух разных пространствах имен.
Это означает, что для доступа к методу чтения вам необходимо вызвать Foo.bar(), который ничем не отличается от вызова любого другого метода.
Таким образом, это соглашение о назначении может помочь дифференцировать этот вызов от других (не связанных с свойствами), поскольку "все службы (здесь" просто чтение/установка значения или вычисление "), предлагаемые модулем, не могут быть доступны через единая нотация".
Это не обязательно, но является способом распознавания службы, связанной с получением/установкой или вычислением значения свойства, из других служб.
Если бы UAP был доступен на Java, это соглашение не понадобилось бы вообще.

Примечание: size() вместо getSize(), вероятно, является устаревшим плохим наименованием, сохраненным для Java-мантры, является "Обратная совместимость: всегда".

Ответ 6

Рассмотрим это: Многим фреймворкам может быть предложено ссылаться на свойство в поле объекта, такое как "имя". Под капотом структура понимает, чтобы сначала превратить "имя" в "setName", выяснить из своего сингулярного параметра, что является типом возврата, а затем сформировать либо "getName", либо "isName".

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