Я всегда применял ограничения на уровне базы данных в дополнение к моим (ActiveRecord) моделям. Но мне было интересно, действительно ли это требуется?
Немного фона
Недавно мне пришлось провести модульное тестирование базового метода автоматической генерации меток времени для модели. Обычно тест создает экземпляр модели и сохраняет его без проверки. Но есть и другие обязательные поля, которые нельзя обнулять в определении таблицы, то есть я не могу сохранить экземпляр, даже если пропущу проверку ActiveRecord. Поэтому я думаю, стоит ли мне удалять такие ограничения из самой базы данных и позволить ORM их обрабатывать?
Возможные преимущества, если я пропущу ограничения в db, imo -
- Может изменить правило проверки в модели без необходимости переноса базы данных.
- Может пропустить проверку в тестировании.
Возможный недостаток?
Если возможно, что проверка ORM окажется неудачной или будет обойдена, база данных не проверяет наличие ограничений.
Как вы думаете?
РЕДАКТИРОВАТЬ В этом случае я использую Yii Framework , который генерирует модель из базы данных, следовательно, правила базы данных также генерируются (хотя я всегда мог написать их и сам после генерации).
источник
Ответы:
Ваш руководящий принцип должен звучать так: « Не повторяй себя» :
ORM - это, по сути, дополнительный уровень (или уровень, если вы предпочитаете), удобно расположенный между вашим приложением и хранилищем данных. Ваши ограничения должны быть в одном месте и только в одном месте, будь то ORM или хранилище данных, в противном случае достаточно скоро вы будете поддерживать разные их версии. Вы действительно не хотите этого делать.
Однако на практике большинство полуприличных ORM автоматически генерируют большую часть ваших моделей из вашей схемы данных. Хотя дублирование все еще существует, шансы на адское обслуживание минимальны, поскольку дублированный код ORM генерируется по одному и тому же шаблону каждый раз. Было бы идеально, если бы не было дублирующегося кода, но автоматически генерируемые ограничения - это следующая лучшая вещь.
Кроме того, наличие ограничений в одном месте не обязательно означает, что все ограничения должны быть в одном месте. Некоторые, такие как ограничения ссылочной целостности, могут быть более подходящими для хранения данных (но могут быть потеряны при переходе на другое хранилище данных), а некоторые, в основном те, которые касаются сложной бизнес-логики, больше подходят для вашего ORM. Было бы предпочтительнее иметь все свои яблоки в одной корзине, но ...
Отказы
Вы упоминаете, что ORM не работает. Это абсолютно не имеет отношения к вашему вопросу, ваше приложение должно воспринимать ORM и хранилище данных как единое целое. В случае сбоя произошел сбой, поэтому обходить ORM для непосредственного общения с хранилищем данных не очень хорошая идея.
В обход ORM для всего остального
Также не очень хорошая идея. Однако это может произойти по разным причинам:
Устаревшие части приложения, созданные до появления ORM.
Это жесткая один, и именно в такой ситуации я имею дело с прямо сейчас , поэтому моим постоянным повтором «поддерживающей ад». Либо вы продолжаете поддерживать части, отличные от ORM, либо переписываете их для использования ORM. Второй вариант может иметь больше смысла на начальном этапе, но это решение, основанное исключительно на том, что именно делают эти части вашего приложения, и насколько ценной будет полная перезапись в долгосрочной перспективе.
Попробуйте изменить ключ в плохо спроектированной таблице MySQL с 2 * 10 ^ 8 строками (без простоя), и вы поймете, откуда я.
Не унаследованные части приложения, которым абсолютно необходимо напрямую общаться с хранилищем данных:
Еще сложнее. ORM - это модные инструменты, и они заботятся почти обо всем, но иногда они просто мешают или даже абсолютно бесполезны. Модное слово (действительно, модная фраза) - это несоответствие объектно-реляционного импеданса , попросту говоря, технически ORM не может делать все, что делает ваша реляционная база данных, а для некоторых вещей, которые они делают, существует значительное снижение производительности.
Комментарии
Вот где добавление дополнительного слоя было бы чрезвычайно полезно, и если мы говорим о веб-приложении, я бы пошел с REST API. Чрезмерно упрощенный дизайн для этого было бы:
ORM будет находиться между API и хранилищами данных, и все, что находится за API (включая его), будет рассматриваться как единое целое из различных приложений.
источник
На самом деле это очень сложный вопрос, и я считаю его очень спорным вопросом.
Как отметил в своем ответе Яннис Ризос, имея логику ограничений как в базе данных, так и на уровне ORM , по-видимому, нарушает DRY, что «может привести к кошмарам обслуживания, плохому факторингу и логическим противоречиям».
Однако удаление логики ограничений из базы данных и сохранение ее только на уровне ORM не будет работать, если у вас есть любое из следующих условий:
Ручные обновления БД (они, кажется, происходят в каждой компании)
Обновления БД из другой системы, которая не всегда может легко совместно использовать логику ограничения ORM (например, скрипт Perl, который выполняет рутинные задачи, когда уровень ORM реализован в Hibernate и используется приложением Java для повседневной деятельности)
Это предполагает, что вы только добавляете логику ограничения в БД и удаляете ее из уровня ORM , чтобы предотвратить нарушение DRY. Однако это может привести к случаям, когда код приложения не сможет успешно перехватить реальную проблему и передать ее пользователю (хотя, как разработчик, скорее всего, отладит проблему). Это может быть неприемлемо для некоторых проектов.
Последний вариант - автоматизировать создание ограничений в ORM (и любой другой системе) из ограничений БД (или, на самом деле ... наоборот). Хотя в конечном итоге вы получите две или более реализации ограничений, это не будет нарушением принципа DRY, как описано в «Прагматичном программисте», поскольку они рекомендуют использовать генерацию кода, чтобы избежать нарушений DRY. Конечно, это не так просто, потому что, например, каждое изменение в ограничении БД может привести к повторной сборке и повторному развертыванию всех ваших приложений, которые его используют (не просто для автоматизации).
Действительно, это должно быть оценено в каждом конкретном случае . Я могу сказать вам, что до этого момента меня встречали пустые взгляды, когда я предлагаю, чтобы логика ограничений не повторялась.
источник
Я бы определенно добавил ограничения в базу данных в качестве варианта по умолчанию. Это связано с тем, что для предприятия важны данные, а качество данных имеет первостепенное значение. @ Яннис Ризос привнес принцип СУХОГО в обсуждение. Ну, другой принцип - защита в глубине. Для данных я бы использовал этот принцип.
Я работал на реальных предприятиях, где БД имеет данные, созданные 30 лет назад. Это было и до сих пор доступно приложению COBOL, а теперь - приложению .Net. Через 10 лет это может быть приложение поставщика, кто знает. Произошло слияние, и миллионы строк данных были преобразованы и перенесены из другой компании в эту базу данных с использованием SQL. Ни один ORM не может сделать это. Суть в том, что данные остаются, приложения меняются, изменяются способы генерирования данных. Так почему бы не уменьшить вероятность повреждения данных?
источник
Я думаю, что вы делаете оба в некоторой степени.
Основные ограничения должны существовать в ORM - языки программирования гораздо более гибкие, их легче тестировать и легче настраивать при изменении требований; не нужно беспокоиться об исправлениях DDL по крайней мере. И вы, как правило, избегаете проблем с регрессией данных.
Некоторые очень жесткие и быстрые ограничения должны также существовать в базе данных. Я не говорю о ненулевых именах, например. Я говорю о вещах, таких как ссылочная целостность или требующих некоторых абсолютно важных идентификаторов. Структурные требования, поэтому вашему коду не нужно иметь дело с «что, если в Ордене нет несуществующего продукта».
источник
База данных является IMO единственным местом, где DRY может быть нарушен, потому что, если что-то обходит ваш ORM и содержит неверные данные, это все. Игра закончена. Повреждение данных - смертельный удар.
источник