Java Beans: преувеличенные ассоциативные массивы?

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

Я нашел этот вопрос:

Java Beans: что мне не хватает?

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

Я вижу код, который выглядит так:

public class FooBean {
  private int a;
  private int b;
  private int c;

  public int getA() { return a; }
  public int setA(int x) { a = x; }

  // etc...
}

Никакой дополнительной структуры или контроля, кроме геттеров и сеттеров. Есть ли какой-то супер-крутой трюк с компилятором, который включает в себя отражение, геттеры и сеттеры, а также необходимость в некоторых очень неудобных (но оптимизированных компилятором) статических ассоциативных массивах?

Или, может быть, я полностью упускаю суть. :\

Ваше здоровье!

Изменить:

Здесь определенно не продвигается идея публичных полей.


person Jeremy Powell    schedule 27.07.2009    source источник
comment
К сожалению, большинство ответов на этот вопрос полностью пропустили фактический вопрос и интерпретируют его как то, почему есть методы получения и установки...   -  person Mike Daniels    schedule 27.07.2009
comment
Из того, что вы, ребята, говорите, кажется, что Java Beans - это скорее практика программирования культа грузов, чем что-либо еще.   -  person Jeremy Powell    schedule 27.07.2009
comment
@Mike: так дай свой ответ, если считаешь, что правильно его понял   -  person dfa    schedule 27.07.2009
comment
Просто подумал, что я упомяну: многие bean-компоненты используются для передачи данных и не имеют никаких данных. Я пришел к выводу, что это ужасная трата кода. Единственная причина, по которой я вижу, что это не просто хеш-таблицы, — это безопасность типов. Когда мне сейчас нужен такой набор свойств, я на самом деле просто инкапсулирую хэш свойств в свой пакет. Я бы хотел, чтобы в Java был принят какой-то предопределенный безопасный для типов шаблон набора свойств с автоматическим уведомлением и проверкой, но большинство людей, похоже, счастливы вместо этого тратить свои дни на написание сеттеров и геттеров.   -  person Bill K    schedule 29.07.2009


Ответы (6)


На самом деле, да, волшебство происходит.

Это действительно тупой шаблон, но GUI bean-компоненты (которыми являются все компоненты) предназначались для рефлексивного анализа разработчиком GUI. Общедоступные поля set/get предназначены для использования в качестве «свойств», с которыми пользователь может работать при создании своего графического интерфейса.

Редактировать: в защиту солнца я должен сказать, что, хотя шаблон оказался довольно неприятным из-за всех людей, которые скопировали его и начали использовать в своем коде, отличном от bean-компонента, он позволил людям интегрировать классы с помощью GUI Builder. без использования каких-либо внешних метаданных. Вам не нужен XML-файл или файл свойств для редактора, это так же просто, как расширение Button и размещение нового объекта на поддоне.

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

Теперь есть гораздо лучшее решение: используя аннотации для пометки закрытых полей, отражающий инструмент все еще может анализировать их и привязывать к элементам управления конструктора. Это было бы намного чище и не делало бы все ваши объекты настолько уязвимыми для внешних изменений состояния.

person Bill K    schedule 27.07.2009

Как вы заметили, Java Beans - это довольно тривиальное соглашение о кодировании.

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

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

person Alex Feinman    schedule 27.07.2009
comment
+1 за хорошее краткое изложение того, для чего предназначена конвенция. Но я бы не согласился с вашим утверждением, что конвенция больше не нужна. Spring является примером, в котором широко используется проводка в стиле bean. Если у вас есть крупномасштабная веб-служба, которая в основном состоит из компонентов Java, гораздо удобнее связать их вместе с помощью XML-файла, чем писать код Java для выполнения связи. - person Stephen C; 28.07.2009
comment
И большинство из них теперь используют аннотации вместо проводки в стиле bean-компонентов, потому что стиль bean-компонентов, одним словом, плох. - person Bill K; 29.07.2009

Без сомнения, люди злоупотребляют глупыми геттерами/сеттерами.

Однако представьте, сколько боли вам придется пережить за 2 года, когда вы поймете, что вам нужно удалить пробелы из строки в вашем методе setEmail(string email);, и весь ваш код жестко связан с использованием открытых полей вместо вызова метода.

Помните одно из основных правил объектно-ориентированного дизайна «Код для интерфейса, а не для реализации». Доступ к общедоступным полям класса, безусловно, относится ко второму варианту и значительно усложняет рефакторинг кода.

person nos    schedule 27.07.2009
comment
Возражение связано не обязательно с идеей геттеров и сеттеров, а с тем фактом, что мы должны писать чертовы вещи вручную. - person skaffman; 27.07.2009
comment
@skaffman, современные IDE предоставляют шаблоны, поэтому их легко сгенерировать автоматически. Eclipse может генерировать конструкторы и методы получения/установки для нескольких полей. - person Thorbjørn Ravn Andersen; 27.07.2009
comment
Хорошо, справедливо,. но вы все равно получите кучу бесполезного беспорядка. - person skaffman; 27.07.2009
comment
@skaffman: IDE можно легко написать, чтобы скрыть бесполезные геттеры и сеттеры, например, Eclipse может скрывать операторы «импорта». Но я не заметил IDE, которая делает это. Либо я не очень усердно смотрю... либо большинству программистов все равно, чтобы требовать, чтобы IDE реализовали это. - person Stephen C; 28.07.2009
comment
@nos ваш ответ показывает ТОЧНУЮ проблему с сеттерами и геттерами. Вы не запрашиваете у объекта данные, вы просите его оперировать своими данными. Таким образом, у вас может быть имя, но вы сделаете его окончательным и установите его в конструкторе, только если это вообще возможно (где вы можете легко манипулировать им перед установкой поля)... Вероятно, у вас не должно быть геттера, но они менее вопиющие... Но у вас может быть метод getPreferredEmail(), который вернет один из адресов электронной почты, которые он хранит, это не чистый геттер. Еще лучше может быть метод mailTo() в вашем объекте. - person Bill K; 29.07.2009

Вы не упускаете суть. Геттеры/сеттеры уродливы, но встроены во многие инструменты, которые делают предположения об именах классов/методов/полей (например, spring), что (помимо их очевидной ценности для инкапсуляции) они фактически стали почти обязательным требованием, если только вы не работает в очень ограниченном и частном контексте.

person Steve B.    schedule 27.07.2009
comment
Разве Spring теперь не предпочитает аннотации, потому что бобы отстой? Между прочим, сеттеры и геттеры противоположны инкапсуляции — они позволяют получить доступ к внутреннему состоянию, которое должно быть полностью скрыто. - person Bill K; 29.07.2009

«Геттеры» и «сеттеры» отлично подходят, если вы хотите переопределить доступ к своим данным, например, для ведения журнала/безопасности или возврата значения, отличного от исходного класса.

person Pierre    schedule 27.07.2009

без сеттера вы не можете проверить инварианты:

public void setFoo(Foo foo) { 
     if (foo == null) {
          throw new InvalidFoo();
     }

     this.foo = foo;
}

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

person dfa    schedule 27.07.2009
comment
Это был честный ответ... возражение! - person skaffman; 27.07.2009
comment
Согласен, к вопросу отношения не имеет. Заслуживает ли положительный ответ такой ответ, как «Вода мокрая»? Это на 100% правильная и очень полезная информация, но не совсем применимая к рассматриваемому вопросу. - person Bill K; 29.07.2009
comment
Кроме того, это анти-шаблон для инвариантов, было бы гораздо лучше сделать его окончательным и установить в конструкторе, чтобы вы точно знали, что его устанавливает даже не ваш собственный код. Это было бы весьма полезно, если бы вам абсолютно необходимо было использовать шаблон построителя, но если бы это было так, вы должны были бы вернуть это. - person Bill K; 29.07.2009
comment
анти-шаблон? вы не можете моделировать все объекты как неизменяемые - person dfa; 29.07.2009
comment
@Bill: однако ты прав, мой ответ не так хорош, как принятый - person dfa; 29.07.2009