Являются ли Java Beans как классы хранения данных плохим дизайном?

Обычно JavaPractices.com - хороший сайт с хорошей идеей, но это меня беспокоит: JavaBeans - это плохо.

В статье приводятся несколько причин, главным образом, что термин JavaBean означает, что "Java Bean является многократно используемым программным компонентом, который можно визуально манипулировать инструментом builder". а не хранение данных, нарушает определенные шаблоны и является более сложным.

Теперь я могу согласиться с последним, но в моих глазах JavaBeans в списке имеет гораздо больше смысла, чем вложенные Карты. В статье утверждается, что рамки отображения базы данных должны вызывать конструкторы, а не устанавливать * методы, и объект должен быть неизменным. Однако, на мой взгляд, вызов методов set * при попытке создания объекта легче читать, чем new MappedObject("column1", "column2", "yet another column", "this is stupid");

Я также использую класс стиля JavaBean для других вещей, помимо сопоставления базы данных, например, для IRC-бота, имеющего объект для каждого пользователя, который обновляется различными вещами. Я не хочу создавать новый объект каждый раз, когда предоставляется новая информация, я хочу добавить его в существующий.

Итак, мой вопрос: использует ли JavaBeans для хранения данных плохую практику и ее следует избегать или это абсолютно безопасно?

Ответ 1

Кажется, что вы неправильно читаете текст.

Теперь я могу согласиться с последним, но на мой взгляд, JavaBeans в списке делает гораздо больше смысла, чем вложенные Карты

Текст никогда не упоминает вложенные карты в качестве альтернативы (yiack)

... должен вызывать конструкторы, а не устанавливать * методы, и объект должен быть неизменным

Это хорошая практика, особенно полезная при работе с потоками.

Но мы не можем сказать, что использование seters - это baaad, особенно когда один поток использует этот объект. Это совершенно безопасно.

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

Это прекрасно, если вы контролируете объект, нет проблем с этим, другим может быть проще просто создать новый объект.

Использует ли JavaBeans для хранения данных плохую практику и ее следует избегать или это абсолютно безопасно?

Нет, это не плохая практика. Не совсем безопасно. Зависит от ситуации.

Проблема с изменяемыми объектами (а не с JavaBeans per se) использует разные потоки для доступа к ним.

Вам необходимо синхронизировать доступ, чтобы один поток не изменял объект, а другой - к нему.

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

Чтобы гарантировать неизменность объекта, вы должны объявить свои атрибуты окончательными.

class MyBean  {
    private final int i;
}

Если вы хотите назначить разумное значение MyBean.i, вы должны указать его в конструкторе:

 public MyBean( int i ) {
     this.i = i;
 }

Поскольку переменная является окончательной, вы не можете использовать setter. Вы можете просто предоставить геттер.

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

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

Если в будущем вам придется иметь дело с приложениями с несколькими потоками, вы можете использовать неизменяемый JavaBean;)

BTW, альтернатива созданию неизменяемого beans и по-прежнему предоставляющая набор настроек, использует Builders как:

 Employee e = new EmployeeBuilder()
                  .setName("Oscar")
                  .setLastName("Reyes")
                  .setAge(0x1F)
                  .setEmployeeId("123forme")
                  .build(); 

Что выглядит довольно похоже на обычный setXyz, используемый в регулярном beans, с использованием неизменяемых данных.

Если вам нужно изменить одно значение, вы можете использовать метод класса:

 Employee e = Employee.withName( e, "Mr. Oscar");

Что берет существующий объект и копирует все значения, и устанавливает новый....

 public static EmployeeWithName( Employee e , String newName ){
      return new Employee( newName, e.lastName, e.age, e.employeeId );
  }

Но опять же, в одной модели нити совершенно безопасно использовать геттеры/сеттеры.

PS Я настоятельно рекомендую вам купить эту книгу: Эффективная Java. Вы никогда не пожалеете об этом, и у вас будет информация, чтобы судить о лучших статьях, подобных цитируемым.

Ответ 2

Мое возражение против использования JavaBeans в качестве классов хранения данных заключается в том, что они позволяют объектам с несогласованным состоянием. В типичном примере использования для такого beans вы выполняете следующие действия:

  • создать экземпляр класса;
  • установить первое свойство;
  • установить второе свойство;
  • ...
  • установить конечное свойство;
  • используйте экземпляр объекта.

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

  • (Дополнительно: настройка объекта параметров);
  • создать экземпляр класса;
  • используйте экземпляр объекта.

Ни в коем случае в этом потоке работы я не могу случайно начать использовать объект с несогласованным состоянием. Если я использую объект параметров, он не используется напрямую ни для чего, и его содержимое будет проверено при создании экземпляра моего основного класса. Сам основной класс, вернувшись из экземпляра, даст мне экземпляр объекта, который будет немедленно использован.

Такая настройка лучше всего подходит для более простых объектов, конечно. Для более сложных объектов с такими вещами, как дополнительные свойства и т.д., Вы захотите сделать шаг дальше и использовать что-то вроде шаблона Builder, к которому другие указали вас. Строителям приятно, когда у вас более сложные сценарии, IMO, но для более простой и более простой параметризации просто использовать аргументы конструктора или объект параметров какого-то типа более чем достаточно.

Ответ 3

"Шаблон JavaBeans имеет серьезные недостатки". — Джошуа Блох, Эффективная Java

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

Кстати, упомянутая книга (Эффективная Java) имеет обширное обсуждение как этих моделей, их преимуществ, недостатков и альтернатив. Вы можете проверить это. Но в JavaBeans нет ничего неправильного, просто иногда это не лучший выбор.

Изменить: См. пункт 2 ( "Рассмотрите построителя, столкнувшись со многими параметрами конструктора" ) в "Эффективной Java" в Google Книгах: http://books.google.com/books?id=ka2VUBqHiWkC&lpg=PP1&pg=PA11#v=onepage&q&f=false

Ответ 4

Основная причина избегания сеттеров - неизменность. Код для неизменности впереди, и вы избегаете проблем с потоками вокруг этих объектов.

Если вы закончите конструктор, который читает

new Person ( "param 1", "param 2", "param 3", "param 4", "param 5", "param 6", "param 7", "param 8" )

то ваш объект слишком сложный. Вам понадобятся объекты параметров (см. Книгу рефакторинга Мартина Фаулера).

Защищайте код в начале и люди, которые приходят и поддерживают ваш код, будут либо благодарны вам (хорошо), либо проклинают вас (потому что они не могут лениться и просто мутировать объекты).

Когда вам нужно изменить объект, добавьте конструктор копирования (т.е. метод клона). Современные JVM справляются с этим легко и быстро, и есть небольшое ограничение скорости. Вы также облегчаете работу в Hotspot и GC.

Ответ 5

Его совершенно безопасный и гораздо более предпочтительный, чем бесконечно вложенный java.util.Map. Вы получаете безопасность типов, проще понимать код и избегать того, чтобы ваш код заканчивался в Daily WTF. Обратите внимание, что реализация должна быть разделена - не смешивайте слишком много логики (помимо простой проверки) в своих классах хранения данных. Вы должны прочитать о POJOs

Ответ 6

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

Сеттеры - это лучшая вещь, а не "чистая" OO, но огромное удобство над конструкторами и хорошо работает на практике.

Тесты Whem начинают сбой из-за "плохого" java beans, тогда я передумаю, что это вызывает беспокойство. Но пока я этого не видел. Единственный раз, когда я скажу, что они, вероятно, неприемлемы, - это общий beans в многопоточном коде, поскольку синхронизация общего измененного состояния сложна. Уберите это и beans просто отлично.