2015-04-14 1 views
15

Предположим, у нас есть десятки java POJO, которые представляют мой домен, то есть мои данные в системе, которые текут как объекты между разными слоями моей системы. Системой может быть веб-приложение или простое настольное приложение. То, из чего состоит домен, на самом деле не имеет значения.Должен ли Java POJO проверять поле и исключать исключения в методах setter?

При проектировании моей системы я смущен, где я должен поместить любую логику проверки. Мои POJO (объекты домена) представляют мои данные, а некоторые из полей внутри этих объектов должны придерживаться определенных критериев, но если я положу много логики проверки внутри своих методов setter, тогда единственный способ рассказать вызывающему клиенту - выбросить исключение. И если я не хочу, чтобы система выходила из строя, исключение должно быть проверенным исключением, которое необходимо поймать и обработать. Следствием этого является то, что каждый раз, когда я создаю новый объект с помощью setter-методов (или даже конструкторов), я делаю либо повторное бросить это исключение, либо использовать блок try-catch. Он не чувствует себя хорошо, если вы будете вынуждены использовать try-catch на многих методах setter.

Итак, вопрос заключается в том, где я должен поставить свою логику проверки, чтобы я не загромождал свой код с большим количеством блоков шаблонов try-catch и rethrows. Лучшие участники JAVA-байтов могут присоединиться к обсуждению.

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

+0

Вы проверили проверку Java bean http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html? –

+0

Попробуйте использовать проверку бина ([JSR-303] (http://beanvalidation.org/1.0/spec/)), как реализовано ['hibernate-validator'] (http://hibernate.org/validator/) – beerbajay

+0

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

ответ

13

Вы можете сами ответили на свой вопрос, когда вы сказали

некоторые поля внутри этих объектов должны придерживаться определенных критериев

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

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

Со временем я начал бесконтрольно в пользу исключения более проверяемых единиц для любых случаев нарушения контракта, частично по причине, вы упомянули, а именно, чтобы избежать try - catch блоков везде.стандартные непроверенные исключения
Java включают в себя:

  • NullPointerException
  • IllegalArgumentException
  • IllegalStateException
  • UnsupportedOperationException

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

Глава 9 из Джошуа Блоха «Effective Java, 2nd ed.» дает больше мудрости по этой теме:

  • Пункт 57: Используйте исключения только для исключительных условий
  • Пункт 58: Использование проверяемых исключений для извлекаемых условий и исключений выполнения для ошибки программирования
  • Пункт 59: Избегайте использования проверяемых исключений
  • Пункт 60: Фавор использование стандартных исключений

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

+0

Да, POJO всегда должен находиться в правильном состоянии. Я просмотрел элементы из Эффективной Java, но их немного сложно понять, я думаю, что они, конечно же, будут трудны для промежуточного уровня, который знает принципы OO-дизайна, но не может правильно решить, как применять эти элементы. Например, я не понимаю, что он конкретно подразумевает при помощи «восстанавливаемых» и «ошибок программирования». Некоторые конкретные и, возможно, разные примеры могут помочь понять мощные идеи этих предложений. Что он подразумевает под «ненужным», есть ли у нас какие-либо известные примеры этого. – Moni

+0

Я согласен с тем, что Блоху требуется тщательное прочтение, и ваши проблемы были бы великими вопросами SO самостоятельно. Ошибка _programming_ является нарушением контракта, например. передавая «null» или отрицательный индекс, когда документировано, что это не поддерживается.Примером ошибки _recoverable_ может быть что-то вроде таймаута, когда вызывающий может решить повторить попытку позже или просто отказаться; используя исключение _checked_, заставляет вызывающего пользователя справиться с этим и принять решение. Использование исключенных исключений для управления потоком вместо блоков IF-ELSE является примером использования _unnecessary_. – fspinnenhirn

3

В целом, я также не думаю, что есть уникальное решение, соответствующее каждой потребности, и это просто сводится к вашему сценарию и предпочтениям.

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

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

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

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

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

+0

Согласен с шаблоном Builder (+1), это сразу то, о чем я думал при чтении вопроса. –

1

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

1

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

Использование проверки компонентов в порядке, но во многих случаях (к которым я уверен, что вы сейчас сталкиваетесь) простая аннотация не проведет достаточно тщательную проверку. Рамки вроде Spring имеют Validator, которые вы можете реализовать для этого.

Есть множество преимуществ для разделения логики проверки:

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

Надеюсь, что это поможет.

+0

Некоторые существенные моменты, которые вы делаете здесь, специально регистрируете, читаете и разделяете проблемы. Можете ли вы приготовить действительно «глубокий» и реалистичный пример, который немного прояснит дым? – Moni

+0

Если вам почему-то нужен более конкретный пример, я могу предоставить его позже, но этого должно быть достаточно: http://www.journaldev.com/2668/spring-mvc-form-validation-example-using-annotation-and-custom- валидатор-реализация. Как вы можете видеть, в методах setter нет проверки. Этот дизайн использовался долгое время и в производственных условиях. В случае, если ссылка будет разбита позже, Google использует, например, использование Spring Validator, что даст вам больше дел. – bphilipnyc