Прежде чем ответить на вопрос, я думаю, что некоторые фон в порядке.
Суть проблемы
После нескольких лет интервьюирования и найма разработчиков я узнал две вещи:
Подавляющее большинство разработчиков имеют очень небольшой опыт проектирования баз данных.
Я заметил слабую корреляцию между теми, кто не понимает базы данных, и теми, кто ненавидит ORM.
(Примечание: и да, я знаю, что есть те, кто очень хорошо разбирается в базах данных и ненавидят ORM)
Когда люди не понимают , почему внешние ключи важны, почему вы не встраивать имя производителя в item
таблице, или почему customer.address1
, customer.address2
и customer.address3
поля не является хорошей идеей, добавив ОРМ , чтобы сделать его проще для них ошибок базы данных записи ничем не поможет
Вместо этого, с правильно разработанной базой данных и сценарием использования OLTP, ORM являются золотыми. Большая часть основной работы уходит, и с помощью таких инструментов, как DBIx :: Class :: Schema :: Loader , я могу перейти от хорошей схемы базы данных к работе с кодом Perl за считанные минуты. Я бы сослался на правило Парето и сказал, что 80% моих проблем были решены с помощью 20% работы, но на самом деле я считаю, что выгоды даже больше, чем это.
Злоупотребление решением
Другая причина, по которой некоторые люди ненавидят ORM, заключается в том, что они пропускают абстракцию. Давайте рассмотрим общий случай веб-приложений MVC. Вот что мы обычно видим (псевдокод):
GET '/countries/offices/$company' => sub {
my ( $app, $company_slug ) = @_;
my $company = $app->model('Company')->find({ slug => $company_slug })
or $app->redirect('/');
my $countries = $app->model('Countries')->search(
{
'company.company_id' => $company->company_id,
},
{
join => [ offices => 'company' ],
order_by => 'me.name',
},
);
$app->stash({
company => $company,
countries => $country,
});
}
Люди пишут такие маршруты контроллеров и похлопывают себя по спине, думая, что это хороший, чистый код. Они были бы ошеломлены жестким кодированием SQL в своих контроллерах, но они сделали чуть больше, чем выставили другой синтаксис SQL. Их код ORM должен быть помещен в модель, и тогда они могут сделать это:
GET '/countries/offices/$company' => sub {
my ( $app, $company_slug ) = @_;
my $result = $app->model('Company')->countries($company_slug)
or $app->redirect('/');
$app->stash({ result => $result });
}
Вы знаете, что случилось сейчас? Вы правильно инкапсулировали свою модель, вы не раскрыли ORM, и позже, когда вы обнаружите, что можете извлечь эти данные из кэша, а не из базы данных, вам не нужно менять код контроллера (и это проще написать тесты для этого и повторно использовать логику).
На самом деле происходит утечка кода ORM по всем контроллерам (и представлениям), и когда они сталкиваются с проблемами масштабируемости, они начинают обвинять ORM, а не свою архитектуру. ORM получает плохой рэп (я вижу это неоднократно для многих клиентов). Вместо этого скрывайте эту абстракцию, чтобы, когда вы по-настоящему достигли пределов ORM, вы могли выбрать подходящие решения для вашей проблемы, а не позволять коду настолько тесно связываться с ORM, что вы привязаны к нему.
Отчетность и другие ограничения
Как пояснил Роб Киньон выше, отчетность обычно является слабым местом в ORM. Это подмножество более крупной проблемы, когда сложный SQL или SQL, который охватывает несколько таблиц, иногда не работает с ORM. Например, иногда ORM вызывает тип соединения, который мне не нужен, и я не могу сказать, как это исправить. Или, может быть, я хочу использовать подсказку индекса в MySQL, но это не так просто . Или иногда SQL просто настолько сложен, что было бы лучше написать SQL, а не предоставленную абстракцию.
Это одна из причин, по которой я начал писать DBIx :: Class :: Report . Пока он работает хорошо и решает большинство проблем, возникающих у людей (если они в порядке с интерфейсом только для чтения). И хотя на самом деле это похоже на костыль, если вы не пропускаете абстракцию (как объяснялось в предыдущем разделе), это делает работу с ней DBIx::Class
еще проще.
Так, когда я выбрал бы DBIx :: Class?
Для меня я бы выбрал его в большинстве случаев, когда мне нужен интерфейс к базе данных. Я использую это в течение многих лет. Однако я не могу выбрать его для системы OLAP, и новые программисты наверняка будут бороться с этим. Кроме того, я часто нахожу, что мне нужно метапрограммирование, и хотя они DBIx::Class
предоставляют инструменты, они очень плохо документированы.
Ключ к DBIx::Class
правильному использованию такой же, как и для большинства ORM:
Не пропускайте абстракцию.
Напишите свои проклятые тесты.
Знать, как перейти к SQL, при необходимости.
Узнайте, как нормализовать базу данных.
DBIx::Class
После того, как вы изучите это, вы позаботитесь о большей части своей тяжелой работы и быстро создадите приложения.