Почему имена методов Java используют "получить" префикс так экстенсивно? По крайней мере, в моих программах Java существует много методов с именами, запускающимися со слова, "добираются". Процент получать-методов подозрительно высок. Я начинаю чувствовать, что слово "добирается", теряет его значение из-за инфляции. Это - шум в моем коде.
Я заметил, что существует другое соглашение о присвоении имен, используемое в функциональном / декларативном программировании и МН / SQL. Имя метода просто указывает, что возвращает метод. Вместо account.getAmount()
или Time.getIsoFormattedDateString(Date date)
они будут использовать account.amount()
и Time.isoFormattedDateString(Date date)
. Это имеет смысл мне, поскольку название функции описывает результат оценки метода (предполагающий, что нет никаких побочных эффектов, которыми не должно быть так или иначе). "Получить" префикс кажется лишним.
Я только что начал читать книгу "Чистый Код". Это говорит, что методы должны сделать только одну вещь, и что той вещью должно обычно быть одно из следующего:
Мой вопрос о третьей категории. Есть ли соглашения о присвоении имен кроме, "добираются" для этого вида методов? Какие критерии Вы используете при выборе имен/префиксов метода?
Вот пример:
У меня есть класс с двумя методами getDates()
и getSpecialDates()
. getDates()
просто возвращает значение частной переменной (ссылка на набор дат). Это - стандартный метод считывания, насколько я понимаю. getSpecialDates()
отличается; это звонит getDates()
, выбирает фильтр от другого класса, применяет фильтр и возвращает то, что является эффективно подмножеством getDates()
.
Метод getSpecialDates () можно было назвать computeSpecialDates()
, findSpecialDates()
, selectSpecialDates()
или elicitSpecialDates()
или что бы то ни было. Или я мог просто назвать его specialDates()
. И затем, для непротиворечивости, я мог переименовать getDates()
в dates()
.
Почему беспокойство, отделяющееся между методами, которые должны быть снабжены префиксом, "добирается" и методы, которые не должны, и почему беспокойство, находящее заменяющие слова для, "добирается"?
Важно, чтобы префикс "get" оставался, потому что:
метод должен указывать действие, поэтому он должен содержать глагол в своем имени
get показывает, что состояние переменная не изменится
насколько легко вы отличите метод account ()
от переменной account
в этом выражении:
newAccount = currentAccount + account ()
--- что делает этот account ()
?
Причина, по которой вы видите слишком много геттеров в своем коде, должна вас беспокоить!
Я использую get и set только для методов, которые только получают или устанавливают свойство, но не многое другое.
Я думаю, это подмножество идеала "дайте вашим переменным и функциям осмысленные имена".
"get" имеет специфическое значение в Java Beans, как многие уже отметили. Поэтому я думаю, что его следует ограничить использованием для получения значения внутренней переменной, возможно, с побочными эффектами. Я думаю, что это допустимо, если "get" включает в себя незначительные вычисления, например, преобразование типа данных или извлечение значения из встроенного класса или переосмысление других значений, например, "public int getRightMargin() { return width-margin.left; }". Любые побочные эффекты должны быть ограничены тем, что действительно является "побочным эффектом" получения значения, например, установкой флага, который говорит, что значение было получено.
Но если есть серьезные вычисления, я не думаю, что это должно называться "get". Может быть, "calc" или как-нибудь еще.
Было бы хорошо, если бы у нас были единообразные термины для именования функций, например, если бы мы все согласились, что "read" означает, что основная деятельность заключается в получении чего-то из базы данных, а "calc" означает выполнение вычислений или что-то подобное. Но это может быть нереально: возможно, существует слишком много случаев с тонкими различиями.
Как многие уже отметили, get() и set()... являются частью Конвенции Java Beans. Это необходимо для взаимодействия с другими частями Java Spec. Например, в JSP вы можете получить доступ к членам Java bean, указав имя свойства без префикса get
.
Учитывая боб: -
public class Foo {
public int getX() { return 1; }
}
Мы можем сделать следующий JSP, чтобы получить X: -
<jsp:useBean id="aFoo" class="Foo" />
<c:out value="${aFoo.X}" />
Существуют ли другие соглашения об именовании, кроме "get", для такого рода методов?
Да, вы можете использовать is
вместо get
для булевых свойств.
Исторический фрагмент: если вы посмотрите на некоторые из самых ранних API Java 1.0 (до JavaBeans), вы увидите, что у них нет префикса get. Например, java.awt.Container # minimumSize () устарел и заменен на #getMinimumSize ().
Одна из причин, которая требует от Java разработчиков использовать общее соглашение get/set, заключается в том, что многие фреймворки полагаются на него при создании bean и установке полей. Например, если у вас есть некоторое свойство, настроенное для Spring bean как
и в классе нет метода с именем setFoo()
, вы получите ошибку при создании bean.
Я начинаю чувствовать, что слово "получить" теряет смысл, потому что инфляции. Это шум в моем коде.
Я немного не согласен с этим выводом. Я бы не сказал, что это теряет свой смысл, я бы сказал, что, поскольку он широко используется, методы с префиксом get будут делать в значительной степени то, что вы от них ожидаете.
Для следующего примера:
Time.isoFormattedDateString(Date date)
Устанавливает ли это тип формата на основе входного параметра, чтобы все последующие вызовы использовали этот формат?
Я знаю, что кто-то придет к такому выводу с большой натяжкой. поскольку это статический метод, но были бы вы так же уверены, если бы этот метод был вызван на экземпляре? Возможно, но использование get устраняет всю двусмысленность:
getIsoFormattedDateString(Date date)
На мой взгляд, свойства - более элегантное решение, чем полное исключение get.
Java Beans очень привязаны к своим соглашениям об именах, например Предположим, вы объявляете имя переменной Name с соответствующим сеттером как setName (). Но это приведет к ошибке, поскольку setName должно соответствовать 'name' вместо Name. Другой пример логического isReadey; с получателем isReady (). Снова ошибка, поскольку он ищет готовое логическое значение. Итак, перед написанием кода вы должны ознакомиться с этим соглашением об именах. Но я лично предпочитаю это соглашение, так как оно упрощает работу программиста и кажется немного логичным после нескольких минут, проведенных с ним.
Лично я зависим от get
. Это просто человеческий язык. Когда вы чего-то хотите, вы хотите получить
что-то. Нет ничего плохого в префиксах get
. Что касается соглашения об именовании, я могу вспомнить префикс Select
для запросов к базе данных - SelectUsers
, например.
Какое значение имеет значение "get", когда мы живем в эпоху, когда любая IDE, которую стоит иметь, будет генерировать геттеров и сеттеров для ваших частных переменных и позволит вам сложить их, если вы не хотите их читать?
Ваша реальная проблема должна быть связана с дизайном: почему ваши объекты имеют так много атрибутов? Если у ваших объектов нет ничего, кроме добытчиков и сеттеров, страдаете ли вы от «анемичной модели предметной области»?
Нотация C# {get, set}
немного лучше, потому что она сокращает строки кода,но у вас все еще есть это надоедливое «получить», чтобы набрать для каждой переменной.
Одна из причин в том, что это существенная часть Java Bean Spec.
Отчасти причина большого количества методов get* заключается в том, что Java не поддерживает "свойства" в стиле .net/COM, а Java-бобы и подобные им используют функции getX и setX для воспроизведения функциональности свойства под названием X. Некоторые IDE для Java пользуются этим, чтобы позволить устанавливать и извлекать свойства.
Лично я не использую геттеры и сеттеры, когда это возможно (что означает: я не использую какой-либо фреймворк, которому он нужен, например Struts).
Я предпочитаю писать неизменяемые объекты ( общедоступные конечные поля), когда это возможно, в противном случае я просто использую общедоступные поля: меньше стандартного кода, больше продуктивности, меньше побочных эффектов. Первоначальным оправданием для get / set является инкапсуляция (сделайте ваши объекты как можно более застенчивыми), но на самом деле мне это не нужно очень часто.
В Effective Java Джошуа Блох дает такую убедительную рекомендацию:
Классы должны быть неизменными, если только есть очень хорошая причина сделать они изменчивы ... Если класс не может быть сделано неизменным, ограничьте его изменчивость насколько это возможно.
В той же книге он также говорит (но я не хочу копировать здесь всю книгу):
В шаблоне JavaBeans есть серьезные недостатки.
Я полностью согласен с этим, поскольку JavaBeans изначально предназначались для очень узкой проблемной области: манипулирования графическими компонентами в среде IDE. Плохая практика - использовать одно решение, предназначенное для решения другой проблемы.
Ну, хотя спецификация JavaBeans просит вас объявить геттеры и сеттеры, я обычно не объявляю их, если это не является абсолютно необходимым (как в случае многих MVC фреймворков). Я много занимался свингом в своей карьере Java и склонен объявлять переменные как public (да, это звучит немного не OOPy). Но мне это нравилось, поскольку выглядело лаконично, и "я" знал, что я делаю. Единственное преимущество, которое он имел - это уменьшенное количество строк.
Имена методов, например getSpecialDates ()
, computeSpecialDates ()
, findSpecialDates ()
, selectSpecialDates ()
и ()
для меня это команды из-за использования в их именах глаголов (действий). Команды должны вызывать побочные эффекты каждый раз, когда вы их вызываете. В то время как имена методов, такие как date ()
, date ()
, specialDates ()
[существительные], являются методами, которые возвращают полезное значение без побочных эффектов. Вызов метода несколько раз возвращает одно и то же значение каждый раз, если только не вызывается команда, побочным эффектом которой является изменение состояния.
Одна из причин того, что методы getter и setter часто пишутся в Java, заключается в использовании JavaBeans конвенций.
Однако стандартный API Java не является последовательным в этом отношении. Например, класс String
имеет метод length()
, а интерфейс Collection
определяет метод size()
, вместо getLength()
или getSize()
.
Java не поддерживает принцип единообразного доступа, поэтому для доступа к свойствам нужно писать методы getter и setter.
Один из вариантов - сохранить префикс get
для методов, возвращающих примитивные или неизменяемые значения, но убрать префикс для методов, возвращающих ссылки, которые могут быть использованы для изменения исходного получателя.
например, в java.util.Map
, size()
может называться getSize()
, но keySet()
будет не называться getKeySet()
.
Как упоминали другие, это для Java Beans. Однако, если вы используете Java, ПОЖАЛУЙСТА, назовите метод getXXX() только в том случае, если он возвращает только значение и больше ничего не делает. Как вы намекнули, если он делает что-то другое, назовите это чем-то другим, например, computeXXX().
Я иногда нахожу методы getXXX() с 50 строками кода - если это так, вы делаете это неправильно.
Предпосылка 1. Метод должен делать только одно. Предпосылка 2: метод получения - независимо от того, использует он префикс get или нет - не должен иметь побочных эффектов. С учетом этих двух предпосылок я предлагаю: метод, роль которого заключается в получении чего-либо и который делает это относительно простым и недорогим способом, не должен иметь в названии глагола.
Смысл существования добытчика не в том, чтобы что-то делать, а в том, чтобы что-то оценить. Нас не интересует, что делает метод . Поскольку он не имеет побочных эффектов, любые вычисления, выполняемые в методе, не могут представлять интереса. Нас интересует только то, что возвращает метод . Название метода должно отражать это в форме существительного. Имена методов, состоящие только из существительных, всегда должны быть «геттерами».
Информация в префиксе «получить» может быть выведена из-за отсутствия глаголов. Это проще и интуитивно понятнее, чем использование префикса get.
Можно предположить, что метод, имя которого состоит только из существительного и имеет возвращаемое значение, не имеет побочных эффектов и является относительно дешевым. Метод, имя которого содержит глагол и не имеет возвращаемого значения, существует, чтобы иметь побочные эффекты. Можно считать, что метод, имя которого содержит глагол и имеет возвращаемое значение, является относительно дорогим и может иметь побочные эффекты.
Похоже, что причина, по которой все повсюду пишут "получить", является просто догматической традицией, происходящей из шаблона JavaBeans. Оставьте префикс get, если вы действительно планируете использовать инструменты / фреймворки, которые в этом нуждаются!