2010-07-09 4 views
37

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

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

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

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

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

Вот пример:

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

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

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

+6

Использование «getThis» и «getThat» не теряет смысла, поскольку каждый получает действительно доступ. Это помогает понять, что вы делаете. Это не похоже на то, что компилятор собирается сказать «О, а другой получается? Теперь вы просто говорите об этом ...» – corsiKa

ответ

2

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

+1

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

+3

Это ваше мнение, а не факт. – duffymo

+1

+1 обеими руками :) Если у вас есть 100 методов в вашем классе (или доступно через иерархию), то просто набрав «yourObjectInstance.get» и немного подождите, заставляет Auto Complete в вашей среде IDE отфильтровать все «get "методы. Если бы они не начинались с получения, было бы трудно найти правильный. Типичным примером этой путаницы является collection.size() и array.length() –

9

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

+0

+1 Голые объекты для одного - это структура, которая опирается на соглашения об именах для создания переднего конца. – APC

+1

На самом деле (выступая как коммандер Обнаженных объектов), это подключаемая функция. Мы создаем метамодель с использованием FacetFactorys, а фабрики по умолчанию ищут префикс 'get'. Но им это не нужно. Этот дизайн также позволяет нам поддерживать другие языки; Я не работал с Groovy несколько недель назад, и (как это бывает) начался на Scala на этой неделе. Это использует аннотацию @BeanProperty Scala. Но, к OP, мы не думаем, что с геттерами тоже есть что-то не так: это соглашение об именах, которое представляет собой «ноу-хау». - Dan –

5

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

0

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

+0

Что вы используете для других методов, если не получаете *? –

16

Он исходит из JavaBeans naming conventions.

+7

Если Java добавит реальные свойства, нам больше не придется об этом беспокоиться. Я разочарован тем, что они были удалены из предложения Java 7. – Powerlord

+0

@R. Bemrose: Я согласен, я бы хотел, чтобы они добавили свойства. Однако нам все равно придется беспокоиться об этом, все устаревшие коды и существующие библиотеки/рамки не просто исчезнут. Кроме того, людям часто сложно менять свои привычки. Кажется, что много людей используют 'get ____' независимо от того, может ли метод быть хотя бы как свойство или нет. –

+0

библиотек и фреймворков не пришлось бы менять, так как любое предложение для поддержки свойств первого класса, скорее всего, будет синтаксическим сахаром и генерирует фактические методы в классе. Это инструмент, который придется корректировать (думает, как генераторы кода, IDE и т. Д.). – Matt

0

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

6

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

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

Java не поддерживает uniform access principle, поэтому вам необходимо написать методы получения и настройки для доступа к свойствам.

+0

Что вы подразумеваете под «Java не поддерживает принцип единого доступа»? Метод get() может возвращать вычисленное значение, а не значение частной переменной - переменные экземпляра не связаны по сути с методами get() или set() с тем же именем – Tarski

+0

@ Tarski вы понимаете UAP? Это означает, что вы можете получить доступ к свойствам так же, как и к элементам-членам. Так что что-то вроде 'Foo.thingy' действительно называет' Foo.getThingy() 'за кулисами. «Foo.thingy» выглядит так, как будто вы напрямую обращаетесь к var-компоненту, но вы этого не делаете. Такие языки, как C#, Ruby, Scala, поддерживают это. – Jesper

+0

В соглашении JavaBeans требуются методы get/set для каждого поля, но 'lenght' и' size' являются (скорее всего) не полями. Действительно, они, по-видимому, являются вычисленными значениями на основе полей –

4

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

0

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

2

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

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

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

Time.isoFormattedDateString(Date date) 

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

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

getIsoFormattedDateString(Date date) 

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

+1

Да, но почему не formatDateStringAsIso (Дата)? –

+0

@donroby Да, в каком-то смысле я согласен на этот пример. Но если бы вы взглянули на имя метода полностью вне контекста, вы бы знали, что он сделал? Зачем удалять префикс «get», когда он немедленно указывает любому разработчику, что будет делать этот метод. Это должно быть основной проблемой при использовании методов именования. –

+0

В этом случае «get» подразумевает, что я прочитал свойство. Если мой метод работает исключительно на входных аргументах для получения выходного значения, я бы не назвал его «получателем». Я бы сделал 'Time.toISO8601 (Date)' или 'ISO8601.from (Date)'? Конечно, «Instant.toString() Java 8, который выполняет эту работу для нас, полностью отверг эту особенность вопроса OP. –

3

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

Учитывая боб: -

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

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

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

Есть ли назвать, кроме "получить" соглашения для такого рода методов ?

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

1

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

26

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

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

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

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

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

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

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

+0

Хороший совет (из очень хорошей книги). – ZoFreX

+4

Согласен. Один из моих питомцев: Кто-то скажет, что слишком много публичных данных плохо, потому что это делает API сложным. Согласен. Но затем он говорит, что решение состоит в том, чтобы сделать их частными и создать геттеры и сеттеры. Как это помогает? Почему говорит «x = myObject.someValue» плохо, но «x = myObject.getSomeValue()» устраняет все проблемы? Единственная хорошая причина, по которой я вижу использование геттеров и сеттеров, - это побочные эффекты. – Jay

+0

@Jay: Это еще хуже, когда 'getSomeValue()' возвращает объект, и люди не понимают, что теперь кто-то может изменить состояние объекта только с помощью геттера. –

3

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

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

Нотация C# {get, set} немного лучше, потому что она сокращает количество строк кода, но у вас все еще есть что надоедливое «получить» для ввода каждой переменной.

0

Важно, что приставка «получить» остается, потому что:

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

  • ПОЛУЧИТЬ показывает, что состояние переменная не изменится

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

    newAccount = currentAccount + account() --- что именно account() делать?


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

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

Я не понимаю, почему «геттер» должен указать действие: он ничего не делает, он что-то оценивает. Чтобы показать, что состояние не изменяется, вы можете оставить глаголы из имени метода. Если я увидел метод с именем account(), я бы предположил, что он возвратил объект любого типа, представляющего учетную запись, скажем, интерфейс с именем Account. Если бы я увидел метод с именем amount(), я бы предположил, что он возвратил число, представляющее сумму. Кто бы не стал? –

+0

Я говорю, что слово GET в начале имени метода не является чем-то, что должно вызвать такой шум! И я не буду использовать account(), потому что это сделает мою программу более запутанной и неоднозначной. Я предпочитаю не оставлять двусмысленности в своих программах для тех, кто читал это после меня. Я лично простенько неправильно прочитал бы ACCOUNT() как ACCOUNT, и я подумал бы, что это не метод ... Если вы решили сбросить четкость кода один раз, вы сделаете это позже. Я думаю, что ясность кода важнее, чем метод, состоящий из 3-х символов короче ... –

+0

если вы читаете лучше, я написал «метод должен указать действие» , а так как вы сражаетесь за инкапсуляцию, вы используете методы и методы должен указать действие, потому что это то, что отличает их от переменных или типов (классов) ... снова - ясность кода. Но есть еще одна позиция - составите свои собственные правила написания кода и STICK WITH THEM - согласование является более важным, чем «лучше начинать переменные с верхнего регистра или нижнего регистра» ... –

1

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

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

Но если есть серьезные вычисления, я не думаю, что его следует называть «получить». Может быть, «calc» или что угодно.

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

3

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

Иногда я получаю методы getXXX() с 50 строками кода - если это так, вы делаете это неправильно.

3

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

3

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

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

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

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

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

1

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

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

Смежные вопросы