segunda-feira, janeiro 22, 2007

Java 6: Bem-vindo o antialiasing

Antialiasing é, grosso modo, uma técnica para reduzir o ruído em imagens. Esse ruído nada mais é do que a percepção dos pixels que formam a imagem na tela do computador. Em suma, quando maior a resolução de um monitor, menor é a percepção desse ruído. Isso ocorre porque quanto mais pixles pudermos colocar em uma determinada área, menor será a percepção de erro que conseguimos detectar. Por exemplo, ao desenharmos um quadrado na tela, não percebemos nenhum problema de aliasing, uma vez que os pixles do monitor estão alinhados com as linhas horizontais e verticais do respectivo quadrado. Entretanto, quando a figura é um círculo, ou uma diagonal, ou qualquer outra forma que exija pixles não alinhados, o aliasing ocorre.

Resolvendo o aliasing
Monitores LCD, como os de notebooks, são os mais afetados por esse problema. Para resolver esse problema via hardware, a única alternativa é aumentar a quantidade de pixles que podem ser colocados em uma área. Em outras palavras, aumentar a resolução. Porém, quanto maior o número de pixles, mais instável é a imagem, uma vez que a varredura de atualização horizontal deve aumentar também. E isso ocorre em outro problema que é a potência de brilho e capacidade de contraste, que também devem aumentar. Em suma, traduzindo em palavras mais simples, quando tentantamos resolver um problema, acabamos caindo em outros.
Outra forma de reduzir o aliasing é através de software. Através do software, não resolvemos o problema, mas conseguimos criar uma ilusão óptica, que simula um resultado satisfatório. Quando desenhamos uma diagonal na tela, sempre teremos, uma estrutura parecida com uma escada, como ao lado. Não conseguimos reduzir esse "serrilhado" porque, cada degrau dessa escada é um pixel - não existe um nível menor de pintura. Assim, a técnica de antialiasing baseada em software tenta resolver esse problema adicionando pixels adjacentes à escada. Esses pixels adjacentes possuem tonalidades de cores intermediárias entre o pixles pintado e o fundo da imagem.
Quando essa imagem é vista de muito perto, notamos os pixels adjacentes. Mas quando a imagem é vista de longe (uso normal do monitor), esses pixels adjacentes são fundidos com os pixels pintados e o nosso cérebro encarrega-se de fazer a ilusão para nós. O resultado é uma imagem sem ruído.

Antialiasing no Windows
Quem utiliza o Windows deve conhecer o chamado ClearType Tunnig. Ele não é padrão do sistema operacional, mas pode ser instalado como integrante do pacote Power Toys. Uma vez instalado, é possível configurar o nível do antialiasing a ser aplicado no monitor. Novamente, para usuários de monitores LCD, esse recurso é fundamental, melhorando consideravelmente a experiência do usuário.

Antialiasing no Java
E agora o fundamento desse post. O Java, historicamente, não se preocupa com esse problema de aliasing. Talvez porque na época de sua criação os monitores LCD eram quase inexistentes, e esse problema não era detectável. Hoje, porém, uma aplicação Java Swing sofre muito com o aliasing. Java nunca pode resolver esse problema porque a solução de antialiasing dos sistemas operacionais é algo implementado em baixo nível. Em outras palavras, Java não poderia ter uma solução multiplataforma que operasse em todos os locais, uma vez que nem todos os sistemas operacionais suportados pela JDK têm um mecanismo de antialiasing.
Felizmente, o release 6 do Java resolve esse problema. E mais, a solução implementada é totalmente Java. Parte da API 2D do Swing foi reescrita e agora os algoritmos de renderização implementam a técnica dos pixels adjacentes descritos acima. Assim, para quem usa uma aplicação Java Swing, a experiência será bem superior.
Abaixo, tenho dois screenshots da mesma aplicação. Uma rodando sobre o Java 5 e a outra sobre o Java 6. Notem que a aplicação da direita não apresenta o serrilhado sobre o texto. Para quem não conseguiu visualizar muito bem a diferença, recortei dois fragmentos da imagem ampliada. Notem que o suporte antialiasing além de adicionar os pixels adjacentes, também encarrega-se de alterar algumas cores de pixels.

Comentários finais
O antialiasing é uma técnica de redução de ruído das imagens. Podendo se implementado por hardware ou software, alguns sistemas operacionais, como o WindowsXP, possuem suporte nativo para o ajuste desse recurso. Quanto ao Java, na sua versão 6 o antialiasing é suportado de forma intrínsica, melhorando sensivelmente a aparência das aplicações desktop Swing. Como último comentário, salienta-se que o suporte do antialiasing do Java é independente de plataforma operacional e de hardware, sendo suportado totalmente pela sua API 2D. Assim, mesmo quando desabilitado o ClearType no Windows, a aplicação Java continuará efetuando o antialiasing dos pixels. Para desabilitá-lo totalmente, deve existir algum atributo "-D" para o interpretador da virtual machine, mas isso é uma coisa que eu ainda devo procurar :-)

terça-feira, janeiro 16, 2007

O Mundo das JSRs

Java Specification Request, ou simplesmente JSR. Quem trabalha com Java sabe o que essas letrinhas significam. Ou pelo menos deveriam saber.
Qualquer coisa que você no Java possui uma JSR. Claro, também existem JSRs que não vingaram ou mesmo que estão obsoletas, substituídas por versões mais novas. Existem JSRs muito limitadas e simples, já outras são verdadeiras obras de arte. Algumas, de tão complexas, precisam ser divididas em várias outras, como a do Java EE. Estas são conhecidas como especificações Umbrellas, ou guarda-chuvas.

JSRs em foco
Ao olharmos uma JSR, notamos que ela não tem nada demais; elas são "apenas" documentos de texto simples que solicitam a criação de um padrão para alguma coisa e, em um segundo momento - após inúmeras discussões e possivelmente anos de brigas entre os diversos integrantes do comitê - documentos que definem o padrão solicitado.
Implementar uma JSR, todavia, pode ser uma tarefa herculóide. Não vou entrar nesse mérito, mas sim, apenas, elencar as JSRs que eu tenho interesse, ou melhor que as telas de cadastro têm interesse.

JSRs relativas às telas de cadastro

227 : A Standard Data Binding & Data Access Facility for J2EE - Provê as bases para construção do famoso binding de componentes de tela e objetos de dados. Focada no Java EE (ex J2EE). É uma especificação de 2003 e à ela são relacionadas as JSRs 114 (JDBC Rowsets), 127 (primeira versão da JSF) e 221 (JDBC 4). Quanto às telas de cadastro, podemos dizer que essa JSR é um Norte para efetuar a ligação dos controles da tela e os objetos de dados (e negócio) que contém a informação.

252: JavaServer Faces 1.2 - Define como criar aplicações web através de componentes, tal como é feito em sistemas desktop: o programador deveria poder ter uma IDE visual para, via drag and drop, montar a tela. Essa especificação define quais são os componentes, como eles podem ser ligados, arrumados na tela e a semântica de sessão, configuração, etc. Enfim, ela é grande. Talvez por esse motivo, ela é uma expansão de algo anterior, a JSR 245 (JSPs) e a JSR 127 (JSF 1.1). Utilíssima para as telas de cadastro porque define como fazer univocamente as coisas na web. Em outras palavras, é assim que se constrói interfaces web para Java. Essa é parte do Java EE 5, definida pela JSR Umbrella 244.

269: Pluggable Annotation Processing API - Essa a osmose não me atingiu e só fiquei sabendo dela pelo artigo do Danny Coward sobre novas features do Mustang. Serve para trabalhar com anotações via parsing no código-fonte do sistema. Por exemplo, quem vai criar um plugin para editores de código pode ser beneficiar muito dela. Quem conhece a ferramenta Apt (Annotation Processing Tool) do Java Tiger pode considerar essa JSR com a mesma coisa, mas agora com uma API e um comportamento mais transparente e extensível. Para as telas de cadastro, considero essa API uma coisa fundamental para o sistema de configuração baseada em histórico e plugin de edição do Merlin. São relacionadas as JSR 175 (anotações) e 14 (genéricos).

296: Swing Application Framework - Assim como a web ganhou servlets controladores e um conjunto de informações de deployment padronizadas (os web-descriptors), o Swing também vai ganhar um padrão para suas actions, tratamento de sessão, gerenciamento de preferências e outras coisas. É essa a JSR responsável por isso. Para as telas de cadastro, tudo de bom: poderemos (talvez) ter um consenso em como fazer várias coisas, desde políticas de gerenciamento de objetos em memória (e o vínculo deles com os controles de tela - um PresentationModel, por exemplo, só ganharia com isso) até recursos i18n.

223: Scripting for the Java Platform - Quem já usa o BeanShell (JSR 274) sabe a mão na roda que ele pode ser. Embora o Merlin já suporte ele, com o advento dessa JSR teoricamente Java poderá suportar qualquer linguagem de scripting. Por padrão o Java 6 virá com a implementação Mozilla Rhino, o que indica que scripts JavaScript (e outros) poderão interagir com objetos Java dentro da aplicação, mesmo as desktop. Para as telas de cadastro, uma flexibilidade extrema, abrindo possibilidades semelhantes às oferecidas pelos programadores VBA.

222: Java Architecture for XML Binding (JAXB) 2.0 - Ela é um seguimento da antiga JSR 31 (Java XML Data Binding) e a idéia dela é permitir o trabalho (criação, uso e manipulação) sobre arquivos XML de forma transparente. Ao usá-la, você sua impressão é que está trabalhando com objetos Java (Javabeans) que, ao final da sessão de trabalho, serão persistidos em arquivos XML. Muito rápida se comparada à Serialização Java. Para as telas de cadastro, considero útil para persistência de estados intermediários de sessões de usuário ou preferências (claro, eu sei que temos a API prefs para isso e agora também a JSR 296 que promete bastante) É esperar para ver.

224: Java API for XML-Based Web Services (JAX-WS) 2.0 - E aqui a parte dos webservices. Com essa JSR, estamos convergindo esforços para acesso a webservices e a interação com eles. Atuando em sincronia com a JSR 222 (JAXB) e com os padrões SOAP 1.2, WSDL 1.2, essa JSR promete facilidades no desenvolvimento e evolução de serviços para web. Assim, recursos como a abstração de mapeamento de objetos recebidos via JAX-RPC para objetos Java e vice-versa, podem atuar em conjunto com features de compilação on demand de classes e recursos de engenharia de bytecodes (BCEL, ASM, etc.). Na prática, vejo um futuro como uma aplicação Java conectando-se em um webservice (feito em .NET, por exemplo) e gerando stubs e classes em tempo de execução e com elas inicializando os dados e exibindo-os na IHC do usuário. Um mundo com conectividade total. Para as telas de cadastro, dou a dica: Um sistema baseado no Merlin pode conectar-se em um webservice qualquer (feito em .NET, de novo!) para obter dados. O JAX RPC traz esses dados e gera das classes Java em tempo de execução junto com o trabalho de mapeamento do JAXB. Essas classes vão para a árvore de classloaders do sistema. O Merlin lê essas classes e gera a tela de cadastro para elas, já inicializando os dados recebidos. O usuário pode, então editar esses dados. Dados alterados, o sistema faz o caminho inverso, sendo que no fim do trajeto um outro webservice recebe os dados (automaticamente mapeados) e persiste em uma base qualquer. Legal, né? Também acho :-)

295: Beans Binding - Essa é ótima. Pelo menos é o que eu imagino que os desenvolvedores desktop deveriam pensar. A idéia é ligar controles de tela e objetos de dado astravés de uma coisa como a Expression Language (EL) usada pelos programadores JSF. Não está no request da especificação, mas acho que também deveria estar disponível um mecanismo de validação e invocação de ações para os controles. No Merlin, eu fiz um esquema de Agentes para isso, como na Eiffel. Essa JSR é crítica ao meu ver, pois centraliza inúmeros pontos que possuem tratamentos a la vonte pelos programadores: desde patterns como o famigerado PresentationModel até códigos ad hoc sobre listeners como o PropertyChangeListener. Para as telas de cadastro? Um ponto único de trabalho para gerenciar a ligação entre os controles de tela e os objetos do sistema.

Bom, como disse, são JSR às pampas. E não estão aqui todas as que considero ligadas às telas de cadastro. Apenas listei as que vieram à cabeça no momento. A dica que deixo é: Mantenham-se atentos às JSRs.

quarta-feira, janeiro 03, 2007

Magoo, uma pequena peça para uma grande solução

Começo esse post com um pequeno fragmento de código e peço que pensem no que ele pode fazer:

addPropertyChangeListener(property, new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
//codigo maravilhoso
}
);


Pense.

Pense.

Pense mais um pouco.

Descobriu?

Não?

Pois é. Esse pequeno listener encerra uma solução que me incomodava há tempos: como implementar o mecanismo de permissões não intrusivo do Magoo. Magoo? O que é o Magoo?

O Magoo
O Magoo é um mecanismo de gerência de permissões não intrusivo para aplicações Java web e desktop. Idealizei ele há uns dois anos e está em banho-maria durante esse tempo porque o Merlin sempre está à frente (e parece não querer sair).
Embora o mercado ofereça várias soluções para gerenciamento de permissões, como o Acegi, não encontrei nelas a transparência, a facilidade de uso, a escalabilidade e a integração necessária com as aplicações novas e, principalmente, com as já em produção. Em outras palavras, eu queria um controle de acesso totalmente integrável ao meu sistema, mesmo que ele já estivesse pronto. Não obstante, eu queria poder construir novos sistemas sem se preocupar com permissões. Da mesma forma, também queria poder aumentar ou diminuir meu sistema sem pensar em impactos no gerenciamento de permissões. Criar usuários, perfis, grupos, subgrupos, atribuir permissões específicas por usuário, por tela, por controle, com base em valor de dado e outras coisas. Tudo isso eu queria fazer sem ter impacto no código da aplicação. Em suma, eu queria que algo como isso nunca existisse em um sistema:

//No carregamento do formulário...
if (usuario.getPermissions().hasValues("ADMIN","GERENTE","DIRETOR") {
btnExportarDados.setEnable(true);
} else {
btnExportarDados.setEnable(false);
}

Deu para entender? Bem, esse tipo de código é sempre uma dor de cabeça e, em qualquer solução de mercado, ele vai existir.
Esse tipo de controle é chamado (grosso modo) Permissão Por Controle (PPC). Devido sua granularidade elevada, aplicações grandes podem facilmente implodir devido a gama de possibilidades que podem ocorrer. Permissões Por Tela (PPT) são mais fáceis de solucionar. Em aplicações web, é relativamente fácil para um servlet controlador dirimir sobre as permissões (baseado em expressões regulares que definem URLs de páginas) e habilitar ou não o acesso para o usuário. Permissões por Sistema (PPS) são ainda mais simples. Uma página de logon resolve o problema. Por outro lado, Permissões Por Valor (PPV) são mais problemáticas que as permissões por controle. Dado o conteúdo de um objeto, o usuário terá ou não acesso à informação. Como exemplo, poderíamos dizer que Administradores e o João (sempre ele) têm acesso aos dados de número 1, 2 e 3. Todos os outros integrantes do controle acesso, exceto os Estagiários do Departamento de Tecnografica (o que é isso?) podem ver os valores maiores que 4. Os Estagiários do depto. acima têm permissão padrão sobre dado (que permissão é essa?)
Bem, o parágrafo acima ilustra um cenário bastante simplista, mas real de gerenciamento de permissões. Nem cheguei a falar de GRANTs, REVOKEs, inversão de permissões ou integração com mecanismos de autenticação e Single Sign On (...)
Imaginar um controle de acesso que faça tudo isso e sem mexer em uma linha do código da aplicação é um dos meus sonhos (além do Merlin, do Melvin, do Jestor....).
Bem, o fato é que nesses dois anos de elucubrações, percebi que é possível sim conseguir isso. E a resposta é extremamente simples (ou quase). As peças para ela são: reflexão (adoro ela), instrumentação de código e uma estrutura de permissões escalável, que permita tanto evoluir os objetos da aplicação quanto as ações que podem ser realizadas no sistema e os integrantes que o compõem.
Na prática, o Magoo é o projeto que reúne essas características que considero essenciais para um controle de permissões.

O Estalo
Nessa semana, enquanto o Julio cuidava da integração do sistema em um cliente, eu peguei o note dele e coloquei em prática algo que até então parecia difícilimo: como colocar tudo isso de forma não intrusiva em um sistema?
Embora eu conheça (e reclame sempre) da arquitetura web, meu chão de fábrica é o Swing. Gosto dele porque tem ferramentas visuais (embora ainda toscas) para trabalhar e é uma API MVC por natureza. E estruturas MVC têm vantagens notórias.
Uma delas, é a separação clara dos trabalhos. Temos o Modelo (de dados), empacotado em classes ou interfaces simples. Temos o Controle, que trata (ou delega) as ações do usuário. Temos também a View, que mostra para o usuário aquilo que o modelo contém (adoro o pattern Observer) e o que o Controle operou como regra de negócio.
Pois bem. Um dos controles que pode ser feito no Swing é adicionar listeners para eventos, tais como o ActionListener de um botão. Mas aqui ele não interessa. O que interessa é o listener do primeiro código do post: o PropertyChangeListener.
Esse listener é acionado toda vez que uma propriedade muda no controle de tela. Uma operação como setEnable, setVisible ou setColor dispara esse listener. Assim, você pode ouvir essas operações e tomar atitudes. Já sacou? Ainda não? Continuemos...

Listeners sr. Watson! Listeners!
Podemos criar um listener de modificação de propriedade bem simples, que faz o seguinte: Quando uma regra de negócio modificar sua propriedade para enabled=true, o listener de modificação é disparado. Ele vai em uma base de permissões e verifica se o usuário atual tem permissões para isso. Se tem, nada acontece. Se não tem, o listener aplica enabled=false de novo e deixa vir a renderização do controle. Obviamente, o controle não é habilitado, mesmo que a regra de negócio tenha tentado. Em outras palavras, nosso listener suprimiu a regra de negócio e manteve o status desabilitado no botão para o João.

Instrumentação de código
Obviamente, não é interessante criar listener para todas as telas e controles do sistema. Isso seria algo extremamente demorado e em nada escalável. Precisamos de algo mais simples.
Uma alternativa tosca é usar AOP e adicionar os listeners na mão para os controles. O grande inconveniente é termos que apontar cada elemento da aplicação manualmente e decorá-lo com o listener em questão.
Uma alternativa bem melhor seria deixar a reflexão trabalhar em conjunto com a instrumentação de código (auauauau). Explico.
Através da reflexão podemos varrer todo o grafo de objetos do sistema (qualquer objeto acessível através do bootstrap da aplicação) e verficar seu conteúdo, tipo, etc. Assim, poderíamos extrair os objetos que são telas, os que são controles (etc.) e montar uma árvore ou grafo de objetos. Esses objetos seriam comparados aos objetos gerenciados pela permissão e, quando fossem iguais, o listener seria adicionado via reflexão. E a instrumentação de código?
A instrumentação de código vem para resolver a seguinte questão: usar AOP ou reflexão dá na mesma, pois precisamos rodar um código dentro da aplicação cliente. Instrumentar a aplicação permite que nossos códigos de reflexão sejam carregados no boot da aplicação, mas sem o inconveniente de ter que alterar o código do sistema cliente.
Já testei isso no Merlin e funcionou muito bem para o reloading de classes. Para o Magoo, o conceito é o mesmo.

Usuários e ações
Bem, dito o que fazer para resolver o problema (usar listeners) e como fazer para evitar alterações de código (reflexão + instrumentação) a perguna que fica é: Como gerenciar a complexidade de usuários e objetos gerenciados?
Minha resposta é simples: Utilizar o conceito de ações (baseei isso no conceito - nada análogo - de ações em Casos de Uso) de usuário. Enquanto os outros controles de acesso tem a visão de perfil > operação; o Magoo tem o conceito de perfil > ação. Em palavras simples, enquanto uma operação define uma função F:pode(permissao,objeto); uma ação define a função F:pode(açao,permissões). Que loucura! Espera.
Uma ação nada mais é do que um conjunto de permissões sobre um objeto. E um objeto pode ser qualquer coisa tangível na interface do usuário: um sistema, um módulo, uma tela ou um controle. As permissões podem ser Ver e Habilitar (sendo que isso são abstrações para coisas como Ver e Clicar e coisas do gênero). Ações podem ser agrupadas. Integrantes podem executar ações. Integrantes podem ser Usuários ou Grupos. Grupos são compostos de integrantes, sucessivamente. Permissões podem ser diretas, baseadas em expressões regulares, regras de negócio ou scripts (ou qualquer outra coisa). E tudo isso fica em cache. E pronto. E estou com sono.

Bem, isso foi um preview do Magoo e das coisas que ele vai implementar. Não tenho previsão para ele, mas digo que os contatos que estou tendo, parecem mostrar-me que ele é algo bem mais simples de implementar que o Merlin e possui um mercado mais amplo e imediato.
Talvez (eu disse talvez) acabo fazendo ele antes do Merlin.