sexta-feira, maio 16, 2008

Putz, copiaram o Merlin

Frameworks runtime para Telas de Cadastro

Quando iniciei o Metagen lá em 2001, achei que era uma coisa bem diferente. E era. Até a semana passada, para o mundo Java eu não conhecia nada do gênero.

Nas diversas pesquisas que realizei, encontrei mais de 20 projetos acadêmicos provando que a gerção de IU em tempo de execução já era possível lá nos anos 80.

Porém, frameworks de uso profissional, que não entrassem em “viajens” como álgebra relacional, formalismos maquiavélicos, linguagens conceituais ou gramáticas de outro mundo, bem, isso não tinha nada até o Merlin aparecer...

Metawidget

Mas agora os tempos são outros. E como me atraso constantemente em implementar o Merlin, a máquina anda e mais e mais pessoas começam a perceber que esse negócio de gerar código-fonte não tem nada a ver.

Bem por acaso, anteontem, nem não sei o que eu estava fazendo no branquelo, mas me deparei com um link de uma ferramenta chamada Metawidget.

Li alguns artigos e uma entrevista com o criador e só tenho uma frase a dizer: putz, copiaram o Merlin!

Funcionamento da bagaça

O framework do cara tem a essência do Merlin, mas trabalhando de outra forma.

Ele suporta além de beans Java, o famigerado XML. Assim, ele chama isso de “back-end”. Para ler esses back-ends, ele possui o conceito de Inspectors. Os inspectors usam (basicamente) reflexão e coisas to tipo para ler classes POJO, JavaBeans, Anotações ou XML.

E também dá para estender e criar inspectors para outros back-ends, tais como tabelas relacionais (pelo menos é o que o cara diz).

Para a geração, que também ocorre em tempo de execução, ele usa o conceito de Metawidgets. Você pode interpretar essas metawidgets como sendo um pattern Wrapper que encapsula e delega a widget do pacote gráfico em uso.

Assim, tal como o Merlin, ele também suporta diversas bibliotecas gráficas, como Swing, JSF, SWT e – isso eu achei legal – o Android.

Muito parecido

Depois de ler a documentação, baixei o fonte começei a olhar o negócio por dentro.

O Merlin possui a anotação @Caption, que serve para definir o label na tela, tendo suporte à internacionalização (i18n). A bagaça tem a @UiLabel.

O Merlin possui a anotação @Group, que serve para definir (sub)agrupamentos. O framework do cara possui a @UiSection.

O Merlin possui a anotação @Order, que serve para reordenar componentes na tela. O cara usa a @UiComesAfter.

O Merlin possui a anotação @Property, que serve para definir propriedades do controle de IU. O do cara tem a @UiAttributes.

O Merlin possui a anotação @Ignore, quando desejamos que um atributo de um objeto não seja mostrado na tela. A bagaça do cara tem o @UiHidden.

Os Inspectors do cara, são, praticamente, os Resolvers do Merlin.

Os Metawidgets do cara, são, again, os Renderers do Merlin.

Cada metawidget do cara estende a classe-base do pacote gráfico em uso. Por exemplo, ele tem uma metawidget que estende um JComponent para o Swing, outra que estende um UIComponentBase para o JSF, e outra que estende LinearLayout para o Android.

Observem que isso não representa limitações, pois permite que essas metawidgets (ainda não consegui decorar esse nome) sejam estendidas ou mesmo criadas do zero para pacotes gráficos diferentes. Ele tem um exemplo para o RichFaces.

Na prática, essas metawidgets recebem alguns parâmetros (que vêm das anotações, do objeto “inspectado” ou do código-fonte da aplicação principal) e passam-nos para a widget real no sistema. Como disse, é um wrapper com um pouco de deletage (ufh)...

Também olhei trechos de código e, pasmem (ou nem tanto), tem coisas praticamente iguais. Estruturas IF e blocos SWITCH parecem fazer as mesmas coisas em determinados momentos.

Outras funcionalidades semelhantes são o suporte à substituição de controles em tempo de execução, parametrização de layout, binding customizável (com suporte à JSR295) e mapeamento automático de tipos de dados para tipos de controle.

Para não dizer que estou mentindo, vejam:

//Metawidget renderizando um campo booleano e outro char

if ( "boolean".equals( type ) )

return new JCheckBox();

if ( "char".equals( type ) )

return new JTextField();


//Merlin renderizando as mesmas coisas

if (field.getClass() == FieldString.class) {

c = new JTextField();

} else if (field.getClass() == FieldBoolean.class) {

c = new JCheckBox();

}

Enfim, muito, mas muito parecido mesmo ;)

Parecido sim, mas não igual

Mas embora tenham os mesmos objetivos, os frameworks têm algumas diferenças sim. Evitando falar na configuração realimentada do Merlin, vou colocar algumas coisas que os distinguem:

1. POJO x Back-End: O Merlin foi projetado para suportar somente classes que sejam, no mínimo, POJOs. E nada mais. Nesse ponto, o framework do cara vai além, pois permite XML e outras coisas. Nós, no Merlin, vamos continuar afincos à nossa abordagem, pois dia após dia, a Domain Driven Design vem provando que é a melhor forma de fazer sistemas. Assim, nada de XML ou mundo relacional. Peço “sorry” aos que discordam...

2. Campos de lookup: Toda vez que o Metawidget encontra um campo de objeto que é uma referência para outro objeto, ele renderiza o objeto referenciado dentro da janela principal. No Merlin, o padrão é renderizar como um campo de lookup, ou seja, uma caixa de seleção. Acredito que o cara permita outro comportamento, mas não vi isso nos exemplos ou documentação. No Merlin, isso é feito via anotação ou novos renderizadores.

3. Renderização customizada: Nos exemplos do cara, para trocar um controle por outro (por exemplo, não quero o campo “nome” como uma caixa de texto, mas sim como uma caixa de seleção), o cara usa código-fonte na aplicação principal. No Merlin, isso também é possível. Poré, o mais fácil, rápido (e conveniente, pois entra para o sistema de histórico) é usar a anotação @RenderAs.

4. Inspectors x Renderers (again): No framework do cara, os inspectors são definidos na aplicação principal. Assim, se um bean tiver a anotação (do JPA) @Column.length mas não tiver o Inspector associado definido, então essa anotação é ignorada. No Merlin, o propósito é continuar usando ela para fazer coisas como, saber o tamanho que o campo deve ter na tela.

5. Binders: O Metawidget delega, assim como o Merlin, o processo de binding para frameworks de terceiros, como a JSR295. Mas para fazer isso, ele usa código na aplicação principal, ou via XML. No Merlin, usa-se essencialmente anotações, como @Binder, ou @RenderAs.binder.

6. Section x Group: São agrupadores de campos na tela. Não consegui ver detalhes maiores, mas acredito que as sections no Metawidget não possam ser renderizadas de maneiras diferentes. Por exemplo, no Merlin dá para fazer @Group.renderAs e também dá para fazer subagrupamentos com @Group.in.

7. Tratadores de eventos: Também não percebi suporte para o tratamento de eventos no Metawidget. Toda vez que o cara deseja colocar um tratador de evento em um controle, ele chama, tal como no Merlin, o método utilitário getComponent(String name). No Merlin, acredito que o conceito de Agentes seja muito mais fácil. Por exemplo @Agent(event=”focusLost”, action=”buscarPessoaPorCpf”)

8. Injeção, scripting, OCL e EL: Não vou falar tanto, pois o cara está, assim como quase eu estou, sozinho nessa história de criar frameworks. Porém, o suporte à injeção de recursos, previsto para o primeiro release do Merlin, é uma coisa obrigatória nos frameworks de hoje em dia. Ademais, para quem conhece Object Constraint Language e o poder que ela nos trás, não a dispensa tão facilmente. O suporte a scripting também é um recurso poderoso e não pode ser deixado de lado. Essas são coisas que estamos prevendo no Merlin e que o Metawidget parece deixar para um segundo momento, eu acho. Mas ele traz a Expression Language, e isso é bom. Tanto, que é previsto no Merlin.

Não conheçe? Tá bom...

Posso estar sendo tendencioso em minha análise (seráquáquáquá?). Mas não ocultei verdades em nenhum momento.

A única coisa que fico triste mesmo é que lendo o FAQ do projeto do cara, ele diz que não conheçe nenhuma solução do gênero. E isso é uma pena.

Compreendo que usando a língua inglesa o poder de penetração é maior. E até engines como a do branquelo acabam aumentando essa diferença. Mas o cara dizer que não conheçe nenhum gerador (ou seria, renderizador) semelhante é uma abscência total de informações. E não estou falando do Merlin, mas de coisas bem mais antigas, como o DRIVE, ITE, FUSE, AME, MASTERMIND, HUMANOID, UIDE, MECANO e, claro, o bom e velho Metagen...

Conclusões

Quatro.

Se temos concorrentes, é porque temos nicho de mercado.

Se a forma de implementar é quase a mesma, é porque estamos fazendo certo (ou estamos errando junto!).

Se os releases do Merlin demorarem a sair, não precisam sair mais.

E se não aprendermos inglês logo, de nada adianta ter releases.

0 comentários: