Следует ли применять ограничения на уровне базы данных, а также на уровне приложений? - PullRequest
46 голосов
/ 21 января 2009

Я читал книгу «Enterprise Rails» Дэна Чака, и это заставило меня задуматься: считаете ли вы, что у вас должны быть ограничения данных как на уровне базы данных, так и на уровне приложения? Или вы чувствуете себя аналогично самоуверенным фреймворкам, таким как Ruby on Rails - база данных является просто «тупым хранилищем» данных, и все проверки должны выполняться в вашем приложении (я не пытаюсь выделить здесь RoR - я Огромный фанат Rails сам, но я не согласен с его подходом к базе данных)?

Лично я чувствую, что вы должны иметь их обоих, чтобы убедиться, что ваша база данных и приложение хорошо защищены. Я имею в виду, что вы должны использовать ненулевые ограничения, дать вашим полям длину, если она известна (вместо того, чтобы оставлять их все в nvarchar (255) ), иметь такие вещи, как Foreign Ключи , Проверяют ограничения и Триггеры в вашей базе данных, а затем применяют это с помощью правил бизнес-логики в вашем приложении. IMO это делает ваше приложение надежным через его пользовательский интерфейс, а также защищает от кого-то, кто может иметь прямой доступ к базе данных.

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

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

Я, например, не вижу в этом ничего плохого - да, у вас есть некоторая дублирующая логика, но конечным результатом является мышление «база данных как крепость», поскольку, если вы подумаете об этом, ваши данные - это самая важная часть ваше приложение; В конце концов, что хорошего в вашем новом блестящем приложении Web 2.0, если данные могут быть легко повреждены и скомпрометированы?

Что вы думаете об этом? Должна ли база данных быть неприступной крепостью, такой как Форт Нокс, или открытым сейфом, который охраняют лазеры? Другими словами, следует ли вам пожертвовать некоторым дублированием логики для обеспечения безопасной модели данных или оставить все для вашего приложения и использовать базу данных просто для хранения данных?

Ответы [ 15 ]

33 голосов
/ 21 января 2009

Вкратце: база данных должна применять ограничения.

Почему:

  1. Проще. Например чтобы установить ограничение для определенного столбца данных, есть только одно место для его установки: сам столбец. Данные могут поступать из разных источников, но проверка ставится там, где данные окончательно помещаются в состояние покоя.
  2. Целостность. База данных должна отвечать за данные, которые она хранит. Несогласованная база данных так же хороша, как и база данных.
  3. Гибкость. Новые среды разработки пользовательского интерфейса появляются слишком часто. Если база данных протянет руку, чтобы сказать, что она позаботится об ограничениях, разработка внешнего интерфейса и функциональное тестирование станут проще.
21 голосов
/ 21 января 2009

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

Нет никакой гарантии, что ошибочный (или вредоносный) слой «бизнес-логики» не вставит токсичные данные в ваши таблицы. Конечно, если вы можете доверять другим слоям, вам, вероятно, это не понадобится. Но я работаю в магазине мэйнфреймов, где администраторам баз данных всегда приходится исправлять проблемы, вызванные молодыми программистами Java, которые выкладывают свой ошибочный код в производство без адекватного (какого-либо?) Тестирования: -).

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

19 голосов
/ 21 января 2009

Если вы следуете школе Джеффа Этвуда, база данных - это просто тупая система хранения и поиска данных, тогда вы положите всю проверку на прикладной уровень.

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

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

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

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

  2. Если вы выполняете операции CRUD в представлении. Триггеры обязательны для операций вставки / обновления / удаления.

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

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

Джефф Этвудс этого мира предложил бы вам написать веб-сервис, с которым все приложения используют для связи. Веб-сервис выполняет проверку данных. Это позволяет базе данных оставаться тупым контейнером хранения, что позволяет вам переключать ядра базы данных. В действительности вы редко меняете движки баз данных (если только вы не начали с Microsoft Access!). Если вы пишете веб-сервисы исключительно для централизации проверки ваших данных, то, я думаю, вы идете за борт.

16 голосов
/ 21 января 2009

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

Кроме того, используя базу данных в качестве «тупого хранилища», вы, скорее всего, получите менее эффективное приложение. База данных может делать много вещей намного эффективнее, чем ваше приложение. Почему бы не воспользоваться этим?

8 голосов
/ 21 января 2009

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

дб

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

Вы не можете делать все в БД, но вы можете сделать многое. Защитите данные.

бизнес-уровень

Поднимая уровень, у вас есть бизнес-логика. Обычно это ваша точка интеграции с другими приложениями (веб-сервис, ваш собственный интерфейс и т. Д.). Здесь бизнес-логика закодирована в приложении. Такие вещи, как если продукт имеет конечную дату x, то это не может также произойти в y, если у y другая конечная дата.

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

также трудно выразить в базе данных другие «правила», например, «у новых пользователей срок годности 1 год, если они из Арканзаса, в противном случае - 2 года, если у них нет 3 детей и один из них называется Барри». Мы можем смеяться над этим примером, но опытный программист скажет вам, что бизнес-логика - один из самых больших оксюморонов вокруг.

щ

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

Пользовательский интерфейс знает, что нужно искать товары с помощью X, если пользователь уже выбрал виджет Y. Пользовательский интерфейс знает, что описание требуется, и что количество элементов> 0 и <100 (В этих примерах хороший пользовательский интерфейс будет полагаться на бизнес-уровень, чтобы сообщить ему, например, минимальное и максимальное значения, но пользовательский интерфейс все еще осведомлен отношений) </p>

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


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

8 голосов
/ 21 января 2009

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

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

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

3 голосов
/ 21 января 2009

Если вы не обеспечите хотя бы базовую целостность базы данных, в какой-то момент появятся недействительные данные. Возможно, из приложения. ошибка, может быть от кого-то подтягивая консоль SQL, что угодно. И затем вы обнаруживаете, что в вашем приложении есть интересные режимы сбоев, когда происходит невозможное («все записи B должны иметь запись A! Что вы имеете в виду, что оно не существует?»).

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

2 голосов
/ 21 января 2009

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

Прежде всего, за прошедшие годы я перешел от 100% убежденности в реализации ограничений в СУБД к попыткам их полностью избежать: я хочу, чтобы вся моя бизнес-логика была на одном уровне.

Во-вторых, я много работаю с миграциями Rails и ActiveRecord, которые не допускают большого определения резидентного db, кроме размера поля и NULL_ness.

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

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

Если вы создаете новое приложение / базу данных в расчете на то, что другие приложения получат доступ к данным, тогда подход будет зависеть от того, как будут создаваться эти другие приложения. Опять же, в Rails вы, вероятно, должны искать способы поделиться своими моделями, и в этом случае этого уровня должно быть достаточно. Если вы не можете отказать другим стилям реализации в прямом доступе к вашим данным, тогда вы вернулись к дублированию. Я предпочел бы - очень стараюсь - запретить прямой доступ БД к этим приложениям и стремиться обслуживать их через (надеюсь, RESTful) веб-службу, чтобы вы могли управлять целостностью данных на уровне бизнес-логики.

Если стороннее (внутреннее или иное) приложение имеет DDL-доступ к вашей схеме, то перестаньте беспокоиться о проблеме - вы уже потеряли контроль над своими данными, и вы облажались!

1 голос
/ 21 января 2009

Да для обоих. Я узнал об этом в моем последнем месте. У нас были устаревшие системы Delphi с базами данных Sybase. Новая система была .NET и Sql server. Один конкретный сотрудник отвечал за перевод базы данных sybase в базу данных sql server для клиентов, которым требовалось обновление до новой системы .NET. Он никогда не работал с кодом приложения .NET и, следовательно, никогда не видел ограничений данных на уровне приложения.

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

1 голос
/ 21 января 2009

С точки зрения ООП, база данных, как в объекте / субъекте, в более крупной системе, и она должна отвечать за себя. Это включает в себя необходимость проверки ввода.

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