terça-feira, 6 de maio de 2008

Sessão Nostalgia: Metagen, o pai do Merlin

NOTA: Para quem não conhece o Metagen, sugiro a leitura do documento Sistemas Dinâmicos Baseados em Metamodelos, disponível na área colaborativa do Merlin.

O que é o Metagen?
O Metagen foi nosso (meu e do D. Moreira) primeiro esforço para criação de um sistema de renderização em runtime de interfaces CRUD, ou seja, as telas de cadastro.

Na prática, a idéia não era muito avançcada; ela apenas colocava ênfase para o fato que não precisávamos muito mais do que algumas heurísticas para criar controles de tela durante o uso do sistema, evitando a geração de código-fonte - coisa que sempre odiamos. A idéia era simples e, essencialmente, ela foi evoluindo aos poucos.

Quando iniciei meus trabalhos de programação de telas de cadastro (ainda em Visual Basic 6), eu havia pegado muitos trechos de código repetitivos (meu ex-colega devia ser fã do Control-C, Control-V...). Logo pensei: pô, vou criar um método utilitário aqui!

O embrião: um método utilitário para carregamento de comboboxes
Lembro como se fosse hoje. O trecho de código utilitário que fiz, nada era além de umas 15 linhas de código que recebiam como parâmetro o nome de uma tabela e de um campo, e montava o comando SQL para preencher uma combox. Esse foi o início do Metagen e, por consequencia, o início do Merlin.

Logo, aquele método foi crescendo: mais parâmetros foram colocados e mais funcionalidades ele suportava, como cláusula WHERE, ORDER BY, concatenação de campos, etc.

Algum tempo depois o método nem retornava mais uma coleção de registros para ser colocado em uma comboxes: ele literalmente retornava a combox, a qual era tão colocada no formulário em tempo de execução.

Isso foi em 2002, se não me engano.

O Metagen
Aquela coisa de retornar controles e colocá-los em formulários em tempo de execução era legal, e logo eu estava criando não só comboxes, mas também textfields, labels, botões, checkboxes e outras coisas.

O tempo passava, e as funcionalidades aumentavam. Lembro ainda do dia que chamei o Moreira para a cozinha do café e disse: cara, consegui fazer o bind de métodos em tempo de execução; acho que agora podemos ter aquilo que queríamos.

O que queríamos (bem, pelo menos eu), era um gerador de telas de cadastro, que me retiresse o fardo de criar aqueles famigerados (acho essa palavra muito legal) artefatos de software todos os dias. Uma nova era estava surgindo.

Baseado em texto
Logo logo, nossos conceitos evoluíram, e de código estático de geração, tínhamos estruturas configuráveis a partir de arquivos INI.

Esses eram (ou deveriam ser) gerados por outro utilitário que importava modelos do erWin (conhecem?) através de uma API muito legal (ahaha, como eu gostava desse tempo)....

Delphi e Kylix
O sucesso pareceia certo. O projeto evoluía e já tínhamos migrado para Delphi e, então, Kylix (lembram?), para rodar no Linux também. Época boa, onde tudo parecia fácil.

Foi mais ou menos naquela época que publicamos o artigo acima e que fizemos algumas apresentações do projeto em alguns eventos na região central do Estado.

JH Santos
A coisa ia de vento em popa, e então decidimos que era hora de abrir uma área de pesquisa - nem era, nem poderia ser um negócio, embora querêssemos que fosse.

Saíamos do trabalho e íamos para lá. Levávamos coca-cola, pizza, cachorro-quente, xis (embora essas duas últimas iguarias não eram apreciadas por mim) e café, muito café. Brincávamos de programar em Delphi e fazíamos testes com diversas coisas.

O local? Bem, era uma sala num prédio da antiga...

Mais um para o fim
Mas queríamos mais. E mais significava que precisávamos ter alcance web.

Porém, nem eu nem o D. manjavam de web, e então abrimos "a jogada" para um outro colega, o J.

Agora tínhamos uma equipe de três bonecos: um centrado, um pirado e outro maluco. Orbitávamos em nossos devaneios e rodávamos para lá e para cá.

Acho que a coisa não foi muito para a frente porque, libertos como estávamos, acabamos mirando em muitos lugares e quando parei de contar, eu estava em 1.200 horas de pesquisas que envolviam desde RMI, Delphi, VB, EJB, Hibernate, JDO, Eclipse, Netbeans e ... pára por aí. Acho que não dá mais.

Isso foi em 2004.

Merlin, o renascimento
Não que três fosse demais. Muito pelo contrário. Até hoje acredito que 3 é o número ideal: 3layer diz alguma coisa?
Visto que a JH não era mais nosso lugar, precisávamos de algo novo para brincar. E fomos para o mundo. O mundo livre.

O projeto Merlin fora criado no JavaNet e as brincadeiras lá continuaram.

2005 foi um ano difícil para mim, mas que teve uma recompensa inigualável. E quem me conhece sabe o motivo. Também nesse ano, a 3Layer Tecnologia teve sua pedra fundamental lançada: ganhamos um CNPJ :)

2006 foi um ano de recuperação e 2007 de preparação.

Agora, em 2008 estamos com uma bagagem sólida de estudos - sim, são praticamente 7 anos lapidando essas coisas de telas de cadastro!

Estamos nos focando em transformar a coisa em algo sério, e ao invés de brincar, revolucionar.

Antes de terminar...
...mostro uma tela de cadastro gerada pelo Metagen:



Isso é o que gerávamos em 2003 com o Metagen. Para cada campo na tela, algo em torno de 11 propriedades no arquivo INI eram necessárias. Tínhamos um fraco, mas funcional, suporte para ligação de regras de negócio e as telas eram 100% livres de erro de programação.

E esse, bem por cima mesmo, foi o começo...

quinta-feira, 1 de maio de 2008

Criando layouts malucos com o Merlin

Nenhum renderizador (ops, gerador) de tela é completo se não suportar uma customização total das telas que ele gerar. E não estou apenas falando de customizações simples, como a reordenação de campos ou a aplicação de CSS sobre um formulário.

Estou falando de revolucionar (adoro essa palavra) as coisas e criar um layout totalmente piscodélico, incluindo span horizontal ou vertical, disposição circular de elementos, transparências e mesmo sobreposições (z-order) de controles.

O Merlin suporta tudo isso, e a feature é chamada simplesmente de Layout Maluco. Porém, antes de falar dele, vai uma breve introdução sobre os tipos de customização de layout suportados pelo Merlin.

Tipos de Customização Suportadas
Desde o princípio, o Merlin foi projetado para suportar 3 tipos de customização de layout:

1. Simples (use anotações): São aquelas corriqueiras, onde o objetivo é apenas dar uma “aparada” no que o renderizador de layout atrelado produz. Isso inclui reordenação de campos, subtituição de tipos de controles, reposicionamento de labels descritivos, definição de resizing (vertical ou horizontal) e algumas outras pequenas features que, na prática, dependem muito do renderizador de layout associado ao bean.
O Merlin disponibiliza alguns renderizadores “built-in”, sendo que essas features que comentei são suportadas por eles.
Na prática, customizações simples são feitas apenas através de anotações sobre os beans e suas propriedades.

2. Complexas (crie anotações e renderizadores): Quando você deseja algo a mais, e as anotações built-in oferecidas podem não ser suficientes, e você pode precisar criar novas anotações ou modificar (ou adicionar, estender, ou remover) os renderizadores existentes.
Por exemplo, digamos que você tem um controle de tela um pouco diferente, como um StackPanel ( do GWT, que agrupa controles em uma barra vertical) e queira que as propriedades de beans que são coleções tenham seus elementos exibidos dentro desse controle na tela. Solução? Marque o controle com @RenderAs(value=StackPanel.class,binder=MyStackPanelBinder), onde MyStackPanelBinder é a classe que você criou e que se responsabiliza por traduzir a coleção de objetos no StackPanel e vice-versa (saiba mais ou assista o demo).

3. Malucas (eu quero como eu quero!): Noutras (existe essa palavra?) vezes, a coisa encrespa mesmo, e a tela de cadastro que tem de ser criada é totalmente pirada (usuários têm disso). Nesses casos, a solução mais rápida ou efetiva é não criar nada de novo, e sim reusar coisas prontas. O restante do post mostra mais detalhes sobre esse tipo de coisa.

Criando um Layout (ainda nem tanto) Maluco
No primeiro release do Merlin, que deve incluir o suporte para o pacote gráfico Swing, a engine de renderização padrão é o JGoodies Forms. Essa biblioteca é muito prática, de rápida assimilação e, principalmente, projetada para suportar diversos dispositivos gráficos (MacOS, Windows, JavaME, etc.) sem degradação de qualidade.

O exemplo que vou mostrar é em cima dela, mas lembre-se que essas regras valem para qualquer pacote gráfico que você escolher.

Vamos supor que o usuário quer uma tela como essa:



Essa tela apresenta 2 labels e 3 controles, sendo duas caixas de texto e um botão. Nos controles de texto, as setas indicam o redimensionamento que irá ocorrer no caso do usuário modificar o tamanho da tela.

Para fazer isso no Merlin, temos duas formas.

A Primeira Forma: Usando Posicionamento Manual
Usar posicionamento manual significa que, para cada controle a ser exibido na tela, uma anotação @Pos é colocada sobre uma propriedade do bean. Nesse exemplo, o bean associado seria como:

@Layout(impl=JGoodies.class, init="'p, 4dlu, 40dlu, 15dlu, p, 4dlu, 25dlu:g', '30dlu, 20dlu, 15dlu:g'")
class Bean {

@Pos(value=“3,1,1,3”, captionAt=”1,1”)
String nome;

@Pos(“7,2”, captionAt=”5,2”)
String historico;

@Pos(“5,1”)
@RenderAs(JButton.class)
String importar;
}

Não entendeu nada?

Bem, primeiro o que fizemos foi informar para o Merlin utilizar um gerenciador de layout diferente nesse bean. Isso foi feito com a anotação @Layout. Nessa anotação, passamos como parâmetro a classe JGoodies.class, que é uma classe utilitária (nesse caso built-in do Merlin) que representa a implementação de gerenciador de layout a ser utilizada. Na prática, ela é uma classe Delegate, que encarrega-se de receber alguns parâmetros (pelo atributo init) e repassá-los para o gerenciador de layout, no caso, o próprio JGoodies Form Layout.

Depois disso, informamos que dentro desse layout, os controles devem ser posicionados conforme a anotação @Pos. Essa anotação nada mais faz do que informar as posições exatas em que as propriedades devem ser exibidas, tal como em layouts na web: em outras palavras, Linha, Coluna, Span Horizontal e Span Vertical. O atributo #captionAt indica a posição em que deve ser colocado o label descritivo associado ao controle.

Para o caso da propriedade “importar” (que já vai ser renderizada como um botão devido a presença da anotação @RenderAs), não precisamos de um label descritivo e, assim, simplesmente não usamos a propriedade #captionAt.

A Segunda Forma: Usando Ferramentas WYSIWYG
WYSIWYG é acrônimo de What You See Is What You Get, e significa literalmente isso: Você simplesmente usa seu editor WYSIWYG preferido, como o Netbeans ou o Visual Editor do Eclipse e cria a sua classe visual. Feito isso, você passa ela como parâmentro para o Merlin no método createIU.

A única coisa que você deve ter em mente é que os controles criados no editor WYSIWYG devem ter o mesmo nome daqueles que serão renderizados pelo merlin.

Usando essa abordagem, o bean pode ser “oco”, como:

class Bean {

String nome;
String historico;
String importar;

}

Mas como funciona isso?

OK, você tem o bean oco. Ao ser renderizado esse bean, o Merlin vai gerar (por padrão, e o que pode ser customizado também) os seguintes nomes de controles: bean.nome, bean.historico, bean.importar. Assim, quanto voce estiver criando sua classe visual com layout realmente psicodélico (usando o SpringLayout do Netbeans, por exemplo), você coloca na propriedade #name dos componentes os nomes indicados acima.

É isso, simples assim? Quase, o último passo é extremamente complexo: você deve chamar o método createIU com um parâmetro extra, que é justamente a sua classe criada no Netbeans.

Por exemplo: merlin.createIU(Bean.class, TesteLayoutMaluco.class).

O Merlin simplesmente “varre” cada propriedade do bean e tenta localizar um controle equivalente na classe de template (o seu form). Quando encontra, ele faz a substituição, ou seja, ele renderiza a propriedade do bean na exata posição em que se encontra o controle equivalente no form. O tipo do controle a ser renderizado vai depender do tipo de controle que você colocou no seu form, ou, existindo a propriedade @RenderAs na propriedade do bean, usa-se essa.

Qual usar?
Bom, se considerarmos o que Karsten Lentzsch afirma (que o JGoodies abrange 90% dos layouts para cadastros – e eu concordo veementemente com ele), a resposta é justamente esta: em 90% dos casos você vai criar layouts malucos usando a abordagem do @Layout + @Pos. E lembro, que o mesmo esquema de posicionamento vale para outros frameworks gráficos, como o GWT ou JSF

Agora, se você realmente não quer se preocupar com cálculos de posicionamento (o que é uma pena, pois a experiência mostra que a maioria dos layouts feitos em IDEs não suporta redimensionamento, escalonamento de fonte, troca de ambiente – Windows, Mac, etc. ou um simples ajuste de resolução de tela…) e quer usar ferramentas WYSIWYG, vá em frente. Você não precisa usar nenhuma anotação e pode desenhar as telas livremente, usando o Merlin para fazer o trabalho sujo de binding, validação, tratamento de eventos, etc.

quinta-feira, 24 de abril de 2008

Customizando telas com o Merlin

Este é o primeiro de uma série de posts que devem vir sobre como o Merlin suporta a customização das telas de cadastro.

Muitos desses posts são idéias que podem se concretizar ou não. Enfim, o que vale é o espaço para discussões, objetivando chegar à melhor solução.

Uma tela simples

Supomos que temos um bean muito simples, como:

class Pessoa {

String nome;

String historico;

}

Para esse bean, ao fazer a geração (ops, renderização!) da Tela de Cadastro com o Merlin, chegamos a isso:

Como não existe informação de contexto alguma, esta tela é o melhor que podemos fazer nesse momento.

Evoluindo as telas simples

Porém, o usuário espera que o campo historico seja um campo textual para escrever bastante coisa, e assim, usando uma anotação do próprio Hibernate, podemos fazer a evolução:

class {

String nome;

@Length(max=5000)

String historico;

}

Com isso, o resultado da renderização da tela de cadastro é algo como (as setas indicam o redimensionamento):

Mais evoluções

Mas, mesmo assim, o usuário não está satisfeito. Ele quer um resultado como:

Nessa tela, o campo historico continua sendo renderizado como uma caixa de texto simples e possui um botão extra que, ao ser clicado, abre uma outra tela para então, aí sim, termos todo o texto de histórico do cliente!

Como conseguir isso usando o Merlin?

class Pessoa {

String nome;

@Length(max=5000)

@RenderAs(JtextField.class)

String historico;

@RenderAs(value=JButton.class, init=”text='...'”)

@Agent(event=”onClick”, event=”showPopup”)

@Merge(“historico”)

String botao;

}

E pronto. E pronto? Mas como assim?

Explicação

A primeira anotação @RenderAs, indica que o campo historico deve ser mostrado como uma caixa de texto, que será redimensionável horizontalmente (devido o tamanho de 5000), mas que terá apenas uma linha (pois é uma caixa de texto, e não um “textArea”).

A segunda anotação @RenderAs faz com que o campo botao seja renderizado na tela de cadastro como um botão com a propriedade text inicializada com uma String de reticências.

A anotação @Agent adiciona um tratador de eventos ao controle, indicando que ao ser clicado, o método showPopup seja executado (vide mais informações ao final do post).

A anotação @Merge é o kernel da coisa. Ela implica que o botão renderizado seja combinado ao texto do histórico. Em outras palavras, é como se o controle de histórico fosse encapsulado em um painel e nesse painel também fosse adicionado o botão. Essa anotação suporta mais coisas, como a especificação de um layout diferenciado para esse painel, eventos, etc. Mas não precisamos disso aqui. Na prática, essa anotação é muito parecida com @Group, a qual devemos falar em outras oportunidades...

Conclusões

Essa tela de cadastro é bem simples, mas a idéia é essa mesmo.

Como estamos iniciando o nosso framework, nada melhor do que pensar em situações que podem ocorrer e, conforme conseguirmos resolvê-las, irmos incrementando-as em complexidade.

A cada passo, devemos olhar o passado e tentar manter a compatibilidade ou, então, repensar as coisas. É assim mesmo.

Estamos fazendo várias simulações “em casa” e, tão logo tenhamos tempo para postar, bem, é isso que faremos :)

Mais explicações

O leitor atento vai questionar: Mas o Swing (que é o pacote UI inferido no exemplo devido o uso do Jbutton e do JTextField) não possui um evento onClick. Como se explica isso? Como funciona?

Rapidamente, a resposta é: O Merlin suporta aliases de nomes (e não só para eventos, mas para tudo – classes, métodos, etc.). Logo, tanto faz se escrever onClic, doClick, actionPerformed, etc. E o melhor de tudo, é que esses aliases são criados conforme o gosto do usuário e de forma facilitada, propagando-se (ou não) por todo o contexto da aplicação e mesmo de várias aplicações, caso seja de interesse. E claro, são intercambiáveis entre pacotes gráficos diferentes. Uma loucura, como diria um amigo meu...

A segunda pergunta é: E o método showPopup? Este método é obtido por inferência de proximidade. Primeiro, o Merlin tenta localizá-lo no próprio bean vinculado à tela. Não encontrando, procura métodos de aliases no contexto do formulário (por exemplo, se usado Web Beans ou Seam, seria um método de EJB ou análigo que tivesse a anotação @WebMethod) ou códigos de scripting (groovy, beanshel, etc) associados ao formulário. Se não encontrado, ele procura na hierarquia de classes do bean. Se encontrado, ele instancia esse bean e executa o método. Não encontrando, ele procura pelo escopo (primeiro) da aplicação – partindo dos pacotes mais próximos ao bean, e (depois) por todas as aplicações atingíveis pelo classloader da aplicação corrente. Nesse caso de busca por escopo, ele procura primeiro por classes com métodos públicos anotados com @Action (em classes ou métodos) e depois por métodos públicos somente. Toda essa busca é built-in da ferramenta, podendo ser customizada, sobreescrita ou desabilitada.

E ao leitor mais “bicudo” (ahah, lembrei o apelido que eu tinha na época que eu fazia curso de computação antigamente...) vai questionar? E como os parâmetros são passados para o método showPopup? No caso onde o método está diponível no próprio bean, não tem mistério: é acesso direto. Para os outros casos, é possível implementar uma interface InvocationContext, tal como no mundo dos EJBs ou usar a anotação @In, como no mundo do Seam/Web Beans. Outra forma é usar a API da ferramenta.

sexta-feira, 21 de março de 2008

Drools, uma solução para o sistema de histórico?

No texto-base do Merlin, tive que deixar de fora o tema do sistema de configuração baseada em histórico, visto que a complexidade é (e sempre foi) muito grande.

Para se ter uma idéia das coisas envolvidas, o glossário do projeto (sempre em construção), aborda temas como Distanciamento Temporal, Espacial e Relativo de classes. São coisas - e até eu concordo - bem malucas :)

Sempre pensei que esse fosse o ponto mais complicado do framework. Embora eu tenha muito bem definido suas premissas, e suas heurísticas sejam muito bem aceitas (quando corretamente explicadas) pelos ouvintes em fóruns, apresentações e/ou conversas de bar, o fato é que implementá-las sempre foi um desafio.

Minha idéia inicial, após muito fritar os neurônios, foi usar um esquema semelhante aos validadores de beans, os que me constam apareceram pela primeira vez no Hibernate Validator.

Entretanto, tive que fazer adaptações, visto que o Merlin deve suportar quaisquer anotações, ou seja, mesmo aquelas que não foram projetadas para ele. Assim, o simples uso do conceito de validadores (como no Hibernate Validator, e agora na JSR 303), não seria aceitável.

Embora a solução atual, chamada de Resolvers, funcione a contento, o fato é que eles deveriam se preocupar ainda como todo o esquema de "entendimento" do histórico de configurações para, então, resolverem (desculpem o trocadilho) as anotações.

JBoss Rules, a centelha
Nesta semana, mais precisamente na tarde da segunda-feira, de alguma forma, o JBoss Rules me veio à cabeça, e decidi dar uma olhada mais a fundo nele. A ficha caiu.

Todo o esquema de regras de tradução dos beans na IU no Merlin pode ser feito com base no JBoss Rules, ou simplesmente, Drools.

Isso ocorre porque, conforme as complexidades das regras de tradução aumentam, a tendência que ocorram conflitos entre elas aumenta exponencialmente. Colocar um caption à esquerda ou acima de um controle pode depender de inúmeras variáveis e condições do contexto de execução. O Drools resolve isso.

O Velho Modelo ECA Simplificado
O modelo ECA (Evento, Condição, Ação) já é bem conhecido, fazendo parte de frameworks gráficos MVC e outros. Para quem programa em Swing, vai o exemplo:

public actionPerformed(Event event) {
if (user.getUserName().equals("joao")) {
System.out.println("O nome é João");
}

Nesse código acima, o evento (E) ocorreu em um controle na tela. Nesse momento, uma condição (C) é testada e, caso ela seja verdadeira, uma ação (A) é executada. Eis o modelo ECA.

O JBoss Rules, usa algo bem parecido, até mais simples: When Then. Veja o exemplo:

rule "João clicou num controle"
when $user.name == "joao"
then System.out.println("o nome é João")

Simples, não?

Vantagens
Nesse pequeno exemplo, já se percebe a clareza da programação, a qual se assemelha muito à Expression Language (EL) ou Groovy. Para exemplos mais avançados, o usuário vai perceber uma analogia muito grande com a Object Constraint Language (OCL) e outras linguagens de mais alto nível.

Mas tudo isso não é nada se comparado às capacidades do kernel de inferência da ferramenta, o qual é baseado nos trabalhos de Charles Forgy lá nos idos de 1974, onde ele definiu as basas do algoritmo RETE.

Em palavras simples, esse algoritmo é responsável por computar a panacéia de regras (muitas conflitantes entre si) em grafos de objetos (que são a base de dados do Drools) e eleger a regra a ser executada. Traduzindo em miúdos, é este kernel de inferência que acha e resolve as heurísitcas que o Merlin tanto defende.

Conclusões
Não entrei em detalhes do Drools, e nem pude ler um artigo completo ainda. Mas vou colocar no Jira um espaço de horas para identificar melhor seus atributos e fazer os testes necessários.

Obviamente temos drawbacks, como deixar de usar Java nativo para criação das regras - uma coisa que eu não queria. Mas imagino que essas regras podem ser definidas e viculadas através de classes adaptadoras e, logo, é provável que isso não represente um excessivo impacto.

O Drools é bem servido de ferramentas e a duplinha JBoss/Red Hat está por trás. Sendo assim, nada mais justo que confiar nos caras e especular mais sobre o assunto. E é o que iremos fazer.

sábado, 8 de março de 2008

Force


Nesse exato momento estou no La Fiama (uhu, mano Roger) e com 1 garrafa de Duetto da Casa Valduga na mente. Porém, acredito que essas sao minhas melhores horas de produtividade. Assim, sem mais delongas,
vai meu primeiro post pelo gmail do meu W810i:

quinta-feira, 6 de março de 2008

Repositório do Merlin disponibilizado

É com grande alegria que publico este post. Finalmente, após vários e vários meses de enrolação, finalmente consegui colocar o código-fonte do Merlin no nosso servidor. Em http://3layer.no-ip.info:6666/svn/public/merlin é possível baixar o códugo do repositório do Subversion.

O que foi disponibilizado
Nesses longos meses de trabalho, muita coisa evoluiu conceitualmente no projeto. As idéias sobre configuração baseada em histórico e por proximidade já estão bem enraizadas e não são as grandes novidades. Tampouco conceitos como Agentes e Binding, mas uma feature que veio à tona durante os trabalhos no código-fonte foi a questão da Injeção de Dependências, isso sim uma grande novidade. No post anterior eu comento bem isso, a qual o impacto no projeto.
Quanto ao código disponibilizado, para quem baixar, não vai perceber uma maravilha do projeto OO. Vai ver algo como uma macarronada de código, com nomes de classes duvidosos e pacotes nem de todo consistentes. Mas, enfim, agora está disponível e é nele que trabalharemos pelos outros próximos longos meses e, espero, anos.
As features disponíveis no código são várias, porém ainda em nível de experimentação. Temos Agentes funcionando, Binding, Layout, algumas anotações, Dependências de controles, um sistema de recarregamento de classes e algumas outras funcionalidades de menor tamanho.

Working in Progress
Os trabalhos atuais incluem a criação dos Resolvers (Resolvedores de Anotações) e, principalmente, uma estabilidade e independência nos pacotes genéricos; em outras palavras, retirar toda e qualquer dependência em relação ao pacote Swing, que está sendo usado como base para a implementação.
Resolvers, para quem não sabe (e até agora somente eu sei - hic) são tratadores de anotações. No código atual, as anotações têm um tratamento rudimentar e engessado (detesto essa palavra...se alguém souber uma melhor, me avise). Ou seja, não consigo mudar comportamentos para o tratamento de anotações. Da mesma forma, para qualquer nova anotação que for definida, alterações de baixo nível devem ser feitas no mecanismo de geração. Os Resolvers vem para....resolver isso!
Em suma, qualquer anotação pode ser interpretada pelo Merlin: as dele, as de q ualquer framework existente e, claro, as que você mesmo criar ou quiser reutilizar de sistemas de legado. De forma geral, um Resolver aponta para uma anotação e se encarrega de interpretá-la da forma que achar melhor. Depois, pluga-se o Resolver na engine de geração e pronto. As formas com que isso será feito ainda estão em banho-maria, mas imagino uma coisa bem complicada: colocar o Resolver no classpath do sistema, tal como funciona a instalação de plugins no Eclipse :)

Configuração realimentada
O famigerado sistema de configuração do Merlin é a coisa mais complexa da ferramenta. Eu, particularmente, acho que é a mais complicada de tudo que posso imaginar e, com certeza, mais complexa de tudo que já vi. De fato, é tão complexa que na Dissertação de Mestrado sobre o Merlin ela foi deixada de fora para tema de Doutorado. Com todos que comento (e algumas dessas pessoas eu até acho que elas compreendem sobre o que eu estou falando...), a resposta é sempre a mesma: isso não vai funcionar.
Conceitos como Distanciamento Temporal, Distanciamento Espacial Real, Distanciamento Espacial Relativo e outros são palavras-chave nesse mecanismo. Imaginar até é factível; implementá-lo, com certeza é bom um desafio.
Estou juntando as informações necessárias e os commits devem ser diários, ou semanais, conforme o tempo me sobrar.

Status e Acompanhamento
O release ALPHA do Merlin já tem data para sair: dia 02 de Outubro. Marquei-o para o dia do meu aniversário.
Para quem quiser acompanhar o andamento das coisas, vão dois lugares essenciais:

Atividades do Projeto : http://3layer.no-ip.info:6666/jira/browse/MERLIN
Repositório Colaborativo : http://3layer.no-ip.info:6666/confluence/display/MERLIN

segunda-feira, 25 de fevereiro de 2008

Injeção de dependências

Breve. Espero :)

No Merlin, a ligação de regras de negócio aos elementos de IU é feita através de anotações, mais especificamente pela anotação @Agent, cujo uso pode ser visto abaixo:

public class Cliente {

@Agent(event = {"focusLost"} , action ] {"fillEmail"} )
String nome;

String email;
}

Neste trecho de código, está sendo definido um tratador para o evento de perda de foco no controle de tela que armazena o nome do cliente. Quando este evento ocorrer, o método de negócio fillEmail() é invocado.

Observa-se que, como o Merlin usa listas invertidas baseadas em proximidade, não é necessário especificar onde esse método de negócio reside (exceto no cas0 de colisões de nomes - as quais são devidamente reportadas tanto em tempo de projeto, de compilação ou de execução, conforme o caso).

Da mesma forma, é transparente se esse método é um método de uma classe (de qualquer visibilidade ou escopo), um webservice, um método de EJB ou mesmo nativo (novamente, são inferências e, em caso de ambigüidades, detalhamentos devem ser realizados).

O detalhe presente é: Como são passados os parâmetros para que o método fillEmail() seja executado ?

Hoje, o Merlin tem métodos utilitários, e uma possível implementação de fillEmail() seria:

public class AlgumaCoisa {

void fillEmail() {

JTextField nome = (JTextField) MerlinUtil.getControle("cliente.nome");
JTextField email = (JTextField) MerlinUtil.getControle("cliente.email");

email.setText( nome.getText().trim() + "@3layer.com.br");
}

Essa abordagem funciona sem problemas. Entretanto, a implementação fica dependente do pacote gráfico (no caso, o Swing) e a quantidade de código burocrático para recuperar os controles de tela pode ser demasiada.

Injeção de dependências, Groovy e Seam

Visando facilitar as coisas (e também deixar o código transparente quanto ao pacote gráfico), uma versão com injeção de dependências e recuperação automática de contexto, implicaria em um código como:


public class AlgumaCoisa {

@In
Context ctx;

void fillEmail() {

ctx.eval("$email.text = $nome.text.trim + '@3layer.com.br'");

}

ou

public class AlgumaCoisa {

@In
JTextField txtEmail;

@In
JTextField txtNome;

void fillEmail() {

txtEmail.setText(txtNome.getText().trim() + "@3layer.com.br");


}

Todas as três implementações de fillEmail() fazem exatamente a mesma coisa. O diferencial das duas últimas é que o contexto do formulário do cliente foi injetado automaticamente no método fillEmail(), de forma que a recuperação dos valores existentes na tela seja facilitada.

Na segunda implementação, código Groovy é executado e, portanto, nenhuma dependência de pacote gráfico existirá. Observa-se que a variável Context é do Merlin, e armazena toda a conversação do formulário.

Na terceira implementação, o programador possivelmente desejou uma maior clareza sintática, e assim, ele fica dependente do pacote gráfico.

A anotação @In é "herdada" do JBoss Seam. Com essa abordagem, estamos atentos à JSR 299, que acredito ter um draft ainda este ano.

Conclusões

A injeção de recursos é uma realidade hoje e uma tendência para o futuro. Agregada à flexibilidade de linguagens de scripting, como o Groovy, códigos que usam recursos de IU tendem a ficar cada vez mais transparentes e, quem sabe, realmente independentes de pacotes gráficos.

No exemplo dado (na segunda implementação), o método fillEmail() funcionaria sem problemas na maioria dos pacotes gráficos existentes.

quarta-feira, 30 de janeiro de 2008

Merlin humilhado na CHI2008

Acredito que tantas as boas, quanto as más notícias precisam ser divulgadas. É assim que crescemos e evitamos pisar em pedras que afundem.

Como comentei em um post anterior, enviei um artigo do Merlin para a sessão de trabalhos em desenvolvimento do CHI2008. O artigo era em inglês. Não esperava muita coisa, pois, exceto minha língua mãe, meu vocabulário ainda é reduzido.

A data do resultado era hoje, e há poucos instantes veio o email.

O resultado
Em uma palavra: humilhado. Sim, foi assim que me senti. Foram três revisores, dois com expertise (?) na área e, sim, três "definitive reject".

Segundo as revisões dos caras, o Merlin não inova em nada, é superado por abordagens existentes (como a usiXML, OpenLaszlo, uiML, um tal de jguigen que existe no SourceForge e por ferramentas built-in de frameworks como o Ruby e outras) não otimiza processo algum de desenvolvimento e implica em "trabalho às cegas" (ou quase isso).

Completando (e isso sim eu acho que eles podem ter certeza mesmo), estão declarações como "o trabalho apresenta frases disconexas" ou "a estrura gramatical é fraca e apresenta inconcordâncias frequentemente".

E, enfim, claro, o trabalho não foi aceito.

O que eu acho
Fico triste, claro. Mas não entregue.

O Merlin tem 6 anos de vida e, embora ainda não esteja implementado, os conceitos que o fundamentam são baseados em mais de três plataformas de desenvolvimento (VB, Delphi, .Net e Java) e é fruto de uma experiência em mais de 20 projetos desenvolvidos. Não posso concordar com os caras.

Mas, tal como aprendi há muito tempo, o negócio é aceitar. E de preferência, com parcimônia porque, enfim, o tempo é o senhor da razão e até os grantes dizem coisas meio estranhas.

quinta-feira, 10 de janeiro de 2008

Merlin agracia Atlassian

É com grande alegria que publico esse post. A Atlassian, empresa que desenvolve e comercializa o mundialmente famoso software para controle de pendências Jira, acabou de disponibilizar 3 licencas free para a 3Layer Tecnologia aplicar sobre o Merlin.

Os produtos
Os produtos que a 3Layer ganhou direito de uso gratuito são o já conhecido (e diga-se de passagem, muito bom) Jira, o Confluence e o FishEye.

O Jira pode ser visto como o primo rico do Bugzilla. Com preços de mercado entre U$ 600 e U$ 2.400 é um produto robusto e extremamente configurável. Utilizado para controle de pendência, suporta vários plugins e pode facilmente ser usado como ferramenta para gerenciamento de projeto, substituindo ferramentas tradicionais da gigante azul, como o MSProject ou o comunitário dotProject.

O Confluence é um serviço de wiki com portal, que pode ser integrado ao Jira e tem muitas funcionalidades. Ambos podem operar sob SingleSignOn, compartilhando a base de usuários.

O FishEye é um visualizador de repositórios de versões, suportando o CVS, Perforce e o Subversion, o qual é o padrão da 3Layer para seus projetos. Também pode ser integrado ao Jira e ao Confluence de forma bastante simples.

As vantagens
Uma das premissas da 3Layer é desenvolver software livre e utilizar ferramentas ou open source ou gratuitas em todas as áreas da empresa. Amparando-se muito em soluções horizontais, a empresa não vê empencilhos e usar como ferramenta de trabalho soluções como o Google Calendar, Gmail, Groups, GTalk ou Docs.

Entretanto, para determinadas situações, uma maior robustez é necessária. Nesse sentido, abrir mão de um produto como o Bugzilla ou o Jira em troca de um Google Issues (que diga-se de passagem não é ruim; apenas limitado) seria um empecilho para a gerência e controle dos projetos.

Visto que as licenças do Jira e seus "amigos" poderia elevar os custos operacionais do projeto Merlin e que o Bugzilla não é baseado em Java (outra premissa da casa); a possibilidade de uma licença sem custos era uma mão na roda para todos os envolvidos.

A solicitação e os direcionamentos
Algumas modificações precisaram ser feitas no projeto Merlin para que isso fosse possível.

Primeiro, já era acordo entre os desenvolvedores a migração do projeto Merlin para o Google Code, visto sua maior velocidade frente ao site do Javanet e também as melhorias de uso (usuários integrados ao Gmail, Calendar, Docs, Groups) e o suporte à wiki. O suporte do SVN no Google, entretanto, não é uma vantagem. Pelo contrário, na verdade ele é mais uma dificuldade, visto que a falta do suporte ao "lock" de arquivos - requisito para o uso da ferramenta CASE Enterprise Architect, base do projeto. Entretanto, outras possibilidades estão sendo estudadas. O fato é que este foi o primeiro passo: ir para o branquelo.

O segundo passo foi substituir a licença original do Merlin (a Eclipse Public Licence) pela Apache 2.0. Em princípio, não vemos maiores dificuldades nisso, uma vez que o Merlin têm uma política de versões estrategicamente projetada tanto para proteger os nossos esforços, quanto para dar um gás para a comunidade Open Source. Então, esse foi o segundo passo.

O terceiro passo foi entrar em contato com a Atlassian e pedir as licenças. Em menos de 10 dias, ganhamos a aprovação e hoje, esse post comemora isso.

Pobres. Ainda.
Como último comentário nesse longo post, fica a mensagem: meu note deve ter saturado nesses dias. Para conseguir a licença, a instalação dos produtos Jira, Confluence e FishEye devem estar abertas para a Internet.

Assim, como ainda não temos nosso servidor pronto e tampouco um IP fixo, tive que recorrer ao NO-IP para colocar um DNS dinâmico para a minha máquina e abrir as portas do roteador para as instalações alpha no meu note. Bem "coisa de mirim", mas que devemos estar corrigindo nos próximos dias.

terça-feira, 8 de janeiro de 2008

Artigo enviado para o CHI2008, na Itália

É com satisfação que informamos que o artigo Exploiting Runtime User Interfaces foi submetido ao CHI2008. Este é o primeiro artigo em inglês sobre o Merlin e, embora seja um short paper, ele está sendo enviado para um dos maiores eventos mundiais da área de Interface de Usuário.

O evento
O Computer Human Interaction (CHI) é um evento que ocorre desde 1982 e tradicionalmente agrega pesquisadores e projetos de renome da área da interação humano-computador. Este ano o evento acontece em Florença, na Itália, entre os dias 05 e 10 de Abril e o site do encontro é http://www.chi2008.org.

A escrita
Foi no dia 02 desse mes (6 dias atrás) que, procurando por eventos da área de IHC, acabei encontrando o CHI desse ano. Os deadlines já estavam estourados desde Setembro passado (o que é uma dica para o próximo ano), mas a sessão Work-In-Progress ainda estava aberta - até hoje!

Pestanejei um pouco, mas acabei baixando o template de artigo. Abri o Word e me toquei a digitar. Com o auxílio do Babylon, BabelFish e GoogleTranslate, acho que consegui chegar lá. Foram 6 páginas em, pasmem, um formato muito bom de escrever: fonte verdana, layout de página limpo e uma boa cepa de estilos para título, cabeçalhos e refências (estas no formato IEEE - veja nota de rodapé)

A espera
Bem, agora é esperar. Não sei se o texto está bom ou não. Nunca fiz curso de inglês e tenho dificuldades para fazer esolhas simples entre um "is" e um "are". Mas tudo bem, quem não arrisca...não tem chance (ahah, pensaram que eu ia usar aquele trocadilho, hein!). Dia 30 agora deve estar saindo o resultado das aprovações. Assim que o retorno vier, estaremos com a notícia aqui, seja boa ou nem tanto :)

_____
NOTA: Para quem já usa a notação de referências do IEEE (aquela onde as referências são feitas por números, como [1] ou [4,5,6]), já deve estar acostumado com o que ocorre. Eu não estava, e me supreendi. Em outras palavras, como essa numeração é organizada de forma alfabética pelo sobrenome dos autores do trabalho, ocorre que, no texto onde a referência aparece, as diversas obras de um autor acabam aglutinado-se. Por exemplo, eu tinha três trabalhos que falavam de um mesmo assunto. Assim, ao referenciá-los, não deu outra: [n, n+1, n+2]. É bem interessante isso, pois fica fácil para o leitor encontrar todos os trabalhos de um autor juntos na área das referências. E também fica fácil para o cara que escreve, colocar as referências em série, uma junto à outra. De quebra, o texto fica mais conciso e, caso alterações tenham que ser feitas, os "replacements" do editor de texto são bem mais coerentes. Viva o IEEE!