Перш ніж відповісти на питання, я думаю, що деякий фон в порядку.
Основа проблеми
Після багатьох років співбесіди та найму розробників я дізнався дві речі:
Переважна більшість розробників мають дуже мало досвіду в розробці баз даних.
Я помітив вільну зв'язок між тими , хто не розуміє , баз даних і тих , хто ненавидить ORMS.
(Примітка: і так, я знаю, що є ті, хто дуже добре розуміє бази даних, які ненавидять 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 :: Звіт . Поки це добре працює і вирішує більшість питань, які тут виникають (поки вони в порядку з інтерфейсом лише для читання). І хоча насправді це здається милицьким, насправді, поки ви не просочуєтесь абстракцією (як пояснено в попередньому розділі), це робить роботу DBIx::Class
ще простіше.
Отже, коли я б обрав DBIx :: Class?
Для мене я б вибирав це більшість разів, коли мені потрібен інтерфейс до бази даних. Я ним користуюся роками. Однак я не можу вибрати його для системи OLAP, і нові програмісти, безумовно, зіткнуться з нею. Крім того, мені часто здається, що мені потрібно метапрограмування, і хоча вони DBIx::Class
надають інструменти, вони дуже погано документовані.
Ключ до DBIx::Class
правильного використання такий же, як і для більшості ORM:
Не просочуйте абстракцію.
Пишіть свої прокляті тести.
Знайдіть, як потрібно перейти до SQL.
Дізнайтеся, як нормалізувати базу даних.
DBIx::Class
, як тільки ви дізнаєтесь це, він подбає про більшість ваших важких підйомів для вас і зробить легким вітерцем для швидкого написання заявок.