Соглашения об именовании методов 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" ?
Ответы
Ответ 1
Я лично не использую геттеры и сеттеры, когда это возможно (это означает: я не использую какие-либо фреймворки, которым это необходимо, например Struts).
Я предпочитаю писать неизменные объекты (публичные конечные поля), когда это возможно, в противном случае я просто использую общедоступные поля: меньше кода котельной плиты, большей производительности и меньших побочных эффектов. Первоначальное обоснование для get/set - это инкапсуляция (сделайте ваши объекты как можно более застенчивыми), но на самом деле мне это не нужно очень часто.
В Эффективной Java Джошуа Блох делает эту убедительную рекомендацию:
Классы должны быть неизменными, если только есть очень веская причина сделать они изменяемы... Если класс не может быть сделанный неизменным, ограничивает его изменчивость насколько это возможно.
В той же книге он также говорит (но я не хочу копировать всю книгу здесь):
Шаблон JavaBeans имеет серьезные недостатки.
Я полностью согласен с этим, поскольку JavaBeans изначально были предназначены для очень узкой проблемной области: манипуляция графическими компонентами в среде IDE. Плохая практика - использовать одно решение, предназначенное для решения другой проблемы.
Ответ 2
Он исходит из соглашений об именах JavaBeans.
Ответ 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()
?
Причина, по которой вы видите слишком много геттеров в вашем коде, должна вас беспокоить!
- Либо вы отделяете свои классы от меньших, либо
- лучше спрячьте свой код, потому что вам не нужно раскрывать своих стажеров классов и даже пытаться скрыть их как можно больше!