2010-06-25 2 views
10

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

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

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

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

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

+10

JavaBeans не столько представляет собой шаблон в целом, как анти-шаблонный язык. –

+3

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

+6

Рассмотрите возможность изучения шаблона Builder. http://en.wikipedia.org/wiki/Builder_pattern. – CoolBeans

ответ

19

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class MyBean { 
    private final int i; 
} 

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

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

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

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

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

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

Кстати, альтернатива для создания неизменных бобов, и по-прежнему обеспечивает кучу сеттеров используют Builders как :

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

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

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

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 Я настоятельно рекомендую вам купить эту книгу: Effective Java. Вы никогда не пожалеете об этом, и у вас будет информация, чтобы судить о лучших статьях, как цитируется.

+0

+1 для хорошего контента. Я говорил о вложенных картах, потому что я использую beans для других вещей, кроме строк базы данных, IE, изменяющих объекты пользователя. Однако, поскольку оба они развиваются, я не уверен в неизменном маршруте, хотя у него есть преимущества, лучше здесь, потому что, если бы я хотел изменить объект, у меня все еще есть проблемы синхронизации + попытка заменить существующий объект. – TheLQ

+0

@ Lord.Quackstar Да, но большую часть времени один поток достаточно хорош, а Java-бобы - это не плохой шаблон или что-то еще. Это просто альтернатива. – OscarRyz

+0

То, что вы могли бы также рассмотреть, было бы иметь метод toBuilder для любого данного компонента, чтобы вы могли превратить любой компонент в строитель, установить некоторые поля и затем перестроить объект как новый объект. Таким образом, вы можете сделать employee = employee.toBuilder(). SetName («Mary Poppins»). Build(); и это даст вам некоторую полуизменяемость. –

0

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

3

"Узор JavaBeans имеет серьезные недостатки." — Джошуа Блох, Effective Java

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

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

Edit: смотри пункт 2 («Считай строитель, когда сталкиваются со многими параметрами конструктора») в Effective Java на Google Books: http://books.google.com/books?id=ka2VUBqHiWkC&lpg=PP1&pg=PA11#v=onepage&q&f=false

+0

Я согласен с тем, что аргументы в статье очень слабы, основанные на цитатах, взятых из контекста, и статья не предлагает альтернативы, которая явно лучше. Другими словами, @ Lord.Quackstar: не верьте чему-либо, что вы читаете в случайной статье в Интернете по номинальной стоимости. – Jesper

0

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

Сеттеры - лучшее, что лучше всего - не как «чистое» ОО, а огромное удобство над конструкторами и хорошо работает на практике.

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

+0

Что вы считаете «плохой фасолью java»? – TheLQ

+0

«Плохо» было моим юмором названия статьи - я не думаю, что они являются внутренне плохими, но, как и все шаблоны, их можно злоупотреблять, чтобы стать анти-образцом. Возможно, в некоторых случаях бобы могут вызывать ненужную развязку между поведением и данными или когда привычный однопользовательский геттер/сеттер лучше будет делать как более богатое вычисление. И если только свойства были концепцией первого класса, тогда мы могли бы построить шаблон без необходимости в строках (именах свойств) и отражении ... – mdma

+0

«Между созданием экземпляра класса и установкой конечного свойства у вас есть объект, который находится внутри «непостоянное или непригодное состояние», http://stackoverflow.com/a/3122912/262852, это проблема в двух словах. – Thufir

2

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

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

нового Person ("PARAM 1", "пары 2", "пары 3", "пары 4", "пары 5", "пары 6", «param 7», «param 8»)

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

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

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

5

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

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

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

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

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

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

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