Prima di rispondere alla domanda, penso che sia di base uno sfondo.
Il nucleo del problema
Dopo anni di interviste e assunzione di sviluppatori, ho imparato due cose:
-
La stragrande maggioranza degli sviluppatori ha poca esperienza in
progettazione del database.
-
Ho notato una correlazione allentata tra coloro che non capiscono
database e coloro che odiano gli ORM.
(Nota: e sì, so che ci sono quelli che capiscono molto bene i database che odiano gli ORM)
Quando le persone non capiscono perché le chiavi esterne sono importanti, perché non incorporare il nome del produttore nella tabella item
, o perché customer.address1
, customer.address2
e customer.address3
campi non sono una buona idea, l'aggiunta di un ORM per rendere più facile per loro scrivere bug del database non aiuterà nulla.
Invece, con un database progettato correttamente e un caso di utilizzo OLTP, gli ORM sono d'oro. Gran parte del lavoro del grunt va via e con strumenti come DBIx :: Class :: Schema :: Loader , posso passare da un buon schema di database a codice Perl funzionante in pochi minuti. Vorrei citare la regola di Pareto e dire che l'80% dei miei problemi sono stati risolti con il 20% del lavoro, ma in realtà, trovo i benefici ancora più grandi di quello.
Abuso 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 di controller del genere e si accarezzano le spalle, pensando che sia un codice buono e pulito. Sarebbero inorriditi con SQL hard-coding nei loro controller, ma hanno fatto poco più che esporre una sintassi SQL diversa. 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 ora? Hai incapsulato correttamente il tuo modello, non hai esposto l'ORM e, successivamente, quando trovi che puoi recuperare i dati da una cache anziché dal database, non è necessario modificare il codice del controller (ed è più semplice 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 controllori (e viste) e quando hanno problemi di scalabilità, iniziano a incolpare l'ORM piuttosto che la loro architettura. L'ORM subisce un brutto colpo (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 associato all'ORM che sei legato al maiale.
Rapporti e altri limiti
Come Rob Kinyon ha chiarito in precedenza, la segnalazione tende ad essere un punto debole negli ORM. Questo è un sottoinsieme di un problema più ampio 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 forza un tipo di join che non desidero e non posso dire come risolverlo. O forse voglio usare un suggerimento indice in MySQL, ma non è facile . O a volte l'SQL è così complicato che sarebbe più carino scrivere 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 (a patto che stiano bene con un'interfaccia di sola lettura). E mentre sembra come una stampella, in realtà, fintanto che non stai perdendo la tua astrazione (come spiegato nella sezione precedente), rende ancora più facile lavorare con DBIx::Class
.
Quindi quando dovrei scegliere DBIx :: Class?
Per me, lo sceglierei la maggior parte delle volte in cui 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 certamente difficoltà a farlo. Inoltre, trovo spesso che ho bisogno di meta-programmazione e mentre DBIx::Class
fornisce gli strumenti, sono molto scarsamente documentati.
La chiave per usare correttamente DBIx::Class
è 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 appresa, si prenderà cura della maggior parte del tuo lavoro pesante per te e renderà più semplice scrivere rapidamente le applicazioni.