Antes de responder à pergunta, acho que alguns antecedentes estão em ordem.
O núcleo do problema
Após anos entrevistando e contratando desenvolvedores, aprendi duas coisas:
A grande maioria dos desenvolvedores tem muito pouca experiência em design de banco de dados.
Percebi uma correlação fraca entre aqueles que não entendem bancos de dados e aqueles que odeiam ORMs.
(Nota: e sim, eu sei que existem aqueles que entendem muito bem os bancos de dados que odeiam ORMs)
Quando as pessoas não entendem por que as chaves estrangeiras são importantes, por que você não incorporar o nome do fabricante na item
mesa, ou por que customer.address1
, customer.address2
e customer.address3
os campos não são uma boa idéia, acrescentando um ORM para torná-lo mais fácil para eles a erros de banco de dados de gravação não vai ajudar em nada.
Em vez disso, com um banco de dados projetado adequadamente e um caso de uso OLTP, os ORMs são dourados. A maior parte do trabalho árduo desaparece e, com ferramentas como DBIx :: Class :: Schema :: Loader , posso passar de um bom esquema de banco de dados para trabalhar com o código Perl em minutos. Eu citaria a Regra de Pareto e diria que 80% dos meus problemas foram resolvidos com 20% do trabalho, mas, na realidade, acho os benefícios ainda maiores que isso.
Abusando da solução
Outra razão pela qual algumas pessoas odeiam ORMs é porque elas deixam a abstração vazar. Vamos considerar o caso comum dos aplicativos da web MVC. Aqui está algo que geralmente vemos (pseudo-código):
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,
});
}
As pessoas escrevem rotas de controladores assim e dão tapinhas nas costas, achando que é um código bom e limpo. Eles ficariam horrorizados com a codificação do SQL em seus controladores, mas fizeram pouco mais do que expor uma sintaxe SQL diferente. Seu código ORM precisa ser inserido em um modelo e eles podem fazer isso:
GET '/countries/offices/$company' => sub {
my ( $app, $company_slug ) = @_;
my $result = $app->model('Company')->countries($company_slug)
or $app->redirect('/');
$app->stash({ result => $result });
}
Você sabe o que aconteceu agora? Você encapsulou seu modelo corretamente, não expôs o ORM e, mais tarde, quando descobre que pode buscar esses dados em um cache em vez do banco de dados, não precisa alterar o código do controlador (e é mais fácil para escrever testes e reutilizar a lógica).
Na realidade, o que acontece é que as pessoas vazam seu código ORM em todos os seus controladores (e visualizações) e, quando atingem problemas de escalabilidade, começam a culpar o ORM em vez de sua arquitetura. O ORM tem uma má reputação (vejo isso repetidamente para muitos clientes). Em vez disso, oculte essa abstração para que, quando você realmente atingir os limites do ORM, possa escolher as soluções apropriadas para o seu problema, em vez de permitir que o código seja tão fortemente acoplado ao ORM que você estará atrapalhado.
Relatórios e outras limitações
Como Rob Kinyon deixou claro acima, os relatórios tendem a ser uma fraqueza nos ORMs. Esse é um subconjunto de um problema maior, no qual SQL ou SQL complicado, que abrange várias tabelas, às vezes não funciona bem com ORMs. Por exemplo, às vezes o ORM força um tipo de junção que não quero e não sei como consertar isso. Ou talvez eu queira usar uma dica de índice no MySQL, mas não é fácil . Ou, às vezes, o SQL é tão complicado que seria melhor escrever o SQL do que a abstração fornecida.
Isso é parte do motivo pelo qual comecei a escrever DBIx :: Class :: Report . Até agora, funciona bem e resolve a maioria dos problemas que as pessoas têm aqui (desde que estejam bem com uma interface somente leitura). E, embora pareça uma muleta, na realidade, desde que você não esteja perdendo sua abstração (como explicado na seção anterior), isso facilita DBIx::Class
ainda mais o trabalho.
Então, quando eu escolheria DBIx :: Class?
Para mim, eu o escolhia na maioria das vezes em que preciso de uma interface para um banco de dados. Eu tenho usado por anos. No entanto, talvez eu não o escolha para um sistema OLAP, e os programadores mais recentes certamente terão dificuldades com isso. Além disso, muitas vezes acho que preciso de metaprogramação e, embora DBIx::Class
ofereça as ferramentas, elas são muito mal documentadas.
A chave para o uso DBIx::Class
correto é a mesma da maioria dos ORMs:
Não vaze a abstração.
Escreva seus malditos testes.
Saiba como descer para o SQL, conforme necessário.
Aprenda a normalizar um banco de dados.
DBIx::Class
, depois que você aprender, cuidará da maior parte do seu trabalho pesado e facilitará a criação rápida de aplicativos.