sábado, 6 de fevereiro de 2010

3 Camadas com Lazarus

"Aquele que se empenha a resolver as dificuldades resolve-as antes que elas surjam."
Sun Tzu

Olá a todos.

Neste primeiro artigo, gostaria de fazer uma pequena introdução. Sou analista/programador em linguagens Object/Free Pascal e PHP, especialista em Software Livre, com foco em desenvolvimento de aplicações multiplataforma. Por que uso FreePascal e não Java para este desenvolvimento? Simples: porque Java não gera um executável nativo ao ambiente, tendo por necessidade a criação de uma camada intermediária entre ele e o Sistema Operacional, provida pela Máquina Virtual Java (JVM). O custo disso é uma aplicação mais onerosa em recursos e pouco aplicável ao cenário computacional brasileiro.

O Objetivo do Blog

Ao contrário da maioria dos programadores Delphi (afinal, sou um na minha "vida real"), para os quais a única plataforma de desenvolvimento é a plataforma Microsoft, não sou apaixonado por esta plataforma. Sou amante do Software Livre há 14 anos, dos quais dediquei 12 à especialização em ferramentas livres. Me especializei em ferramentas como o PostgreSQL, o MySQL (que hoje pertence à Oracle) e, por fim, o Lazarus. Com este último, tenho uma relação quase tão longa quanto minha relação com o Delphi. Vi o projeto nascer, acompanhei seu crescimento, e vejo com muita alegria o que ele é hoje. Ainda não é a ferramenta que todos os programadores Delphi usariam, mas não deixa nada a desejar à qualquer outra ferramenta livre de desenvolvimento. A IDE encontra-se em um estágio de maturidade impressionante, chegando a substituir o Delphi em meus novos projetos.

Baseado nisto, meu intuito com este blog não é publicar dicas de como fazer isto ou aquilo. Isto você encontrará abundantemente pela internet, principalmente em blogs. Eu, inclusive, recomendo este e este. O primeiro é o programmer ObjectPascal, do meu grande amigo Silvio Clecio, e o segundo é o Dicas for Lazarus, de Isaac Trindade. Ambos são excelentes fontes de referência. Meu intuito maior é discutir e apresentar soluções implementadas com o Lazarus, soluções estas extremamente portáveis, aplicáveis em qualquer ambiente e, principalmente, com custo reduzido.

Portanto, este nosso 1º artigo abordará um tema muito discutido nos fóruns Delphi ultimamente: aplicações em 3 camadas.

O Desafio

Há alguns dias, conversando com meu amigo Silvio Clecio, queixei-me sobre uma solução que necessitava para um novo projeto. Preciso criar um ambiente separado em camadas, onde minha camada de negócios possa ficar isolada fisicamente da minha camada de aplicação. Para desenvolver tal solução, tinha duas alternativas: criava um WebService em Java para hospedá-lo em um servidor Web, ou desenvolvia um AppServer com Delphi utilizando o DataSnap. Nenhum dos dois cenários me agradava, pois não queria nem (re)aprender Java, muito menos ficar preso a plataformas proprietárias.

A Proposta

No dia seguinte, a caminho do trabalho, a solução veio como uma epifania: SOCKETS! Observando o protocolo de comunicação das ferramentas de Instant Messaging percebi a simplicidade da solução. Um servidor executa uma thread que "escuta" uma porta TCP qualquer. Esta thread será a responsável por estabelecer os canais de comunicação entre o servidor e seu(s) cliente(s). Um cliente abre um canal (socket) de comunicação com o servidor, avisando que está ativo e que enviará uma requisição. O servidor então se prepara para receber esta requisição, enviada como texto puro pelo cliente. Enviada a solicitação, o cliente espera pela resposta do servidor de que recebeu a solicitação. Resposta recebida, o cliente fica a espera do processamento da solicitação.

Enquanto o cliente aguarda, o servidor processa a solicitação. Como já sabe quem é o cliente e onde ele está, retorna o resultado de seu processamento pelo mesmo canal de comunicação com o cliente, que também tem uma thread responsável por ouvir uma porta TCP, respondendo à solicitação. Esta resposta também vem em texto puro, o que torna sua transmissão mais leve que a transmissão de pacotes binários. O cliente então processa o retorno da solicitação, exibindo as informações necessárias ao usuário e fechando o canal de comunicação.

Os Problemas

Transmitir os comandos ao servidor e receber suas respostas em texto puro pode tornar tornar esta solução altamente insegura. Qualquer um capaz de capturar estas transmissões será capaz de ler e interpretar seu conteúdo. Em um ambiente LAN este problema pode, mas não deve, ser ignorado. Mas em ambientes WAN, onde as camadas de negócio e aplicação estão localizadas a alguns quilômetros de distância, isto passa a ser um problema gravíssimo.

Além disso, existe o fato de que o Lazarus ainda não suporta interfaces MDI (funcionalidade testada até a versão 0.9.29), o que pode agregar uma baixa usabilidade à solução.

E, por último, há o problema gerado por solicitações que geram muitos dados de retorno. Um exemplo seria a solicitação dos dados da base de CEPs. Ela conta, hoje, com quase 700.000 registros. Isso colocado em texto puro geraria um arquivo de 76 MB, o que tornaria a consulta, em cenários em que a banda disponível é muito estreita, impraticável.

As Soluções

Como será utilizado o projeto Synapse nesta solução, os comandos de solicitação e retorno podem sem criptografados, utilizando a implementação da OpenSSL disponível no próprio projeto. Com isso, cada cliente terá um par exclusivo de chaves de criptografia, as quais serão utilizadas para esta comunicação. O formato de transmissão das solicitações pode variar entre CSV e XML, sendo mais provável este último por sua compatibilidade com outros protocolos de comunicação.

Para contornar a falta da solução em MDI, uma maneira elegante de se construir a aplicação é usar o conceito TDI (Tabbed Document Interface). Este conceito já é amplamente utilizado, sendo sua aceitação um processo natural. Ele é utilizado, principalmente, em navegadores, como o Mozilla Firefox, o Google Chrome e até mesmo o Internet Explorer. Outros softwares já aderiram a este conceito, como o Mozilla Thunderbird, por exemplo.

Para contornar o problema do excesso de dados em um arquivo de retorno, todas as consultas são parametrizadas, para que retornem o mínimo de informações possível. Exemplo: não podemos pesquisar todos os CEPs do estado de Minas Gerais, pois ele possui mais de 800 municípios. Ao contrário, trazemos apenas os municípios. O usuário então escolhe de qual município consultará o CEP. Caso o município contenha apenas um CEP, ele será mostrado instantaneamente, senão, listará os bairros para que o usuário possa efetuar a consulta. Escolhido o bairro, serão, por fim exibidas as ruas e seus respectivos CEPs. Ou seja, dividimos uma consulta de 50.000 resultados em 3 consultas com, no máximo, 800 resultados.

A Plataforma

Para esta solução, foram escolhidos o Lazarus 0.9.29-23675 e o compilador FPC 2.4.1, ambos em ambiente Slackware Linux 13.0 com Kernel 2.6.32.6 otimizado para o hardware onde se abrigam as ferramentas.

Esta solução prevê a utilização de vários SGBDs, como o MySQL 5.1 e o Firebird 2.1, mas, para um melhor suporte aos requisitos de estabilidade, segurança e confiabilidade do sistema, o SGBD escolhido foi o PostgreSQL 8.4.2-1, também para Linux.

A parte de conexão com o SGBD fica por conta da biblioteca ZeosLib, versão 6.6.6-stable, utilizando um pooling multithread para as consultas e operações com o banco de dados.

Já os sockets de comunicação e a criptografia SSL ficam por conta do projeto Synapse.

Demais aspectos relativos ao desenvolvimento serão demonstrados em artigos futuros.

Considerações Finais

A escolha da plataforma para o desenvolvimento é lógica, até mesmo óbvia. Toda a plataforma é composta por ferramentas livres e por nenhuma delas fui obrigado a dispensar um centavo sequer. Mas, se não há custo para o ambiente de desenvolvimento, qual será o valor da solução depois de pronta? A resposta é simples: R$ 0,00. Esta solução, assim como todas as ferramentas envolvidas em sua confecção, não terá valor comercial algum, sendo acessível a qualquer um, em qualquer lugar.

Mas alguns devem estar pensando em porque escolhi o uso de sockets em detrimento ao WebService Toolkit, disponível para Lazarus já há algum tempo. A resposta também é simples: estabilidade. Como o WST ainda não atingiu um estágio de maturidade apropriado, ao contrário da Synapse, que mostra resultados excelentes, inclusive no Delphi, não achei seguro colocá-lo em produção. Além do fato de que um AppServer funcionando por sockets dispensa a implementação de um servidor Web Apache para hospedar a camada de negócios.

Bem pessoal, este é um breve resumo do projeto que estou iniciando. Colaboradores serão sempre benvindos.

No próximo artigo, explicarei em detalhes a comunicação por sockets e a implementação do OpenSSL na comunicação.

Até mais.

Ajude a comunidade Lazarus brasileira. Acesse http://forum.lazbr.net/ e paticipe.