JavaFree.org | RubyOnBr.org

Artigo do Akita no ar: Dieta dos controllers

Acompanhar Artigo do Akita no ar: Dieta dos controllers 21 posts, 9 participantes

Avatar Ronie Uliana 891 posts

http://rubyonbr.org/articles/2007/01/18/a-dieta-dos-controllers/

Inspirado da questão de “controller gordo”, o Akita fala sobre como colocar seus controllers para fazer regime. Grandes exemplos de código e boas idéias pra quem acha que seus controllers estão fora do peso.

Confiram!

 
Avatar Vinícius Teles 27 posts

Ronie, tá dando um Application Error quando tento ler o artigo.

 
Ceccbaaff99be20a857e00767f70b481 Proteu Alceb... 154 posts

Pra mim tambem =(

 
Avatar Adriano Dadario 226 posts

Não sei o que aconteceu… Mas dei umas modificadas de espaços nela e agora apresentou.

Tinha acontecido comigo também, mas agora apresentou! :S

 
Avatar Ronie Uliana 891 posts

Provavelmente o cache do Radiant :( Volta e meia ele dá problemas não consigo descobrir o porquê…

 
Avatar Shairon Toledo 1413 posts

Anorexia! De tando fazer dieta o controller morreu!! :-)

 
Avatar Fabiano França 6 posts

Sobre o artigo:

“No caso de Rails, ele foi feito especialmente para aplicativos web escaláveis. Várias aplicações Rails não foram feitas para conversar entre si e a recomendação é que cada aplicação use um banco de dados totalmente separado. Se houver necessidade de mais de uma aplicação Rails trocar dados entre si (digamos, dados de usuários, permissões, etc.) uma das muitas soluções é criar uma aplicação Rails somente para integração, expondo os serviços como Web Services (futuramente como ActiveResources) de forma que outras aplicações possam acessar os recursos sem precisar ir diretamente ao banco.”

Alguém já passou por essa situação de ter que fazer a comunicação entre mais de uma aplicação?

Estou estudando a posibilidade de migrar nossa intranet para Rails, atualmente esta sem asp, e queria dividi-la em módulos (aplicações) menores com baixo acoplamento entre eles.

Hoje em dia uma simples modificação em uma tabela acaba afetando todo o sistema, dando um trabalho para encontrar os focos de problemas.

 
Avatar Akita On Rails 298 posts

Expandindo um pouco o meu argumento. O que descrevi é apenas uma possível solução. O maior problema de dois aplicativos acessarem as mesmas tabelas em um mesmo banco de dados é que a lógica provavelmente estará nos Models. Então se eu tiver uma tabela chamada Livro, dois aplicativos Rails chamados Biblioteca e Inventario, então terei biblioteca/app/models/Livro.rb e inventario/app/models/Livro.rb.

Imagine a confusão. Uma das possíveis saídas é uma terceira aplicação que serviria de intermediário, um broker. Esse é exatamente um dos problemas que originaram em soluções como CORBA, COM+, J2EE, Web Services. Se quiser uma solução 100% Ruby, a alternativa é uma terceira aplicação Rails que expõe o Model Livro como um Web Service (ou um ActiveResource) para as outras duas. Dessa forma não é necessário fazer um “copy & paste” de models.

Uma saída mais light e caseira é fazer um plugin que ambos os aplicativos utilizariam. O plugin seria controlado em um repositório como SVN e os aplicativos sempre teriam a cópia mais atualizada dos Models. Essa solução é mais performática do que uma terceira aplicação.

Em ambas precisamos garantir uma estratégia de deployment que garanta que ambas as aplicações sempre estejam sincronizados com as mudanças da versão mais recente do Model centralizado. Nesse caso, test suites se tornam ainda mais importantes pois nunca se sabe quando ajustar o Model pode quebrar uma das aplicações.

Com JRuby talvez outra solução seja aplicações JRuby on Rails que acessem remotamente um Session Facade J2EE (ouch!). Com Ruby.CLR talvez tenhamos um Ruby.CLR on Rails que possa acessar componentes COM+ remotamente (duplou ouch!).

Não lembro foi assim mesmo que li, mas a 37signals também tem esse problema já que o mesmo usuário cadastrado poderia acessar o Basecamp, Backpack, Writeboard, sem precisar ter múltiplos logins. Acho que eles fizeram isso com Web Services e teria sido um dos motivadores à solução de Active Resources.

O consenso atual é que a lógica fique nos Models. Nesse sentido as tabelas são um detalhe da implementação e devem ficar o mais escondidos quanto possível. O conjunto classe de Model + tabela seria o “recurso” a ser consumido.

 
Avatar Shairon Toledo 1413 posts

Application error (Rails)

Só eu que não consigo ler o artigo?

 
Avatar Shairon Toledo 1413 posts

Fabiano, sobre a organização da sua aplicação, você tem a opção gererar modules no rails. Exemplo:

script/generate controller Admin::Financeiro::Vendas

O generate cria os módulos com a hierarquia:


admin
/financeiro
/vendas

Pode-se compartilhar as funcionalidades entre esses módulos.

Como sempre isso é mais uma opção do rails.

 
Avatar Thiago Arrais 93 posts

Anorexia! De tando fazer dieta o controller morreu!! :-)

Sério, com toda essa exposição agora de REST e CRUD, o que é que os controllers vão fazer?
Massagear os dados para exibição nas views? Como vamos evitar voltar a aplicações puramente
CRUD (se é que queremos fazer isso)?

 
Avatar Shairon Toledo 1413 posts

Esse brincadeira de anorexia era por que tava dando application error quando fui acessar o artigo.

 
Avatar Fabiano França 6 posts

Akita,

O que eu estou mais inclinado a implementar é cada módulo (aplicação rails) ser responsável por expor serviços para acesso aos seus models.

Assim um módulo de Compras (fictício) seria responsável por ter um serviço que permitisse aos demais módulos (financeiro, por exemplo) obter uma lista de fornecedores.

O meu caso é o mesmo que passou a 37signals, abaixo uns exemplos:

  • Um cadastro de usuários fixo para todas as aplicações
  • Fornecedores sendo utilizados pelos módulos de compras e financeiro
  • Um webmail onde todos os e-mails recebidos são gravados no banco de dados e o usuário só consegue responder um e-mail se ele for vinculado a uma entidade (Funcionário, Fornecedor, Cliente, Débito, Crédito, Nota fiscal, Treinamentos etc.).
  • Uma espécie de sistema de chamados em que você também pode vincular cada interação do chamado com uma entidade (mesmos exemplos do webmail)

Esses são os casos que me lembrei agora, mas minha base de dados tem 261 tabelas, onde tenho desde o sistema de controle de gestão até um sistema para controle de doações de sangue dos funcionários, e boa parte deles se relacionando.

Estou estudando também a opção do J2EE (EJB3, JSF etc.), mas a simplicidade de fazer algumas coisas com o Rails não tem igual.

Shairon, eu conheço essa solução dos módulos, mas manter 261 tabelas em uma aplicação além de achar que o Rails não agüenta, ia ficar dificílimo de manter.

 
Avatar Akita On Rails 298 posts

De fato, é bastante tabela. É o que falei antes: o ideal é particionar o Domain Model em múltiplas aplicações Rails e fazer com que cada uma publique recursos que quiser compartilhar. Exatamente como você disse.

O maior problema que você vai encontrar é se houver tabelas em um módulo com associações a tabelas de outro módulo. Nesse caso o relacionamento não será feito no nível do banco+ActiveRecord, mas no nível do ActiveRecord+ActionController. Será um overhead extra e você precisará tomar cuidado com as operações cruzadas.

De qualquer forma, não vejo solução mais prática agora (deve haver outra). Lembrar que isso também faz sentido do que uma aplicação monolítica com tudo embutido se você precisar de mais de um processo RoR de pé ao mesmo tempo: cada processo irá carregar os 261 Models e todo o resto do aplicativo e isso é bem pesado. Se separar em módulos, apenas as classes necessárias para cada requisição serão carregados, o que deve ajudar na performance e escalabilidade.

Não tem jeito, o negócio é começar a fazer pequenos testes de conceito com suas classes mais críticas. Procure saber sobre o Active Resources, isso pode te ajudar a compartilhar recursos entre seus módulos.

 
Avatar Akita On Rails 298 posts

Thiago, de fato, nem mesmo “massagear” os dados. Se entendi o que você falou, isso é tarefa das Helper Views. Os controller serão usados: 1) apenas para organizar a navegação e 2) como wrappers para os models, para expô-los como diferentes mime types (.xml, .rss, .html, .xls, etc).

A orquestração de actions nos dará a navegação Web e a orquestração dos mime-types nos dará recursos reusáveis remotos de graça. A idéia é essa mesma: controllers extremamente anoréxicos e models extremamente gordurosos. Use e abuse de modules e mixins para organizar melhor seu código.

 
Avatar Ronie Uliana 891 posts

Partindo do Simplício: Por que não fazer apenas uma aplicação com tudo?

É grande, eu sei, mas nada impede que vc divida em subsistemas lógicos, seria realmente necessária uma separação “física”?

 
Avatar Fabiano França 6 posts
De fato, é bastante tabela. É o que falei antes: o ideal é particionar o Domain Model em múltiplas aplicações Rails e fazer com que cada uma publique recursos que quiser compartilhar. Exatamente como você disse.

O trabalho agora é de identificar quais serão os melhores pontos de corte para não quebrar muito o relacionamento entre os models.

O maior problema que você vai encontrar é se houver tabelas em um módulo com associações a tabelas de outro módulo. Nesse caso o relacionamento não será feito no nível do banco+ActiveRecord, mas no nível do ActiveRecord+ActionController. Será um overhead extra e você precisará tomar cuidado com as operações cruzadas.

Esse é um dos problemas que mais vai acontecer, só o Sistema de Gestão e o Webmail interno se relacionam praticamente com todos os demais sistemas.

De qualquer forma, não vejo solução mais prática agora (deve haver outra). Lembrar que isso também faz sentido do que uma aplicação monolítica com tudo embutido se você precisar de mais de um processo RoR de pé ao mesmo tempo: cada processo irá carregar os 261 Models e todo o resto do aplicativo e isso é bem pesado. Se separar em módulos, apenas as classes necessárias para cada requisição serão carregados, o que deve ajudar na performance e escalabilidade.

Sempre tem uma outra forma, mas essa é a solução mais prática em que consegui chegar.

Agora vou começar a botar a mão na massa para ver se como fica isso implementado.

Não tem jeito, o negócio é começar a fazer pequenos testes de conceito com suas classes mais críticas. Procure saber sobre o Active Resources, isso pode te ajudar a compartilhar recursos entre seus módulos.

Já estou usando/estudando o Active Resources em uma aplicação aqui. Achei um post 1 bem legal com um exemplo prático de utilização, parecido com o exemplo dado pelo David na RailsConf.

Agora vou montar uma outra aplicação para ver como consumir os Resources.

Bem, obrigado pela ajuda e assim que eu tiver alguma novidade eu posto aqui no fórum.

UPDATE: Tinha esquecido do link:

1 http://metaatem.net/2006/07/31/rest-and-rails-no-reason-to-be-scared

 
Avatar Thiago Arrais 93 posts

Esse brincadeira de anorexia era por que tava dando application error quando fui acessar o artigo.

A brincadeira me levou a pensar em algo um pouco mais sério. Não que eu me leve tanto assim, mas…
Se pudermos modelar tudo como operações CRUD, para que diabos vamos querer os controllers? Pode ser
que no futuro eles fiquem tão anoréxicos que acabem realmente desaparecendo da face da terra.

Akita, talvez os controllers precisem ser usados na maioria dos casos apenas para a opção 1. A segunda
necessidade pode ser muito bem resolvida com a utilização seletiva de convenção ao invés de
configuração. Para falar a verdade, talvez até o primeiro problema possa ser resolvido com isso, só
estou evitando afirmar porque não acho que tenha entendido o que você quis dizer.

 
Avatar Shairon Toledo 1413 posts

O Akita usou um termo certo para os controllers “orquestrar” ou seja o maestro, um roteador de dados,etc.

Virão anos, muitos anos para retirar os controller com as suas actions. Espero que isso demore muito até eu aprender outra profissão.

Também fico pensando… será que nossos filhos gerarão aplicações, acho que depois tudo vai virar objeto mesmo e uma aplicação teria o nome de “objetão”.

Que viajem minha!!!

 
Avatar Eli 44 posts

Então, tenho uma dúvida bem básica… Quanto ao tratamento cosmético dos dados, seria uma tarefa do model? ou da view? por exemplo, o tratamento do formato das datas… no banco geralmente são armazenadas em “aaaa-mm-dd” e mostramos “dd/mm/aaaa”, este tratamento de vai e vem de formatos, seria uma tarefa dos models, não chega a ser uma regra de negócio, mais um tratamento de dados.

 
Avatar Akita On Rails 298 posts

View Helpers. Formatações que só interessam à tela, à apresentação devem ir em helpers. Isso porque em uma página HTML você pode querer que a data seja mostrada como “dia 19 de janeiro”. Mas se quiser utilizar seu controller como um recurso (eu sei, está repetitivo, mas novamente, ActiveResources) e quiser expor seu recurso como uma API xml, provavelmente a data deverá sair no formato mais universal “2007-01-19T12:00:00”, por exemplo.

Outro detalhe: não coloque a lógica da formatação dentro dos .rhtml ou .rjs mas sim em helpers, dentro de app/helpers conforme descrito aqui