Prima di rispondere alla domanda, penso che alcuni retroscena siano in ordine.
Il nocciolo del problema
Dopo anni di interviste e assunzioni di sviluppatori, ho imparato due cose:
La stragrande maggioranza degli sviluppatori ha pochissima esperienza nella progettazione di database.
Ho notato una chiara correlazione tra coloro che non comprendono i database e quelli che odiano gli ORM.
(Nota: e sì, so che ci sono quelli che capiscono molto bene i database che odiano gli ORM)
Quando la gente non capisce il motivo per cui le chiavi esterne sono importanti, perché non incorporare il nome del produttore del item
tavolo, o perché customer.address1
, customer.address2
e customer.address3
campi non sono una buona idea, aggiungendo un ORM per rendere più facile per loro di bug del database di scrittura non aiuterà nulla.
Invece, con un database ben progettato e un caso d'uso OLTP, gli ORM sono d'oro. Gran parte del lavoro grugnito va via e con strumenti come DBIx :: Class :: Schema :: Loader , posso passare da un buon schema di database al funzionamento del codice Perl in pochi minuti. Vorrei citare la regola di Pareto e dire che l'80% dei miei problemi è stato risolto con il 20% del lavoro, ma in realtà trovo che i benefici siano ancora maggiori.
Abusare della soluzione
Un altro motivo per cui alcune persone odiano gli ORM è perché lasceranno perdere l'astrazione. Consideriamo il caso comune delle app Web MVC. Ecco qualcosa che comunemente vediamo (pseudo-codice):
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,
});
}
Le persone scrivono percorsi del controller in questo modo e si danno una pacca sulla spalla, pensando che sia un buon codice pulito. Sarebbero sbalorditi dal codice SQL nei loro controller, ma hanno fatto poco più che esporre una diversa sintassi SQL. Il loro codice ORM deve essere inserito in un modello e quindi possono farlo:
GET '/countries/offices/$company' => sub {
my ( $app, $company_slug ) = @_;
my $result = $app->model('Company')->countries($company_slug)
or $app->redirect('/');
$app->stash({ result => $result });
}
Sai cosa è successo adesso? Hai incapsulato correttamente il tuo modello, non hai esposto l'ORM e in seguito, quando scopri che potresti recuperare quei dati da una cache anziché dal database, non è necessario modificare il codice del controller (ed è più facile scrivere test per questo e riutilizzare la logica).
In realtà, ciò che accade è che le persone perdono il loro codice ORM su tutti i loro controller (e viste) e quando colpiscono problemi di scalabilità, iniziano a incolpare l'ORM anziché la loro architettura. L'ORM ottiene un brutto rap (lo vedo ripetutamente per molti clienti). Invece, nascondi quell'astrazione in modo che quando hai effettivamente raggiunto i limiti ORM, puoi scegliere le soluzioni appropriate per il tuo problema piuttosto che lasciare che il codice sia così strettamente accoppiato all'ORM che sei legato.
Rapporti e altre limitazioni
Come Rob Kinyon ha chiarito sopra, la segnalazione tende ad essere una debolezza degli ORM. Questo è un sottoinsieme di un problema più grande in cui SQL o SQL complessi che si estendono su più tabelle a volte non funzionano bene con gli ORM. Ad esempio, a volte l'ORM impone un tipo di join che non desidero e non so come risolverlo. O forse voglio usare un suggerimento sull'indice in MySQL, ma non è facile . O a volte l'SQL è così complicato che sarebbe più bello scrivere l'SQL piuttosto che l'astrazione fornita.
Questo è uno dei motivi per cui ho iniziato a scrivere DBIx :: Class :: Report . Finora funziona bene e risolve la maggior parte dei problemi che le persone hanno qui (purché stiano bene con un'interfaccia di sola lettura). E mentre sembra una stampella, in realtà, fintanto che non perdi la tua astrazione (come spiegato nella sezione precedente), rende il lavoro DBIx::Class
ancora più semplice.
Quindi quando sceglierei DBIx :: Class?
Per me, lo sceglierei la maggior parte delle volte che ho bisogno di un'interfaccia per un database. L'ho utilizzato per anni. Tuttavia, potrei non sceglierlo per un sistema OLAP e i programmatori più recenti avranno sicuramente delle difficoltà. Inoltre, trovo spesso che ho bisogno di meta-programmazione e mentre DBIx::Class
fornisce gli strumenti, sono molto scarsamente documentati.
La chiave per utilizzare DBIx::Class
correttamente è la stessa della maggior parte degli ORM:
Non perdere l'astrazione.
Scrivi i tuoi dannati test.
Sapere come passare a SQL, se necessario.
Scopri come normalizzare un database.
DBIx::Class
, una volta appreso, si occuperà della maggior parte del tuo sollevamento pesante per te e ti semplifica la scrittura rapida di applicazioni.