Подтвердить что ты не робот

Соглашения об именовании методов Java: слишком много геттеров

Почему имена методов Java используют префикс "get" так широко? По крайней мере, в моих программах Java существует множество методов с именами, начинающимися со слова "get" . Процент get-методов подозрительно высок. Я начинаю чувствовать, что слово "получить" теряет смысл из-за инфляции. Это шум в моем коде.

Я заметил, что в функционально-декларативном программировании и PL/SQL используется другое соглашение об именах. Имя метода просто указывает, что возвращает метод. Вместо account.getAmount() или Time.getIsoFormattedDateString(Date date) они будут использовать account.amount() и Time.isoFormattedDateString(Date date). Это имеет для меня смысл, так как имя функции описывает результат оценки метода (предполагая, что побочных эффектов не существует, чего не должно быть в любом случае). Префикс "получить" кажется излишним.

Я только что начал читать книгу "Чистый код". В нем говорится, что методы должны делать только одно, и что эта вещь обычно должна быть одной из следующих:

  • Уведомлять о каком-либо объекте о событии, обычно передавая событие как параметр.
  • Задайте вопрос о каком-либо объекте, как правило, с именем метода, формирующим выражение естественного языка, передающим объект в качестве параметра и возвращающим логическое значение.
  • Извлеките что-нибудь, возможно, передав какой-либо ключ поиска или какой-либо объект, который будет преобразован в качестве параметра, и всегда возвращающий желаемый объект/значение.

Мой вопрос касается третьей категории. Существуют ли соглашения об именах, отличные от "get" для такого рода методов? Какие критерии вы используете при выборе имен/префиксов методов?

Вот пример:

У меня есть класс с двумя методами getDates() и getSpecialDates(). getDates() просто возвращает значение частной переменной (ссылка на коллекцию дат). Это, как я понимаю, стандартный геттер. getSpecialDates() отличается; он вызывает getDates(), выбирает фильтр из другого класса, применяет фильтр и возвращает то, что фактически является подмножеством getDates().

Метод getSpecialDates() может быть назван computeSpecialDates(), findSpecialDates(), selectSpecialDates() или elicitSpecialDates() или что угодно. Или я могу просто назвать его specialDates(). И затем, для согласованности, я мог бы переименовать getDates() в dates().

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

4b9b3361

Ответ 1

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

Я предпочитаю писать неизменные объекты (публичные конечные поля), когда это возможно, в противном случае я просто использую общедоступные поля: меньше кода котельной плиты, большей производительности и меньших побочных эффектов. Первоначальное обоснование для get/set - это инкапсуляция (сделайте ваши объекты как можно более застенчивыми), но на самом деле мне это не нужно очень часто.

В Эффективной Java Джошуа Блох делает эту убедительную рекомендацию:

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

В той же книге он также говорит (но я не хочу копировать всю книгу здесь):

Шаблон JavaBeans имеет серьезные недостатки.

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

Ответ 3

Часть причин, по которым так много методов get *, что Java не поддерживает "свойства" a la.net/COM и Java beans, и такие функции использования getX и setX реплицируют функциональность свойства, называемого X. Некоторые IDE для Java используют это, чтобы разрешить настройку и поиск свойств.

Ответ 4

Одна из причин, по которой методы getter и setter часто записываются на Java, объясняется использованием соглашений JavaBeans.

Однако стандартный Java API несовместим с этим. Например, класс String имеет метод length(), а интерфейс Collection определяет метод size() вместо getLength() или getSize().

Java не поддерживает принцип равномерного доступа поэтому вам нужно написать методы getter и setter для доступа к свойствам.

Ответ 5

Одна из причин заключается в том, что она является неотъемлемой частью Java Bean Spec.

Ответ 6

Одной из причин, по которым разработчикам Java необходимо использовать общее соглашение get/set, является то, что многие фреймворки полагаются на него для создания bean и установки полей. Например, если у вас есть какое-то свойство, настроенное для Spring bean, как <property name="foo" value="bar" />, и в классе нет метода с именем setFoo(), вы получите сообщение об ошибке bean.

Ответ 7

Как уже отмечалось многими, get..() и set()... являются частью Java Beans. Это необходимо для взаимодействия с другими частями Java Spec. Например, в JSP вы можете получить доступ к элементам из Java, указав имя свойства без префикса get.

Учитывая bean: -

public class Foo {
  public int getX() { return 1; }
}

Мы можем сделать следующий JSP, чтобы получить X: -

<jsp:useBean id="aFoo" class="Foo" />
<c:out value="${aFoo.X}" />

Существуют ли соглашения об именах, отличные от "get" для такого рода методов?

Да, вы можете использовать is вместо get для булевых свойств.

Ответ 8

Что означает "получить", когда мы живем в день и в возрасте, когда любая IDE, которая стоит того, будет генерировать геттеры и сеттеры для ваших личных переменных и позволяет вам складывать их, если вы предпочитаете их не читать?

Ваша настоящая проблема должна быть о дизайне: почему у ваших объектов столько атрибутов? Если у ваших объектов нет ничего, кроме геттеров и сеттеров, вы страдаете от "модели анемичного домена"?

Обозначение С# {get, set} немного лучше, потому что оно сокращает строки кода, но у вас все еще есть что надоедливое "get" для ввода для каждой переменной.

Ответ 9

Как уже упоминалось, это для Java Beans. Однако, если вы используете Java, PLEASE только называете метод getXXX(), если он возвращает только значение и ничего не делает. Как вы намекали, если он делает что-то еще, назовите его чем-то другим, например computeXXX().

Я иногда нахожу методы getXXX() с 50 строками кода - если это так, вы делаете это неправильно.

Ответ 10

Имена методов, такие как getSpecialDates(), computeSpecialDates(), findSpecialDates(), selectSpecialDates() и elicitSpecialDates(), для меня - это команды из-за использования глаголов (действий) в их именах. Команды должны иметь побочные эффекты каждый раз, когда вы их вызываете. В то время как имена методов, такие как date(), dates(), specialDates() [существительные], являются методами, возвращающими полезное значение без побочных эффектов. Вызов метода несколько раз возвращает одно и то же значение каждый раз, если не вызывается команда, чей побочный эффект заключается в изменении состояния.

Ответ 11

Помещение 1: Метод должен делать только одно. Помещение 2: метод геттера - если он использует префикс get или нет, он не должен иметь побочных эффектов. Учитывая эти два предположения, я предлагаю: метод, чья роль состоит в том, чтобы извлечь что-то и что делает это относительно простым недорогим способом, не обязательно иметь глагол в его имени.

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

Информация в префиксе "get" может быть выведена из-за отсутствия глаголов. Это проще и интуитивно понятнее, чем использование префикса get.

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

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

Ответ 12

Лично я зависим от get. Это всего лишь человеческий язык. Когда вы хотите что-то, вы хотите get что-то. В префиксах get нет ничего плохого. Что касается соглашения об именах, я могу придумать префикс Select для запросов к базе данных - SelectUsers например.

Ответ 13

Я начинаю чувствовать, что слово "get" теряет смысл, потому что инфляции. Это шум в моем коде.

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

В следующем примере:

Time.isoFormattedDateString(Date date)

Указывает ли этот тип формата на основе входного параметра, чтобы все последующие вызовы использовали этот формат?

Я знаю, что это немного зависит от того, что кто-то придет к такому выводу, поскольку это статический метод, но можете ли вы быть уверены, был ли этот метод вызван на экземпляр? Возможно, но использование get удаляет всю двусмысленность:

getIsoFormattedDateString(Date date)

На мой взгляд, свойства - более элегантное решение, чем падение вообще.

Ответ 14

Исторический фрагмент: если вы посмотрите на некоторые из самых ранних API Java 1.0 (pre JavaBeans), вы увидите, что у них нет префикса 'get'. Например, java.awt.Container # minimumSize() был заменен на #getMinimumSize().

Ответ 15

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

"get" имеет определенное значение в Java Beans, как многие отметили. Я думаю, поэтому он должен быть ограничен тем, что используется для извлечения значения внутренней переменной, возможно, с побочными эффектами. Я считаю приемлемым, если "получение" включает в себя незначительные вычисления, например, преобразование типа данных или извлечение значения из встроенного класса или переинтерпретацию других значений, например "public int getRightMargin() {return width-margin.left;}". Любые побочные эффекты должны быть ограничены вещами, которые действительно являются "побочными эффектами" получения ценности, например, установкой флага, в котором говорится, что он был извлечен.

Но если есть серьезные вычисления, я не думаю, что его следует называть "get". Может быть, "calc" или что-то еще.

Было бы хорошо, если бы у нас были согласованные термины для использования в функциях именования, например, если бы мы все согласились с тем, что "чтение" означает, что основным видом деятельности является извлечение чего-либо из базы данных, а "calc" означает выполнение вычислений или некоторые такие, Но это может быть нереалистично: возможно, слишком много случаев с незначительными различиями.

Ответ 16

Один из вариантов - сохранить префикс get для методов, возвращающих примитивные или неизменяемые значения, но отбросить префикс для методов, возвращающих ссылки, которые могут использоваться для изменения исходного получателя.

например. в java.util.Map, size() можно назвать getSize(), но keySet() не будет называться getKeySet().

Ответ 17

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

Ответ 18

Ну, хотя спецификация JavaBeans требует, чтобы вы объявляли геттеры и сеттеры, я обычно не буду объявлять их, если это абсолютно необходимо (как в случае многих фреймворков MVC). Я много сделал в моей карьере Java, и я склонен объявлять переменные как общедоступные (да, это звучит немного не OOPy). Но мне понравилось, так как это выглядело кратким и "я" знаю, что я делаю. Единственное преимущество, которое у него было, это сокращение числа строк.

Ответ 19

Java Beans очень привязана к его соглашениям об именах, например предположим, что вы объявляете имя переменной Name, с соответствующим установщиком как setName(). Но это породило бы ошибку, поскольку, setName должно соответствовать "name" вместо Name. Другой пример: boolean isReadey; с getter isReady(). Опять ошибка, так как она ищет логическое значение. Таким образом, перед кодом вы должны быть знакомы с этим соглашением об именах. Но я лично предпочитаю это соглашение, так как это упрощает работу программиста и кажется немного логичным после нескольких минут, проведенных с ним.

Ответ 20

Важно, чтобы префикс "получить" остался, потому что:

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

  • get показывает, что состояние переменной не изменится

  • Насколько легко было бы отличить метод account() от переменной account в этом выражении:

    newAccount = currentAccount + account() --- что делает это account()?


Причина, по которой вы видите слишком много геттеров в вашем коде, должна вас беспокоить!

  • Либо вы отделяете свои классы от меньших, либо
  • лучше спрячьте свой код, потому что вам не нужно раскрывать своих стажеров классов и даже пытаться скрыть их как можно больше!