Archive for March, 2007

Múltiplas Fontes de Dados, uma Engine ORM

Friday, March 30th, 2007

O Tiago postou no seu blog sua percepção sobre como o Hibernate Search é um tiro no pé. Ele afirma que justo agora que o problema do mapeamento objeto-relacional está ficando irrelevante estão criando outro problema, que ele chamou de object-indexed.

Eu concordo que existe um novo problema no horizonte e que a estrutura simplificada de metadados para persistência não está pronta para este tipo de coisa, mas não acho que seja perda de tempo esta engine, na verdade acho que pode ser muito útil. Em um projeto recente utilizei a tecnologia que meu cliente adquiriu para fazer buscas em conteúdo, uma plataforma cara e famosa de busca. Apesar de eventuais problemas com APIs, a coisa se mostrou bem interessante.

Neste sistema eu utilizo o banco de dados para fazer buscas por objetos quando os quero processar e em um caso específico (o “resultado de busca”) eu preciso destes mesmos objetos vindos da engine de busca. Não importa qual a origem, os dados representam o mesmo objeto. As Camadas de Apresentação e de Negócios estão prontas para lidar com este objeto, apenas a Camada de Persistência deve saber de onde vieram.

Eu fiz todo este trabalho na mão e isso é bem trabalhoso. No final das contas criei um código relativamente reutilizável, que pode ser empacotado numa rquivo JAR e está sendo utilizado em outros projetos com necessidades parecidas.

A grande vantagem em termos objetos que podem vir de fontes estruturadas como um SGBD ou flat como uma engine de busca é que num ambiente como o meu atual onde a base de dados é o centro do universo fazer consultas ao banco é muito caro. Muitas vezes faz mais sentido pesquisar na engine de busca, que apesar de não trazer informações e relacionamentos completos possui informação para leitura facilmente encontrável.

Independência de persistência é algo que sempre existiu. Neste caso ainda é mais simples porque os dados são de somente-leitura em uma base, ela age simplesmente como um cache. O memcached, aliás, está sendo utilizado no meu projeto atual e é tratado de maneira persistente pela aplicação através de filtros no Spring.

Os dados vêm de todo lugar, uma interface única e poderosa como do Hibernate/JPA são muito úteis no cenário moderno.

Exemplos Simples

Thursday, March 29th, 2007

A partir do momento que você resolve utilizar uma tecnologia deve fazer o possível para entendê-la. Hoje eu estava conversando com um amigo e percebi que por mais que estejam espalhados os conceitos ainda não são entendidos. Falávamos sobre JPA e sobre como misturar lógica de negócios com metadados de persistência pode se tornar um problema em longo prazo. O argumento em favor da mistura foi “mas sua lógica de negócios não precisa ficar anotada, apenas seus dados”. Aí eu percebi que a discussão, na verdade, precisava passar por algo mais fundamental.

Eu expliquei o problema de usar VOs e BOs (que ele não chamava por estes nomes mas aplicava os conceitos) através de um exemplo simples.

Vamos supôr que exista uma função que define o novo salário de um funcionário (pseudo-codigo):

public void aumentaSalario(Funcionario f, Valor v){
Valor salario = v + calculaTaxasCargo(f.getCargo());
f.setSalario(salario);
}

E vamos supor que exista um tipo de funcionário chamado Gerente. O Gerente possui uma lógica de cálculo de salário um pouco diferente, dada pela formula:

salario = v + calculaTaxasCargo(f.getCargo()) + (f.getDepartamento().getOrcamento().getBonus() / 10)

Como adaptamos o código acima para que isso seja possível? Uma forma é criar um novo método:

public void aumentaSalario(Funcionario f, Valor v){
Valor salario = v + calculaTaxasCargo(f.getCargo());
f.setSalario(salario);
}
public void aumentaSalarioGerente(Gerente f, Valor v){
Valor salario = calculaSalario(f,v) + (f.getDepartamento().getOrcamento().getBonus() / 10);
f.setSalario(salario);
}

Mas desta forma nós sempre precisamos saber se estamos lidando com um gerente ou funcionário para saber qual função chamar. Se temos uma lista como a abaixo (que pode ser retornada do banco de dados, por exemplo) precisamos verificar cada tipo:

List<Funcionario> lista = new ArrayList<Funcionario>();
.
lista.add(new Gerente("João"));
lista.add(new Funcionario("Lucia"));
.
//aumentando o salario de todo mundo em 1000 dinheiros
for(Funcionario f: lista){
if(f instanceof Gerente){
aumentaSalarioGerente(f,1000);
}
else{
aumentaSalario(f,1000);
}
}

De que adianta ter uma abstração na forma de herança entre Funcionario e Gerente se cada vez que eu preciso manipulá-las eu preciso quebrar esta abstração com um if? Ok, é fácil de resolver isso criando uma função única:

public void aumentaSalario(Funcionario f, Valor v){
Valor salario = v + calculaTaxasCargo(f.getCargo());
.
if(f instanceof Gerente){
salario = calculaSalario(f,v) + (f.getDepartamento().getOrcamento().getBonus() / 10);
}
f.setSalario(salario);
}
.
//Aumentando salarios:
List>Funcionario> lista = new ArrayList>Funcionario>);
.
lista.add(new Gerente("João"));
lista.add(new Funcionario("Lucia"));
.
//aumentando o salario de todo mundo em 1000 dinheiros
for(Funcionario f: lista){
aumentaSalario(f,1000);
}

Mas o que eu fiz foi simplesmente mudar o problema de lugar, não acabar com ele (por isso minha métrica do if).

E qual a solução? Polimorfismo.

class Funcionario{
.
public void aumentaSalario(Valor v){
Valor salario = v + calculaTaxasCargo(this.getCargo());
this.salario = salario;
}
.
}
.
class Gerente extends Funcionario{
.
public void aumentaSalario(Valor v){
super.aumentaSalario(v);
//soma o bonus de gerente ao salario
f.setSalario(salario);
this.salario = this.salario+ (getDepartamento().getOrcamento().getBonus() / 10);
}
.
}

Daí nossa lista de aumento em massa pode fazer simplesmente:

//Aumentando salarios:
List>Funcionario> lista = new ArrayList>Funcionario>();
.
lista.add(new Gerente("João"));
lista.add(new Funcionario("Lucia"));
.
//aumentando o salario de todo mundo em 1000 dinheiros
for(Funcionario f: lista){
f.aumentaSalario(1000);
}

Porque cada objeto tem em si a lógica necessária para realizar a operação. Claro que este é um exemplo acadêmico, já identifiquei uma penca de refactorings necessários para o código ficar aceitável, mas a idéia está expressa nessa simples divisão de responsabilidade.

Aí é hora de alguém postar um comentário dizendo: “mas estes objetos ‘gordos’ têm toda a lógica? Fazem persistência?” a resposta é não. Objetos são ‘animais sociais e colaborativos’, o que significa que eles agem em conjunto com outros objetos para chegar a um fim. No exemplo acima, o cálculo sobre quanto é o bônus não é feito pelo funcionário, nem pelo gerente mas sim sobre quem é “dono” do conceito (dica: esta parte pode ser refatorada se você ler sobre o Princípio de Deméter).

Objetos dividem as responsabilidades e agem em conjunto para executar as regras de negócio de um sistema. Parece simples mas cada vez mais eu acho que as pessoas não gostam de conceitos simples :(

Uma Comparação Interes$ante

Saturday, March 24th, 2007

Fazem algumas semanas que as revistas brasileiras só falam sobre a iminente reabertura total do banco de investimentos Goldman Sachs no Brasil. Não, você não cadastrou o feed errado, este blog ainda é sobre tecnologia. O que me fez pensar foi como os bancos de investimento tratam seus profissionais e como o fazem as consultorias de tecnologia. Nos dois segmentos, talento é tudo. Você tem uma centena de operadores, analistas e o que for, mas eles sozinhos não garantem o sucesso de um projeto, seja um IPO, uma compra agressiva ou a criação de um novo sistema.

A diferença é que no mundo onde as pessoas dão valor ao dinheiro os talentosos são recompensados. Pode ser porque é uma área mais antiga mas o fato é que os peixes-grandes destes lugares sabem muito bem que precisam manter sua mão de obra e evitar a qualquer custo que ela fuja para a concorrência.

Ao contrário do que possa parecer, um profissional técnico no desenvolvimento de sistemas hoje vale uma boa grana sozinho. Se você for realmente bom pode oferecer serviços de consultoria e acabar ganhando no mínimo o mesmo que uma empresa te pagaria de salário. Pode ser que você tenha que trabalhar mais do que se tivesse um ‘patrão’, mas dado os horários loucos e prazos insanos de hoje em dia nem sempre isso é verdade, pelo contrário: se for para manter apenas o valor que você ganha de salário possivelmente você conseguiria ter uma qualidade de vida melhor.

E quando o profissional vai embora no meio de um projeto temos um problema. No cenário atual um projeto geralmente é tocado por um bando de gente que não têm noção de computação básica (ainda que seus diplomas digam que têm) e um pequeno grupo (quase sempre de um) que faz a maior parte do trabalho intelectual. Quando este grupo sai para ganhar R$1.000,00 a mais num outro lugar os prejuízos são enormes.

Várias vezes na minha carreira eu já fui chamado para este tipo de situação. Atuando como consultor independente eu entrava num projeto cujo arquiteto ou líder saíra para ganhar cinco reais e duas mariolas a mais em outra consultoria commodity de três letras. É clássico encontrar uma sala com vários programadores que não têm muita noção do que estão fazendo olhando o consultor que chega como a pessoa que vai devolver a ordem. Como tudo foi muito rápido, não houve tempo de realizar um processo seletivo e a empresa paga ao consultor mais que o dobro do que pagava para o arquiteto/líder. No final do projeto o consultor vai embora e você ainda precisa contratar alguém fixo para tapar aquele buraco.

Bom negócio, heim? O que você faz para evitar isso na sua empresa? Que tal aprender com alguém que já faz isso há mais tempo do que existe a palavra ’software’?

O Futuro na JAOO

Tuesday, March 20th, 2007

Ótimo painel sobre o futuro da programação no JAOO. Especialmente o comentário do PragDave:

Dave: I’d like to predict that the current stacks of software by 10-15 years are going to be in a much worse legacy and more of a nightmare to maintain. You’re going to have employment forever maintaining this stuff. C++, Java code, C# code, this stuff is very complicated and very brittle with all these class libraries and frameworks. We’re digging ourselves in a really big hole and there will be a lifetime of opportunities for you people to maintain this stuff that you’re creating.

Prepare-se e pense nisso antes de comprar aquela ferramenta mágica ou criar mais um framework que faz a mesma coisa que todos os outros.

Palestras do ERECOMP-AL

Monday, March 19th, 2007

Comento em breve o evento mas os slites já estão disponíveis:

Rumo ao ERECOMP 2007

Thursday, March 15th, 2007

Como já falamos aqui, estou indo apra o ERECOMP 2007. Estou bem ansioso para este evento, nunca palestrei no nordeste e não conheço o público.

O keynote será uma apresentação que está na manga há um bom tempo mas nunca tinha a oportunidade de executar. É bem diferente do meue stilo normal de apresentação, pelo menos graficamente. Acho que o livro do Atinkson teve efeito retardado mnas quem viu gostou.

A segunda é uma releitura da palestra de CBD x SOA que foi apresnetada ano passado. Acho que o principal diferencial para esta é estar neste exato momento vivendo os problemas de se implantar uma arquitetura SOA em um ambiente onde já existe um conjunto de sistemas e uma cultura formada.

Bom, que for lá por favor não se acanhe. O melhor destes eventos é a experiência trocada.

Acorda, Maria Bonita…

Tuesday, March 13th, 2007

Lendo a revista Mundo .Net deste mês pensei sobre o estado atual das duas maiores plataformas de desenvolvimento modernas, Java e Microsoft .Net. Infelizmente estou tendendo a creditar em uma coisa: A Microsoft aprendeu, a comunidade Java se acomodou. É impressionante como a MSFT tem investido em ferramentas e plataformas interessantes. A estratégia que pude perceber é mais ou menos assim:

  1. Cria-se uma estrutura fundamental baseada em boas tecnologias e plataformas, geralmente copiadas de casos clássicos de sucesso
  2. Pessoas com nível técnico alto utilizam esta base para criar coisas muito interessantes
  3. Pessoas com nível técnico baixo, grande maioria nas duas plataformas, podem utilizar ferramentas burrotizantes que criam apenas o básico que elas acham que precisam

Dado que as pessoas citadas no item (2) são raridade (eu conheço duas, todos vindos de Java/C++),a estratégia de marketing toda foca no povo do item (3). Para o item (2) (para utilizar um termo MSFT: os Elvis e Einsteins) o marketing é baseado em altos salários e oportunidades muito boas em um mercado saturado de arrastadores de componentes (Morts). Com Java foi exatamente o contrário: a linguagem atingiu o jet-set da computação mas logo se banalizou. Einsteins criaram uma plataforma altamente produtiva e de qualidade impressionante, mas logo Mort caíram em cima, fugindo de Delphi e VB 6.0.

Se o programador mediano Java não tivesse tantos problemas no passado com a Microsoft ele facilmente seria seduzido pela plataforma. Ali tem tudo que ele precisa para fazer seus CRUDs (ou seus grudes…). E se Elvis não tivessem tantos problemas com código proprietário e uma plataforma de um vendedor só eles certamente estariam esmagando cabeças dos programadores Java ao comentar como a plataforma .Net está ficando cada vez mais aberta, cada vez mais flexível, cada vez mais… parecida com sistemas em UNIX.

É sério. Não vou nem citar o MS PowerShell, basta olhar como é feito o deployment em .Net e comparar com um sistema UNIX. Ok, eu sei que é muito mais fácil alguém ter visto um deployment .Net que um UNIX então deixe-me tentar explicar com poucas palavras como geralmente é feito um sistema: cada módulo geralmente é implementado como um programa separado (programa mesmo, tipo uma classe com public static void main(String[])), estes programas conversam entre si utilizando diretivas de IPC. O SO (Linux, HP-UX, Solaris, etc.) controla estes programas (feitos em C/C++, PERL, Python, Ruby, Bash, TCL…).

Se você for esperto já fez uma analogia com um servidor de aplicações J2EE. SIM! Os servidores de aplicação vieram solucionar problemas deste modelo, trazendo um nível de padronização (e racionalidade…) para o processamento de transações distribuídas, segurança, persistência, etc. É para isso que Java EE foi criado, infelizmente as pessoas esqueceram ou não tiveram contato com um ambiente não padronizado e não entendem o que é, por exemplo, um EJB. Ok, mas o problema é que o servidor de aplicações é um mundo a parte, e um mundinho bem fechado.

Tem uns dois anos eu trabalhava para uma empresa líder mundial do setor de sistemas para redes de telefonia celular. Esta empresa possui até hoje uns 90% da base de código em C, rodando em Solaris e outros UNIXes. O sistema principal era exatamente como descrevi: um bando de processos em C que se comunicavam via pipes, filas de arquivos e memória compartilhada. parece uma zona, não? Nada de JMS para mensageria, nada de JAAS para segurança, nada de nada.

Pois a grande vantagem deste sistema não era a velocidade, como defendiam os xiitas locais. A vantagem era a flexibilidade. Quando uma correção era implementada o meu colega de baia enviava para o cliente um patch contendo apenas os processos modificados. Quando eu corrigia uma linha de código tinha que mandar um EAR de 10 megabytes. O primeiro nível de suporte era capaz de fazer scripts em PERL e Bash que corrigiam problemas quando aconteciam e automatizavam tarefas para o programa em C. para o programa em java só o próximo release implementaria a mais boba das tarefas, ou uma famosa dedada no banco de dados (um script SQL).

Claro que a culpa é dos programadores (não me excluo) que não se prepararam para sistemas abertos e extensíveis (anos depois eu consegui fazer alguns progressos nesta área e sumarizei em uma palestra), mas o maior problema é na forma que um Application Server é fechado, lacrado. Mesmo os servidores mais modernos ainda contam com abertura precária se comparados aos bons e velhos sistemas UNIX dos anos 70/80/90.

E neste ponto a Microsoft vai na frente, por incrível que pareça. Sua plataforma está baseada em Camadas que são unidas pelo SO, é como se a pessoa pudesse implementar um sistema UNIX utilizando um framework de workflow, persistência, apresentação, comunicação remota, transações e segurança unificado, não importa qual linguagem (e .Net é multilinguagem desde sempre).

Não, eu não estou falando para você migrar para .Net. O que eu estou dizendo é que Java está trilhando caminhos muito perigosos, como desenvolvedores nós temos que ficar de olho. Cuidado com ferramentas milagrosas e,principalmente, cuidado com caixas fechadas (ainda que sejam Open-Source).

E os Einsteins? Eles brincaram com Java mas voltaram para LISP.

Confundindo DSLs

Monday, March 5th, 2007

O Edgar Silva escreveu um post sobre DSLs há alguns dias. Deixei um comentário mas ao que parece ele não foi aprovado, logo resolvi postar algo para esclarecer uma confusão.

O Edgar anda mexendo com o antigo Drools, atual JBoss Rules, que é uma rule engine bem famosa. A confusão do post pode ser sumarizada em:

Sendo assim podemos criar uma Domain Specific Language (DSL), uma linguagem que especifica para usuários, onde eles possam entender o que está acontecendo nas regras de negócio do sistema. É mais ou menos isso que o projeto que estou ajudando tem que fazer, então vamos a um pequeno exemplo: PT_BR.dsl

Daí seguindo para um exemplo de programação em português:


JAVA:

1. Imprima "{msg}"=System.out.println("{msg}")
2. [when]A quantidade produto igual a {value}=p : Produto( estoque =={value})
3. [then]Chame o comando de continuação de Produto=p.

(quem já programou em VBA em português como eu deve ficar apavorado vendo isso)

A confusão está no fato de que DSLs são linguagens específicas do domínio, não do usuário. Ter uma linguagem de programação em português não faz dela uma DSL. ter uma linguagem declarativa não faz dela uma DSL. Uma DSL vai mapear conceitos do domínio 9venda, estoque, etc.) para dentro dos construtos da linguagem, logo o exemplo não representa uma DSL, apenas uma customização em cima de uma rule engine.

Eu tenho um exemplo que sempre uso em palestras e costuma ser bem claro: Muita gente programa de maneira razoavelmente OO em C e Pascal. O que estas pessoas fazem é definir estrutruas de dados e funções num mesmo módulo (um arquivo .h e um .c em C, por exemplo) e fazem com que todo acesso aos dados sejam encapsulados com funções. Uma pessoa que conheça a paradigma de OO pode criar só com estas técnicas simples programas muitos mais orientados a objetos do que os criados com Java atualmente, com os tais BOs e VOs/TOs que são tudo, menos objetos.

O que eles fazem é mapear um conceito do domínio para a linguagem (sim, isso parece com DDD), funciona que é uma beleza.

Mas existem linguagens que já trazem este conceito dentro de si. Em Java ou C# você não rpecisa desta gambiarra para utilizar objetos, basta você utilizar construtos da linguagem como a palavra reservada class. O domínio ‘Orientação a Objetos’ está mapeado dentro da linguagem.

SQL é outro bom exemplo. É uma linguagem específica para consultas e manipulação de bases de dados, você não constrói qualquer tipo de sofwtare com ela (a menos que utilize extensões bizarras do seu fornecedor de SGBD). Os conceitos de tabela, índice, chave, etc. estão dentro da linguagem.

Hoje ao modelar um sistema de gerência de estoque você não faz mais do que trazer aquele domínio para seu sistema através de um mapeamento de conceitos. O estoque do mundo real vira um bando de classes e atributos. Numa DSL o estoque do mundo real será representado por um construto ‘estoque’ na linguagem utilizada.

Update: O Edgard autorizou o comentário, eu bem sei como é esta coisa de ter que moderar WordPress :P, segue abaixo:

Phillip Calçado “Shoes”

Uma DSL na verdade é uma técnica utilizada para trazer os conceitos de um determinado domínio para o sistema. É como ao invés de implementar OO utilziando C você utilize Java, que possui construtos como classes, modificadores de acesso e interfaces que expressam os conceitos de uma modelagem OO na linguagem ao invés de simular estes em structs e funções.

Apesar de auxiliar na definição de uma ubiquitous language, o objetivo do uso de DSL é diminuir o gap entre implementação e conceito do mundo real, não necessariamente o uso de linguagem natural.

A listagem mostrada é um curto exemplo mas na verdade traz os conceitos de um domínio, apenas utiliza uma linguagem imperativa mais natural e em português para a definição de regras de negócio, o que não é uma DSL. Na verdade DSLs não dizem anda sobre a sintaxe, se é declarativa ou imperativa ou qualquer outra coisa, ela apenas define uma linguagem que é utilizada para modelar um domínio específico, como gerência de estoque.

Para ser uma DSL teríamos conceitos como produto e estoque implementados como construtos da linguagem utilizada, exemplos e um ótimo texto do Fowler em:

http://martinfowler.com/articles/languageWorkbench.html

BPM, ESB, SOA e toda a parafernalha correlata não implicam em DSLs, na verdade não existe nenhuma ligação exceto que implementações como o mencionado Jboss Rules/Drools trazem alguns recursos para implementar mini-linguagens. Infelizmente ainda estão bem longe do ideal, na verdade a Microsoft tem uma linha de produtos antagônicos ao MDA que se aproxima mais do que se esperaria de uma LanguageWorkbench:

http://msdn2.microsoft.com/en-us/teamsystem/aa718951.aspx

No lado Java existem empresas que estão construindo seus workbenches, entre elas a JetBrains:

http://www.jetbrains.com/mps/
http://www.metacase.com/

Você Pergunta 001: DAOs e Repositórios

Thursday, March 1st, 2007

Como todo mundo que bloga há anos, eu estou sem tempo e inspiração para escrever muito (dá pra ver a distância entre um post e outro), então resolvi colocar aqui algumas respostas de e-mails que recebo com questionamentos sobre artigos, posts e etc.

O primeiro segue abaixo:

fromLeandro André Zis
date Feb 23, 2007 11:15 PM
subject Artigo MVC e Camadas, Repositorio e DAOs

Ola Phillip,

No artigo MVC e Camadas mostra os DAOs herdando do repositorio, isto
esta correto?

Leandro Zis

Oi, Leandro,

Sim, está.

Um repositório é um conceito abstrato. Ele representa o lugar onde os objetos estão guardados esperando serem utilizados por alguma operação. Os outros objetos de negócio não enxergam nada além dele, ou seja, não sabem onde os objetos são guardados de fato, num banco de dados, arquivos CSV, etc.

Um DAO (Data Access Object) é uma encarnação do padrão Data Mapper cuja responsabilidade é mapear um objeto para tabelas e vice-versa.

Desta forma o DAO pode se tornar a implementação do Repositório. Os objetos de negócios sabem apenas que podem guardar e recuperar objetos do Repositório, nada além disso. Por baixo dos panos eles estão utilizando um DAO que implementa o Repositório, cuja responsabilidade é apenas salvar e recuperar objetos do banco de dados nada além disso.

Existem casos onde os Repositórios devem ter lógica de negócio incluída. Isso não é muito comum, se for o caso vale uma revisão do design da aplicação, mas se realmente for necessário aí provavelmente você vai querer criar o Repositório como uma classe de negócios que delega as atividades de persistência para um DAO. Fazer este Repositório com regras uma classe abstrata que o DAO herda seria ruim porque numa classe (o DAO) haveria responsabilidade de negócios e persistência.

[]s