Регистрируйте инварианты, в спящем режиме отображенные классы

Это номер раздела справочной страницы. Например,

,
 man printf
,

(следует). В секции 1, printf приведена команда bash, а в

 man 3 printf

- функция C printf.

.
10
задан Thomas Jung 26 October 2009 в 12:08
поделиться

3 ответа

Во-первых, позвольте мне обратиться к перечисленным вами "недостаткам" вашего первого подхода:

Вы начинаете реализацию кода, который зависит от клиента (Hibernate). В идеале класс не знает своего вызывающие абоненты.

Вы используете здесь слово "зависимость" немного быстро и небрежно. Hibernate не является «клиентом»; это фреймворк , который вы (как разработчик / архитектор / что у вас есть) выбрали для реализации своей персистентности. Следовательно, у вас будет где-то код, который использует (и, следовательно, зависит от) Hibernate. Тем не менее, нет НЕТ зависимости от Hibernate в вашем доменном объекте выше. Если хотите, наличие конструктора без аргументов является семантическим требованием; он не вводит фактической зависимости. Переключите режим гибернации на JPA / TopLink / raw jdbc / что у вас есть, и вам не придется ничего менять в коде объекта вашего домена.

Конкретная проблема с этим временным решением это случаи, инициированные hibernate не проверяются, если инварианты. Вы доверяете данным загружается из базы данных, которая проблематично. Даже если твой приложение - единственное, использующее это конкретная схема базы данных есть всегда возможность ad-hoc изменения, внесенные администраторами.

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

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

Все сказанное выше: если вы действительно хотите проверить свой объект, когда он загружен , этого достаточно просто сделать. Определите Valid интерфейс, который имеет метод validate () , и пусть каждый соответствующий объект домена реализует его. Вы можете вызвать этот метод из:

  1. вашего DAO / службы после загрузки объекта.
  2. Hibernate Interceptor или Listener - оба настроены в конфигурации Hibernate; все, что вам нужно сделать, это реализовать любой из них, чтобы проверить, реализует ли загружаемый объект Valid , и, если да, вызвать метод.
  3. Или вы можете использовать Hibernate Validator , однако это БУДЕТ привязывать объекты вашего домена к Hibernate, как вы бы аннотировали их.

Наконец, что касается «внедрения конструктора» - я не знать любую структуру, которая поддерживает его напрямую . Причина этого довольно проста - это имеет смысл только для неизменяемых сущностей (потому что, если у вас есть сеттеры, вам все равно придется иметь дело с проверкой), и, таким образом, требует много работы (обработка сопоставлений параметров конструктора и т. Д. ..) с почти нулевым чистым эффектом. Фактически, если вы , который озабочен наличием конструктора без аргументов для неизменяемых объектов, вы всегда можете не отображать их как сущности и вместо этого загружать их через HQL, который поддерживает ] внедрение конструктора :

select new A(x, y) from ...

Обновление (чтобы ответить на вопросы из комментариев Томаса):

  1. Я упомянул перехватчик только для полноты; listener в этом случае более уместен. PostLoadEventListener вызывается после полной инициализации объекта.
  2. Еще раз, наличие конструктора без аргументов не является зависимостью. Да, это контракт, но он никоим образом не связывает ваш код с Hibernate. Что касается контрактов, то это часть спецификации javabean (на самом деле, она менее строгая, потому что конструктор не обязательно должен быть публичным), поэтому в большинстве случаев вы все равно будете следовать ему.
  3. Доступ к базе данных. «Рефакторинг базы данных и миграции - обычное дело» - да, это так. Но это всего лишь код; вы пишете его, тестируете, запускаете интеграционные тесты, развертываете его в производственной среде. Если ваш объект модели предметной области использует какой-то метод StringUtil.compare () , который вы написали в каком-то служебном классе, вам не нужно, чтобы он повторно проверял результаты, не так ли? Точно так же объекту домена не нужно проверять, что ваш сценарий миграции ничего не сломал - у вас должны быть соответствующие тесты для этого. «Возможность делать специальные запросы ... это одна из особенностей» - безусловно. Запросы . Как и в запросах «только для чтения», используемых, например, для отчетов (даже в этом случае во многих случаях более целесообразно использовать API). Но ручная обработка данных как неаварийная - абсолютно нет.
  4. Изменчивость делает внедрение конструктора несущественным . Я не говорю, что у вас не может быть конструктора не по умолчанию - вы можете, и вы можете использовать его в своем коде. Но если у вас есть методы установки, вы не можете использовать свой конструктор для проверки, так что, есть он или нет, на самом деле не имеет значения.
  5. Внедрение конструктора HQL и ассоциации. Вложенные конструкторы не будут работать, насколько я знаю (например, вы не можете написать select new A (x, y, new B (c, d)) ; так что по порядку чтобы получить ассоциации, вам нужно будет получить их как объекты в предложении select, что означает, что у них должны быть сами конструкторы без аргументов :-) Или вы можете иметь конструктор на «основном» объекте, который принимает все необходимые вложенные свойства в качестве аргументов и создает / заполняет ассоциации внутренне, но это граничит с безумием: -)
5
ответ дан 4 December 2019 в 01:31
поделиться

Один из подходов будет основан на вашем «классе I», но с самим классом, вызывающим checkInvariants () при первом фактическом использовании полей. Это позволяет полям быть временно недействительными во время присваивания (например, после вызова setX (), но перед setY ()). Но он по-прежнему гарантирует, что когда-либо используются только действительные данные.

Ваш примерный класс никогда не использует значения, поэтому я предполагаю, что к значениям можно получить доступ через getX (), getY () и doSomething (), например:

public int getX(){ 
    return x; 
} 

public int getY(){ 
    return y; 
} 

public void doSomething(){
    x = x + y;
}

Вы бы изменили его следующим образом:

private boolean validated = false;

public int getX(){ 
    if (!validated) {
        checkInvariants();
    }

    return x; 
} 

public int getY(){ 
    if (!validated) {
        checkInvariants();
    }
    return y; 
} 

public void doSomething(){
    if (!validated) {
        checkInvariants();
    }
    x = x + y;
}

public void checkInvariants() { 
    validated = true;
    if (x + y « 0) throw new IllegalArgumentException(); 
}

Вы можете переместить if (! Validated) в checkInvariants (), если хотите.

Вы также можете изучить Hibernate Validator, хотя он может не соответствовать вашей структуре -требование независимости. http://docs.huihoo.com/hibernate/annotations-reference-3.2.1/validator. html

2
ответ дан 4 December 2019 в 01:31
поделиться

Согласованность реляционной модели критически важная концепция ахать. Из-за присущего математическая устойчивость принципы, лежащие в основе данных отношений моделирование, мы можем быть полностью уверены что результат любого запроса нашего исходная база данных действительно сгенерирует Фактически достоверные факты. - Из книги Искусство Sql - Стефан Фарут

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

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

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

В любом случае, если у вас есть искаженные данные или ложные утверждения в своей базе данных, чему еще вы можете доверять?

3
ответ дан 4 December 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: