Zanim odpowiem na pytanie, wydaje mi się, że pewne tło jest w porządku.
Rdzeń problemu
Po latach wywiadów i zatrudniania programistów nauczyłem się dwóch rzeczy:
Zdecydowana większość programistów ma bardzo małe doświadczenie w projektowaniu baz danych.
Zauważyłem luźną korelację między tymi, którzy nie rozumieją baz danych, a tymi, którzy nienawidzą ORM.
(Uwaga: i tak, wiem, że są tacy, którzy bardzo dobrze rozumieją bazy danych i nienawidzą ORM)
Kiedy ludzie nie rozumieją, dlaczego klucze obce są ważne, dlaczego nie umieścić nazwę producenta w item
tabeli, ani dlaczego customer.address1
, customer.address2
i customer.address3
pola nie są dobrym pomysłem, dodając ORM aby łatwiej dla nich pisać błędów bazy danych nic nie pomoże.
Zamiast tego, z odpowiednio zaprojektowaną bazą danych i przykładem użycia OLTP, ORM są złote. Większość pracy w chrząstce znika, a dzięki narzędziom takim jak DBIx :: Class :: Schema :: Loader mogę przejść od dobrego schematu bazy danych do działającego kodu Perla w kilka minut. Przywołałbym zasadę Pareto i powiedziałbym, że 80% moich problemów rozwiązano przy 20% pracy, ale w rzeczywistości uważam, że korzyści są jeszcze większe.
Nadużywanie rozwiązania
Innym powodem, dla którego niektórzy ludzie nienawidzą ORM, jest to, że pozwalają wyciek abstrakcji. Rozważmy typowy przypadek aplikacji internetowych MVC. Oto coś, co zwykle widzimy (pseudo-kod):
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,
});
}
Ludzie piszą takie trasy kontrolerów i klepią się po plecach, myśląc, że to dobry, czysty kod. Byliby wstrząśnięci twardym kodowaniem SQL w swoich kontrolerach, ale zrobili niewiele więcej niż ujawnienie innej składni SQL. Ich kod ORM musi zostać zepchnięty do modelu, a następnie mogą to zrobić:
GET '/countries/offices/$company' => sub {
my ( $app, $company_slug ) = @_;
my $result = $app->model('Company')->countries($company_slug)
or $app->redirect('/');
$app->stash({ result => $result });
}
Wiesz co się teraz stało? Właściwie zamknąłeś model, nie ujawniłeś ORM, a później, gdy okaże się, że możesz pobrać te dane z pamięci podręcznej zamiast z bazy danych, nie musisz zmieniać kodu kontrolera (i jest to łatwiejsze napisać dla niego testy i ponownie użyć logiki).
W rzeczywistości dzieje się tak, że ludzie wyciekają kod ORM na wszystkie kontrolery (i widoki), a kiedy napotykają problemy ze skalowalnością, zaczynają obwiniać ORM, a nie swoją architekturę. ORM dostaje zły rap (widzę to wielokrotnie dla wielu klientów). Zamiast tego ukryj tę abstrakcję, aby po prawdziwym przekroczeniu limitów ORM możesz wybrać odpowiednie rozwiązania dla swojego problemu, zamiast pozwolić, aby kod był tak ściśle powiązany z ORM, że jesteś związany.
Raportowanie i inne ograniczenia
Jak wyjaśnił powyżej Rob Kinyon, raportowanie jest zwykle słabą stroną ORM. Jest to podzbiór większego problemu, w którym skomplikowany SQL lub SQL obejmujący wiele tabel czasami nie działa dobrze z ORM. Na przykład czasami ORM wymusza typ łączenia, którego nie chcę i nie mogę powiedzieć, jak to naprawić. A może chcę użyć podpowiedzi do indeksu w MySQL, ale nie jest to łatwe . A czasem SQL jest tak cholernie skomplikowany, że fajniej byłoby napisać SQL niż dostarczoną abstrakcję.
Jest to jeden z powodów, dla których zacząłem pisać DBIx :: Class :: Report . Jak dotąd działa dobrze i rozwiązuje większość problemów, które mają tutaj ludzie (o ile są w porządku z interfejsem tylko do odczytu). I chociaż w rzeczywistości wydaje się to kulą, o ile nie przeciekasz abstrakcji (jak wyjaśniono w poprzedniej sekcji), sprawia, że praca z nią jest DBIx::Class
jeszcze łatwiejsza.
Kiedy więc wybrać DBIx :: Class?
Dla mnie najczęściej wybrałbym interfejs do bazy danych. Używam go od lat. Jednak mogę nie wybrać go dla systemu OLAP, a nowi programiści z pewnością będą mieli z tym problem. Często też uważam, że potrzebuję metaprogramowania i chociaż DBIx::Class
zapewnia narzędzia, są one bardzo słabo udokumentowane.
Klucz do DBIx::Class
prawidłowego korzystania jest taki sam, jak w przypadku większości ORM:
Nie wyciekaj z abstrakcji.
Napisz swoje przeklęte testy.
W razie potrzeby umieć przejść do SQL.
Dowiedz się, jak znormalizować bazę danych.
DBIx::Class
, gdy się go nauczysz, zajmie się większością ciężkiego podnoszenia i sprawia, że szybkie pisanie aplikacji jest dziecinnie proste.