[SP-pm] Controller thin, model fat ! Como fazê-lo ?
Eden Cardim
edencardim at gmail.com
Fri Jun 8 06:29:26 PDT 2012
>>>>> "Solli" == Solli Honorio <shonorio em gmail.com> writes:
Solli> Por exemplo, tenho que receber um arquivo de imagem, que deverá ser
Solli> validada (se é uma imagem mesmo, etc), depois relacionar ao usuário
Solli> e armazenar em um storage.
Solli> Nesta situação eu tenho diversas tarefas, algumas que seriam
Solli> natural colocar no controller, outras nem tanto.
Solli> Qual a melhor maneira de lidar com isto ?
Cria uma classe contendo um ou mais métodos que aceitem o usuário, o arquivo e
o storage e que execute as operações necessárias com eles, esse tipo de classe
se chama "Façade" porque fornece acesso simplificado a uma parte mais
complicada da lógica de negócio. A questão é encontrar a melhor forma de
abstrair essas 3 entidades. Por exemplo, elas podem ser modeladas/abstraídas
dentro de suas próprias classes, caso seja necessário. A melhor forma de
pensar em como montar essas classes, é imaginar como você usaria elas fora do
contexto de web app.
Para abstrair os arquivos, geralmente eu recomendo a API do IO::Handle, ou
seja, você passa um objeto filehandle-like para o método, representando o
arquivo em questão.
"Storage" é bastante dependente da lógica de negócio, e depende da
flexibilidade que você deseja. Um caso comum é que o seu storage seja um banco
de dados, e nesse caso, a abstração mais óbvia seria um dbh do DBI. Se você
precisar de mais "inteligência" nesse objeto, cria uma classe que encapsule o
dbh e faça as operações adequadas em cima dele (um objeto DBIx::Class::Schema,
por exemplo)
"User" poderia ser o objeto retornado por $c->user, já que você tá usando
Catalyst. Mas uma abordagem mais flexível seria passar o username ou coisa que
o valha, assim você não fica amarrado numa implementação específica.
nesse caso, seu model poderia implementar um método assim:
sub handle {
my($self, $fh, $dbh, $user) = @_;
# biz logic goes here
}
E o seu lean controller ficaria mais ou menos assim:
sub my_action :Local {
my($self, $c) = @_;
$c->model('MyBizClass')
->handle($c->req->upload('file')->fh, $c->model('DB')->dbh, $c->user->email);
}
Assumindo que você esteja pegando o arquivo de um campo upload chamado 'file'
e que tenha um model chamado 'DB' já com um dbh conectado, etc. A mentalidade
do lean controller é apenas a de integrar a sua classe contendo a lógica de
negócio com o contexto da web.
Observe que você pode usar essa classe de model em qualquer lugar, como por
exemplo, numa utilidade CLI:
my $biz = MyBizClass->new;
$biz->handle(\*STDIN, DBI->connect($ARGV[0]), $ARGV[1])
cat arquivo | perl util.pl dbi:Pg:dbname=foobar foo em bar.baz
--
Eden Cardim
+55 11 9644 8225
http://insoli.de
More information about the SaoPaulo-pm
mailing list