2008/01/27

Decepção com frameworks Web

Depois de quase dois anos trabalhando no Luca, cheguei à conclusão que o Turbogears, e na verdade todos os frameworks Web da moda, são largamente inadequados para desenvolvimento de sistemas "sérios", no estilo ERP.

Os frameworks Web atuais têm, em minha opinião, o grande defeito de serem norteados por ideologia e não por necessidades reais. Alguns exemplos:

* Todos alegam ser "Model-View-Controller", porque MVC é dogma da orientação a objetos, e todo desenvolvedor sério sabe que desacoplamento total entre visão e controle é utopia, embora uma separação razoável seja saudável. Se MVC perfeito fosse perfeitamente possível, estaríamos usando para Web as mesmas linguagens e ferramentas GUI que usávamos nos anos 90 (afinal, se eram perfeitas, ainda serviriam).

A conseqüência mais visível no Luca dessa separação MVC despropositada é a duplicação de informações no código. Por exemplo, numa tela comum de cadastro, eu preciso especificar as colunas em diversos lugares diferentes:

- No modelo, em SQLObject-ês
- No template XML para AJAX
- No template XML para Web simples (sem AJAX)
- No controlador, para validar o que vem do navegador e repassar ao modelo

Eu estava trabalhando num gerador de templates XML para o meu aplicativo, de modo a diminuir a contagem de 4 para 3. Mas de repente percebi que o certo seria tomar providências para que a contagem caísse a 1. E isto provavelmente implica em usar outro framework que não o TurboGears.

Separar controle de apresentação é análogo a separar conteúdo de estilo. Quem desenvolve site sabe que HTML representa o conteúdo e CSS representa o estilo, mas é impossível separar completamente as duas coisas. Sempre é necessário mexer alguma coisa no HTML para atingir a apresentação final desejada.

* Muitos têm mapeamento objeto-relacional, porque SQL é "ruim" e deve-se usar classes ao invés da interface DBI -- até que a Revolução dos Objetos varra os bancos de dados em favor de bancos de objetos. O resultado é a perda do poder do SQL sem o ganho de poder que existiria num banco de objetos de verdade, e adicionam uma camada de software em cima do DBI, com seus próprios bugs, limitações e idiossincrasias.

Pessoalmente sofri muito com o SQLObject, que tem bugs de Unicode com o MySQL ainda não resolvidos. Qualquer consulta não trivial seria mais fácil fazer em SQL do que em SQLObject. A única possível vantagem de usar SQLObject é a portabilidade de banco de dados, mas mesmo isso é limitado. Às vezes, algo que funciona bem em MySQL não funciona em Postgres por um motivo totalmente obscuro, ou um nome de coluna que funciona no MySQL não funciona no Interbase/Firebird (e o SQLObject não resolve isso, é preciso trocar mesmo o nome da coluna).

Concluo que o ideal é tomar partido de forma clara: ou se usa SQL via interface DBI da sua linguagem predileta, ou se usa um banco de objetos nativo como ZODB. E dentre as duas opções, eu prefiro SQL, em particular se existe alguma chance de outros sistemas em outras linguagens terem de manipular esses mesmos dados. (Como um sistema escrito em Visual Basic vai acessar um banco de objetos ZODB?)

* Templates XML. É outra praga que contamina quase todos os frameworks. Uns poucos decidem ser "agnósticos a template" mas sempre deixam aberta a possibilidade de usar um template de terceiros. Nunca gostei de template XML, mas procurei aceitar a idéia durante o desenvolvimento do Luca, afinal eu poderia estar errado. Mas vejo que eu estava é certo.

XML não foi feito para ser produzido ou editado por humanos. Tanto é assim que o CSS não tem sintaxe XML, justamente porque ele será mais provavelmente editado por um designer, enquanto o HTML de conteúdo será mais provavelmente gerado por máquina e que (quase) nunca é editado por questões de estilo.

XML foi feito para representar dados passivos de forma hierárquica. Coisas como páginas dinâmicas não são bem representadas por XML. Toda linguagem de template acaba resultando em algo parecido com COBOL: uma linguagem rígida, pouco poderosa e desagradável de usar.

Para piorar, um template XML é praticamente um mapeamento de HTML, tanto que algumas linguagens alegam como "vantagem" o fato do XML ser renderizável no browser mesmo sem ser processado pelo framework. Ou seja, é praticamente inútil para renderizar qualquer coisa que não seja um HTML convencional. Isso inclui gerar um HTML mais apropriado para um dispositivo diferente do desktop comum (como sabem os designers, apenas trocar o CSS não é suficiente para tornar uma página boa para qualquer tamanho de tela).

Seria um pouco excessivo pedir que o XML de template fosse capaz de gerar interfaces diferentes de Web (e.g. interface texto ou GUI), afinal ele é justamente o View, e diferentes interfaces pedem diferentes Views. Por isso mesmo, os templates deveriam ser arquitetados de forma a ter pouca ou nenhuma informação sobre nomes de colunas e lógica de programação. Tais coisas pertencem à dupla Model e/ou Controller.

Ouso dizer que o PHP daria uma ótima linguagem de template para os frameworks. Não é uma boa linguagem de uso geral, apesar de infelizmente o PHP ser largamente usado como linguagem de desenvolvimento Web, lugar que na opinião de alguns caberia ao Javascript server-side. Mas como linguagem de template, ou seja, HTML com alguma inteligência embutida, PHP é a melhor. Eu não gosto de PHP mas uso-o no meu sítio Web, simplesmente porque as opções baseadas em Python são piores, para esse uso particular.

No gerador de templates XML que eu estava fazendo para o Luca, eu escrevia "meta templates", usando sintaxe Python convencional, mais ou menos assim:


t = SimpleTable()
t.append( TextField(name="bla", size=40) )


A idéia é usar sintaxe Python convencional, não usar XML e procurar pensar a interface num nível mais alto. O mesmo meta-template gera versões AJAX e não-AJAX da mesma página (no Luca, as duas versões podem ser consideravelmente diferentes). E poderia mesmo ser usado no futuro para gerar uma interface texto ou GUI. Na verdade, esse código poderia estar no próprio Controller ao invés de ser um template. O "View" passa a ser a biblioteca que implemente as classes SimpleTable, TextField etc.

---

Bem, os problemas estão explanados. Quais são as soluções, em particular para meu pet project, o Luca? Seria possível arrumar o Luca, usando técnicas mais adequadas, sem ter de reescrever tudo do zero? Seria possível fazer isso sem abandonar o TurboGears? Ou talvez abandonando o TurboGears mas usando CherryPy, principal componente do TurboGears, de modo a economizar reescrita?

Penso que o código do Luca está demasiadamente poluído pelos problemas do framework, e uma tentativa de reaproveitar muito código acabaria num trabalho mal-feito. Algumas partes muiti reaproveitáveis do Luca (e.g. cálculo do balanço) já são totalmente separadas dos Controllers, e desta forma foram "salvas" dos problemas do framework. Tais partes só teriam de ser reescritas se se trocasse a linguagem Python por Ruby, PHP, Javascript ou outra qualquer.

O Ruby on Rails seria uma coisa interessante de se tentar. Mas ele padece dos mesmos "pecados originais" que o TurboGears, fora que usa outra linguagem, o que significa reescrita total do Luca. Admito que o Ruby on Rails é mais bem-feito que o TurboGears, mas as benfeitorias do RoR não resolvem meu problema.

Em resumo, o framework ideal que procuro teria as seguintes características:

- Preferencialmente feito em Python;
- Não imponha mapeamento objeto-relacional;
- Não imponha templates XML
- Seja (mesmo que minimamente) aberto à possibilidade de Views diferentes de Web

Para atingir estes objetivos sem deixar de usar TurboGears, seria necessário fazer o seguinte:

- Não usar a autenticação nativa oferecida pelo TurboGears, já que este depende do mapeamento objeto-relacional;
- Modificar o código do Luca de modo a utilizar DBI ao invés de SQLObject
- Escrever um decorator @expose próprio, que gere HTML a partir dos meta-templates ao invés do Kid.

1 Comentários:

Às 13:08 , Blogger Osvaldo Santana Neto disse...

É um saco responder a tantas questões no sistema de comentários do blogger, mas vamos tentar...

Depois de quase dois anos trabalhando no Luca, cheguei à conclusão que o Turbogears, e na verdade todos os frameworks Web da moda, são largamente inadequados para desenvolvimento de sistemas "sérios", no estilo ERP.

Você não ter conseguido não significa que não é possível. Sei que você é bom desenvolvedor, mas também sei de sistemas ERP desenvolvidos com esses frameworks. Quem tem razão? :)

Os frameworks Web atuais têm, em minha opinião, o grande defeito de serem norteados por ideologia e não por necessidades reais.

Lá vem você com essa linha soviética de raciocínio ;)

* Todos alegam ser "Model-View-Controller", porque MVC é dogma da orientação a objetos, e todo desenvolvedor sério sabe que desacoplamento total entre visão e controle é utopia, embora uma separação razoável seja saudável. Se MVC perfeito fosse perfeitamente possível, estaríamos usando para Web as mesmas linguagens e ferramentas GUI que usávamos nos anos 90 (afinal, se eram perfeitas, ainda serviriam).

É utopia mesmo mas não é por essa razão que deveríamos abandonar as tentativas?

* Muitos têm mapeamento objeto-relacional, porque SQL é "ruim" e deve-se usar classes ao invés da interface DBI -- até que a Revolução dos Objetos varra os bancos de dados em favor de bancos de objetos. O resultado é a perda do poder do SQL sem o ganho de poder que existiria num banco de objetos de verdade, e adicionam uma camada de software em cima do DBI, com seus próprios bugs, limitações e idiossincrasias.

Você sabe minha opinião sobre bancos de dados relacionais portanto não vou repetí-las aqui.

Mas como você está impondo esse modelo como requisito do seu sistema você tem a obrigação de pagar o preço por usar um RDBMS.

Existem vários sistemas que fazem ORM em Python. O SQLObject é o primeiro deles e o mais mal feito de todos.

Existem alternativas mais novas e melhores mas eu não posso garantir que ao escolher uma delas você será feliz para sempre.

As alternativas são SQLAlchemy que é muito usado, tem uma grande comunidade de desenvolvedores, uma documentação invejável e permite um acesso mais granular à toda aquela monstruosidade relacional.

Tem também o Storm que é desenvolvido pelo Niemeyer e dispõe de uma boa consultoria (tendo em vista que podemos conversar diretamente com o criador).

* Templates XML. É outra praga que contamina quase todos os frameworks. Uns poucos decidem ser "agnósticos a template" mas sempre deixam aberta a possibilidade de usar um template de terceiros. Nunca gostei de template XML, mas procurei aceitar a idéia durante o desenvolvimento do Luca, afinal eu poderia estar errado. Mas vejo que eu estava é certo.

Também não gosto de templates XML e sei que existem várias linguagens alternativas para template. Escolha uma delas e use a que achar melhor e se encaixar melhor com o framework que vc escolheu.

Bem, os problemas estão explanados. Quais são as soluções, em particular para meu pet project, o Luca? Seria possível arrumar o Luca, usando técnicas mais adequadas, sem ter de reescrever tudo do zero? Seria possível fazer isso sem abandonar o TurboGears? Ou talvez abandonando o TurboGears mas usando CherryPy, principal componente do TurboGears, de modo a economizar reescrita?

Sim, é possível usar somente o CherryPy para economizar na reescrita. Acho que para o seu caso é uma boa idéia.

Mas substituir o SQLObject vai exigir uma boa dose de trabalho. Dependendo da complexidade de seus templates pode dar trabalho reescrevê-los em Mako (por exemplo). Mas até onde me lembro o visual do Luca é simples.

Pra finalizar existem várias alternativas de frameworks para desenvolvimento Web em Python. Ao mesmo tempo a quantidade de alternativas também se estabilizou em:

Django

É o mais "badalado", usa um ORM próprio que é bom e estável (permite execução de SQL diretamente), tem uma linguagem de template própria que não é XML, tem muita documentação boa (diferente do TG), tem um sistema de autenticação próprio mas pode ser substituido por outro facilmente.

Ele te força muito o uso de seus próprios componentes mas te garante que estão bem integrados entre si.

É o que estou usando em um projeto pessoal no momento. Mas foi mais uma escolha circunstancial do que técnica (o co-desenvolvedor é especialista em Django e não queria perder esse know-how). Se eu fosse escolher estaria usando Pylons.

TurboGears

Você já conhece então não vou me alongar nas explicações.

O TG vai substituir o SQLObject pelo SQLAlchemy e também vai usar o CherryPy3. Também será possível trocar o sistema de templates, ou seja, você poderá usar um sistema não-XML de templates.

Se você realmente não está querendo reescrever muita coisa me parece que o melhor é usar CherryPy e sair "ajuntando" as outras ferramentas que você gostar mais.

Pylons

Esse é o mais agnóstico e leve dos sistemas. Acho que você gostaria muito dele por não te forçar a usar nada e ser uma casca muito fina de software.

Em compensação ele faz muito uso do "Paste" que é um projeto com a mesma "qualidade" do SQLObject porque são do mesmo autor.

web.py

Esse aqui é o mais próximo do PHP que você vai chegar. É pra quem gosta de lidar com as requests "na mão". Mas te dá flexibilidade infinita para usar os componentes que bem entender.

Grok (Zope3-light)

Esse é novo e não conheço bem mas ele é construído em cima do Zope3. E você já sabe que isso pode ser bom (imagine guardar seus dados no ZODB de maneira realmente transparente), ou ruim (imagina o mastodonte de software).

Mas vale ressaltar que a idéia do Grok é justamente colocar o poder do Z3 na sua mão *sem* ter que usar o f*cking ZCML e toda aquela baboseira de configuração (que você chamou de "soviético").

Conclusão

Essas são as alternativas. Pode até surgir coisa nova por aí mas essas foram as que demonstraram mais "força" até agora. Vai ser difícil um outro framework surgir e conseguir se firmar.

 

Postar um comentário

<< Início