O Laércio Queiroz me entrevistou sobre DSLs. O resultado você vê no blog dele.
Archive for the ‘plataformas’ Category
Entrevista sobre Domain-Specific Languages
Tuesday, January 29th, 2008Você Pergunta: RAD
Thursday, January 24th, 2008Uma pessoa me escreveu um email sobre o tópico anterior. Novamente não vou citar nomes porque não pedi permissão (e não tenho motivos para expôr esta):
Shoes, beleza cara?
Então, lendo sobre a discussão sobre o Maker eu cheguei no seu blog e li sobre RAD.
Aquela ferramenta no NetBeansLixo pra fazer GUIs é um RAD? Ele desenvolve parte de um software, eu sei, não é um modelo de processo de desenvolvimento, né??Enfim, acredito que existam mais algumas por aí como Maker e queria saber da sua opinião: todas essas ferramentas são RADs e todas elas cometem gafes? Onde quero chegar é na pergunta: Hoje em dia, SEMPRE teremos um desenvolvedor por trás da solução?
É que eu sou totalmente contra essas ferramentas de gerar códigos automáticos… não confio muito nessas coisas… prefiro eu mesmo fazer os códigos, mas tenho a dúvida: estou muito antiquado (no sentido de muito atrasado e não acompanhando as tecnologias que estão evoluindo hoje) ou estou no caminho correto?
Bom, se você respondeu que sim na primeira pergunta (do NetBeans sobre GUIs), a principal desvantagem das ferramentas RAD (se é isso que aquele Lixo é) é a manutenção e evolução, certo? Uma vez, fazendo um trabalho pra faculdade, tive que usar aquele NetBeans. Quando fui usar Refactoring… nossa cara, que coisa mais chata… tive que refazer praticamente toda a interface gráfica.
Abraço.
Apesar de usar, eu odeio o termo RAD. Ele significa um grupo enorme de coisas e ao mesmo tempo não significa nada. O livro Software Development: Building Reliable Systems define RAD:
For the last ten years, many software projects have incorporated the use of “Rapid Application Development” methodologies in an effort to decrease development times. RAD, as it is generally referred to, incorporates an umbrella of methodologies based on spiral, iterative development technologies. RAD techniques range from the simple use of GUI development tools to quickly build prototypes, to processes incorporating complete, cross-functional business analysis. [...]
Então vou considerar que você quer dizer por RAD “ferramentas geradoras de código” do contrario este post nunca vai acabar. Sim, o Matisse do Netbeans é uma ferramenta geradora de código.
Ferramentas geradoras, em geral, são úteis quando não querem dominar o mundo. Eu adoro quando o Hibernate ou o Rails gera meu DDL SQL e eu não tenho que escrever CREATE TABLE. Eu adoro quando o Eclipse gera meus getters e setters e coisa do tipo. O problema é que esses geradores não costumam sobreviver num projeto de verdade.
O grande problema do gerador de código padrão, como o citado, é que ele possui diversos vazamentos de abstração. O Joel Spolsky fala especificamente sobre geradores:
The law of leaky abstractions means that whenever somebody comes up with a wizzy new code-generation tool that is supposed to make us all ever-so-efficient, you hear a lot of people saying “learn how to do it manually first, then use the wizzy tool to save time.” Code generation tools which pretend to abstract out something, like all abstractions, leak, and the only way to deal with the leaks competently is to learn about how the abstractions work and what they are abstracting. So the abstractions save us time working, but they don’t save us time learning.
Como pode-se perceber pelas discussões citadas o mercado destas ferramentas é… complicado. Um desenvolvedor que entende como a plataforma funciona (Java EE, no caso) dificilmente se encantaria pela ferramenta. Ele pode utilizar algo como um Spring IDE para gerar arquivos de configuração mas sabe que isso não é tão simples assim.
Os programadores mais recentes na plataforma Java podem não ter consciência disso mas uma ferramenta chamada xdoclet era muito usada quando sofríamos diariamente com EJBs 2.1. O que o xdoclet faz é gerar código, ele gerava todo o mapeamento do EJB (uns 3 arquivos XML diferentes, pelo menos) a partir de anotações JavaDoc (não existia Java 5 naquela época). O xdoclet era a salvação da lavoura, conseguia abstrair muitos problemas mas.. não era perfeito, nem pretendia.
Eu já trabalhei em projeto onde 50% do código era gerado pelo xdoclet e do restante ele não dava conta. A ferramenta não possui o tal do round-tripping então não dava para misturar código gerado com modificado. A solução foi optar por uma arquitetura que isolava as duas partes em módulos diferentes e só conseguimos chegar até ela porque –como disse o Joel- sabíamos como a ferramenta funcionada. Essa é uma ferramenta de automação, não de “geração automática de sistema”. Ela automatiza o trabalho que você teria, não te livra do fato de conhecer o que… bem… é sua profissão.
Acho que o Matisse se enquadra neste tipo.
O problema é que essas ferramentas –e seus persuasivos vendedores- dizem que irão abstrair todo o desenvolvimento. Para os cenários ideais elas podem fazer todo o prometido mas não houve até hoje uma ferramenta que conseguisse real sucesso fora dos casos mais simples e isso porque não é assim que construímos sistemas hoje. Nossos sistemas são uma salada de linguagens, conceitos, mapeamentos e configurações que uma ferramenta deste tipo não consegue acompanhar.
O que geralmente elas fazem é te prender à uma ou algumas arquiteturas genéricas que servem razoavelmente para alguns casos -geralmente sitezinhos CRUD de intranet- mas não para todos ou sequer para a maioria. Como arquitetura não é commodity não se pode simplesmente aplicar a mesma estrutura em todos os cenários.
Apos algum tempo em TI você começa a entender que o dia-a-dia desse mercado é um grande “mais do mesmo”. Você sempre está criando as mesmas coisas. Da última vez que contei eu já tinha criado uns sete gerenciadores de conteúdo web. Dá para utilizar a mesma arquitetura em todos? Não. Uns eram simples formulários, outros se integravam com back-ends complicados, outros era assíncronos, outros tinham integração com legado… cada um tinha uma história. Se há oito anos atrás eu comprasse uma ferramenta dessas e a tivesse aplicado nestes projetos eu teria que fazer personalização (i.e. sair do maravilhoso mundo do fluxograma) a cada projeto.
Mas eu estou falando de desenvolvimento de software de um tipo, não do mercado todo. Quando estive na faculdade pela última vez (antes da segunda fuga) estudei com uma pessoa de 43 anos que desde os anos 80 vive fazendo software em coisas como CLIPPER para lojinhas e boutiques. Ele não ganha mal. Pelo que entendo dos softwares deste tipo (já trabalhei neste ramo) a arquitetura é quase sempre a mesma. Talvez ele se favorecesse de algo assim nos seus negócios, apesar de que eu ainda acharia um risco desnecessário.
Então sim, hoje precisamos de desenvolvedores para projetar um sistema. Desenvolver sua arquitetura, seu design e verificar para que tudo seja eito da maneira mais adequada para o projeto (que nem sempre é a técnica mais adequada). Mas e o futuro?
O futuro prevê o uso de ferramentas de um nível mais alto, mas de maneira diferente. O ponto crucial é que essas ferramentas não são geradores de código Java (ou C#, ou Ruby ou o que for), elas mudam a visão sobre o código. Ferramentas como Domain-Specific Languages aumentam o nível da linguagem não tornando-a mais abstrata apenas mas sim levando para perto do negócio. Ferramentas de visualização criam pontos de vista diferenciado sobre o mesmo artefato, dependendo de com que olhos se enxerga.
Tudo indica que para desenvolver softwares no futuro o desenvolvedor não terá o mesmo papel que tem hoje. Ao invés de criar o código do sistema em si iremos criar as ferramentas que dão suporte à criação de sistemas pelos usuários.
Seja qual for o futuro ele não é sobre gerar código. Isso nós já fazemos à décadas e serve apenas como quebra-galho para nos livrar da complexidade que nós mesmo criamos.
Programação RADioativa
Sunday, January 20th, 2008Há alguns anos, quando era consultor independente, eu fui chamado por uma empresa bem grandinha do ramo de telefonia. Eles tinham produtos em C++ e queriam migrar para o Java. Na verdade já haviam migrado, mas estavam com problemas.
A primeira tentativa deles foi transferir toda a parte gerencial do sistema -que era vendido por alguns milhões de Euros- para Java. Para fazer esta etapa eles haviam contratado há um ano uma consultoria especializada canadense. Os canadenses sugeriram a compra de uma ferramenta RAD -por um acaso de outra empresa canadense- que permitiria que os desenvolvedores C++ criassem a aplicação em pouco tempo. Em três meses, tempo recorde, a aplicação já estava rodando no cliente, em produção. Durante os testes eles verificaram que a coisa era muito lenta mas como o mercado de telefonia tem muito dinheiro eles simplesmente aumentaram o número de máquinas.
A coisa foi passando até que alguém foi fazer a primeira manutenção. O sistema era um grande catálogo de assinantes, dependentes e registros de ligação, as regras pesadas mesmo ficavam no sistema em C++. As primeiras manutenções foram correção de bugs. A ferramenta funcionava dentro do Eclipse, você definia um modelo de entidades parecido com o modelo relacional, depois dizia quais operações precisava (criar, ler, listar, etc.), isso gerava o código. Se você precisasse de uma regrinha de negócio diferente, digamos que cada vez que um novo cliente fosse adicionado alguém recebesse um email, ia ter que alterar o código gerado. Como a aplicação -como todas- tinha suas peculiaridades muito código era escrito a mão. Mesmo assim o ato de criar toda a infra-estrutura (o scaffolding) poupava muito tempo.
Qual não foi a surpresa quando alguém reparou que a ferramenta só gerava código, ela não o lia de volta? Se você alterar o código e fizer alguma alteração o fornecedor deu duas escolhas:
- Alterar o código usando a ferramenta gráfica, regerar o código e depois adicionar novamente nossas alterações
- Abandonar a ferramenta e fazer tudo no código
Neste ponto que eu fui chamado. O fornecedor sugeria fortemente a segunda opção, por incrível que pareça. Eu concordei com eles, recomendei ao cliente que assumisse o prejuízo de ter escolhido uma ferramenta ruim e refatorasse o sistema enquanto inseria novas funcionalidades.
O mundo adora ferramentas RAD. Elas provocam a ilusão de que você não precisa de conhecimento ou de um profissional para criar programas. Não é assim que a banda toca.
Essas ferramentas surgem todos os anos. Todos se dizem revolucionários, quase nenhum diz que é um gerador de código, e todos dizem que servem para 87% dos casos. Puro marketing.
Geradores deste tipo existem há décadas. É até engraçado que o mais novo representante desta leva se gabe de ‘revolucionar’ usando o conceito de programação visual por fluxograma. Ahm? Isso existe praticamente desde que surgiram IDEs gráficas. Qualquer coisa que gere código via UML vai ter um fluxograma. A diferença é que não vai ter só fluxogramas, exatamente porque essas coisas foram abandonadas.
Na UML utilizamos o diagrama de atividades para um fim muito específico: representar transição entre estados dos objetos. É um dos diagramas mais raramente utilizados em um projeto OO simplesmente porque ele é procedural demais. Um sistema OO foca na interação entre objetos, não em algoritmos em si -que estão encapsulados dentro dos objetos.
Ao utilizar um fluxograma como unidade principal do seu sistema você está abandonando a OO. Isso pode ser uma coisa boa, depende do caso. para sistemas genéricos décadas de pesquisa da indústria apontam que Orientação a Objetos traz os melhores resultados na modelagem de negócios. Para um caso específico (BPM por exemplo), fluxogramas podem ser melhor. Estas ferramentas vendem trinta anos de retrocesso em modelagem.
Ainda assim, elas oferecem um bom scaffolding, não? Você não precisa saber nada sobre arquitetura, basta gerar o código na ferramenta! Bem, não exatamente. A maioria destas ferramentas vai seguir o exemplo acima: possuem poucos pontos de extensão e quando possuem não conseguem se integrar a eles. A primeira pergunta a fazer para um fornecedor desses é se a ferramenta suporta round-tripping. Round-tripping é o ato de gerar o código na ferramenta, editar o código e a ferramenta ser capaz de lidar com o código alterado. Quase nenhum RAD possui esta característica.
Outro problema é a arquitetura. Eu tenho certeza que uma arquitetura web simples pode ser utilizada por 87% dos casos mas tenho mais certeza ainda que cada um destes casos vai evoluir de uma maneira diferente. A arquitetura tem que ser flexível o suficiente para permitir todas estas formas de evolução. Obviamente que nenhuma destas ferramentas oferece nada parecido. Nós já vimos antes sobre o problema de se estabelecer uma arquitetura única para tudo, o problema com estas ferramentas é muito pior. Quando se define uma única arquitetura para todos os sistemas de uma empresa é ruim mas o que estas empresas estão vendendo é uma arquitetura única que funcionaria em diversos tipos de aplicações de diversos domínios sem sequer saber as necessidades delas antes.
Infelizmente em busca do cálice sagrado as empresas e -pior ainda- governos vão continuar gastando dinheiro nestes engodos. Eles prometem inovação mas fazem retrocesso de três décadas no tempo. Como conseguem montar um CRUD em 30 minutos são vendidos como a última bolacha do pacote, e lá vão os gerentes desinformados comprar estas coisas.
Se você está procurando este tipo de ferramenta esqueça qualquer um desses produtos ‘revolucionários’. Para começar entenda que a Ciência da Computação ainda não tem uma resposta definitiva para você. Sinto muito, estamos trabalhando nisso (é uma das partes da minha pesquisa). O campo mais avançado nesta área chama-se MDA. Eu não acredito em MDA mas isso não me faria negar que ela é a proposta mais plausível para este tipo de ferramenta atualmente. MDA possui implementações livres e proprietárias, é um padrão do OMG, utiliza UML, é baseado em um conceito de transformação de modelos e não de geração de código, é extremamente extensível e pode ter as características de produtividade dessas ferramentinhas de garagem. Só não baseie sua estratégia nele.
Os problemas de MDA: (1)ele eleva o nível de abstração mas não gera programação intencional e (2)ele usa uma ferramenta que não foi criada para isso, UML. São problemas muito menores do que os que você vai enfrentar com estes softwares ‘revolucionáros’ de ‘programação por fluxograma’.
Não caia no conto do vigário.
Expressividade no Código
Friday, December 28th, 2007Um post no GUJ mais uma vez rende uma resposta maior do que se supunha. A thread em si é bastante útil mas existe muito ruído então vou tentar sumarizar:
Vocês pegam códigos que te faz passar horas e horas tentando entender o que está sendo feito? Valores que você nem imagina de onde estão vindo?
Eu sou muito ruim ou isso é normal?
E logo surge alguém sugerindo que deveria haver documentação. Existem casos onde documentação, seja JavaDoc, especificação funcional ou etc. é fundamental mas neste caso é diferente. JavaDoc, especificação textual e etc. devem ser uma fonte importante quando que está interessado nessa informação não vai lero código, é como reutilizar uma biblioteca ou um framework. Ninguém quer abrir o Spring para entender como utilizá-lo, precisamos de documentação para isso.
Um cenário completamente diferente é quando você recebe de presente um código já existente para dar manutenção. Neste caso o código tem que fazer sentido, tem que dizer algo. Tem que ser expressivo, mostrar suas intenções claramente.
NOTA: O trecho abaixo foi escrito direto no editor de texto, sem ajuda de compilador ou IDE. Por favor me corrijam.
Qualquer programador meia-boca sabe sua linguagem. Sabe o domínio dela. Veja o trecho abaixo:
abstract class A{
public abstract int d(){
}
}
class B extends A{
int z= 0;
int x=-1;
public B(int z, int x){
this.z=z;
this.x=x;
}
public int d(){
if(z==15) return x + x* 0.15;
esle return x;
}
}
Você entendeu muito bem, tenho certeza, que A é uma classe abstrata implementada por B. Que B tem um construtor que recebe dois inteiros, os armazena e usa numa computação simples com uma ramificação abaixo. Ótimo.
Imagine que você recebeu um email do seu usuário dizendo: “Precisamos fazer com que clientes do sexo feminino que comprem mais de R$1000,00 ganhem 10% de desconto.”. Tente implementar isso no código acima enquanto eu vou almoçar.
E aí, terminou? Sim, sim, claro que é impossível sem saber d que se trata. Então depois de procurar bastante você encontra no diretório onde fica a documentação do projeto um arquivo que pode te ajudar a entender. Após umas cinquenta páginas de diagramas de alto nível inúteis explicando tudo que acontece no container web você chega a uma descrição de algo como:
A classe A tem a lógica abstrata de uma venda. As vendas são sempre feitas de acordo com critérios específicos por isso existem classes que implementam vendas específicas. No momento (01/10/2003) só existe uma implementação, na classe B, que é a venda para uma pessoa física.
A primeira coisa que você pensa é: se desde 2003 ninguém precisou de outra implementação para que essa maldita classe abstrata? Mas ants de mexer no código precisamos entendê-lo, então vamos em frente.
O méodo e questão recebe três argumentos: a quantdade em reais vendida, o sexo da pessoa (segundo código vindo do mainframe na tabela ETXS32) e se a compra é casada ou não (um booleano).
De acordo com o caso de uso UC171 o sexo do comprador é utilizado para aplicar descontos.
TABELA ETXS32
15 -> masculino
22 -> femininoSe a compra for casada o processamento é feito delegando para outra classe, mantendo o padrão Strategy, Composite e Adapter do Decorator. Note que o Chain of Responsibility do Bridge é usado com Visitors para passar as instâncias de Flyweight pelos Interpreters[...]
Após a sequência de buzzwords de padrões é bom parar. Acho que a informação necessária já está aí em cima e olha que não se passaram nem 4 horas de procura! Vamos lá: recebemos o valor, o sexo segundo um código numérico sem lóica que vêm de outro sistema. Também é passado um boolean.. cadê o boolean?
Procurando no histórico deste arquivo no CVS (poxa vida, eles ainda usam CVS!) você vê que no meio de 2005 alguém tirou o boolean de lá com um comentário ‘Removido compra casada. Ninguém usa isso e ninguém entende isso. Ninuém vai sentir falta’. Acho que a pessoa estava correta mas ela esqueceu que existem uns 300 documentos que precisam ser revistos porque todos fazem referência a esta tal venda casada, do caso de uso, diagrama de domínio até diagrama de deployment. Cada mudança simples implica em editar 300 documentos… provavelmente mais tempo atualizando a tal documentação que o código… dá pra culpar o desenvolvedor?
Bom, agora você entende o que o código faz ao menos. Ele está aplicando um desconto de 15% para homens, você não conseguiu achar isso no caso de uso mas se ninguém está reclamando em produção é porque deve ser assim mesmo. Amanhã (afinal, você perdeu o dia inteiro hoje na ‘documentação’ do sistema) você faz a mudança.
Novo dia e você está pronto para alterar este código. Hmm… alterar pode ser muito rápido e sujo ou devagar e bem feito. Como disse o Uncle Bob recentemente sujo nunca é rápido então você opta pelo caminho com mais qualidade (e mais ético).
Como desenvolvedores profissionais escrevem testes (e gerar você deve começar por aí. Você sabe muito pouco sobre este sistema e o teste vai te dar alguma garantia que a menos esta pequena parta que está mexendo vai continuar funcionando após suas modificações. Vamos lá:
class TestVenda extends TestCase{
public void testDeveAplicarDescontoSeSexoDoCompradorForMasculino(){
B vendaParaUmHomem = new B(15, 100);
assertEquals("Valor final sofreu 15% de desconto", 85, vndaParaUmHomem.d());
}
public void testDeveNaoAplicarQualquerDescontoSeVendaNaoCaiEmNenhumaPromocao(){
B vendaParaUmHomem = new B(9999, 1);
assertEquals("Valor final intacto", 1, vndaParaUmHomem.d());
}
}
Os testes executam. Agora vamos alterar um pouco esta classe, pensando no pobre coitado que for mexer nela após você. Vamos começar agregando nomes mais expressivos:
abstract class VendaAbstrata{
public abstract int vender(){
}
}
class Venda extends VendaAbstrata{
static final int NAO_INFORMADO = -1;
static final int MASCULINO = 15;
static final int FEMININO = 22;
int sexoDoComprador= NAO_INFORMADO;
int valorDaCompra=-1;
public B(int sexoDoComprador, int valorDaCompra){
this.sexoDoComprador=sexoDoComprador;
this.valorDaCompra=valorDaCompra;
}
public int vender(){
if(sexoDoComprador==MASCULINO) return valorDaCompra - valorDaCompra* 0.15;
esle return valorDaCompra;
}
}
Já está bem melhor, não? Compare com a primeira versão do código Os testes passam? Então é hora de commitar (eu acho esse neologismo horrível mas alguém sugere algo melhor?).
Vamos para o segundo round: pequeno refactoring. Já é possível fazer a alteração neste código mas anda temos tempo para deixá-lo um pouquinho mais legível, mais claro, mais expressivo. Vamos alterar:
abstract class VendaAbstrata{
public abstract int vender(){
}
}
class Venda extends VendaAbstrata{
static final int NAO_INFORMADO = -1;
static final int MASCULINO = 15;
static final int FEMININO = 22;
int sexoDoComprador= NAO_INFORMADO;
int valorDaCompra=-1;
public B(int sexoDoComprador, int valorDaCompra){
this.sexoDoComprador=sexoDoComprador;
this.valorDaCompra=valorDaCompra;
}
public int vender(){
int valorFinalDaCompra = aplicarDescontosSobreValorDaCompra();
return valorFinalDaCompra;
public int aplicarDescontosSobreValorDaCompra(){
int valorComDesconto= valorDaCompra;
if(sexoDoComprador==MASCULINO)
valorComDesconto = descontarPorcentagem(15, valorDaCompra);
return valorComDesconto;
}
public int descontarPorcentagem(int porcentagem, int valorOriginal){
return valorOriginal * (porcentagem / 100.0);
}
}
Agora que tal esta versão do código + teste unitário contra a versão antiga + trezentos documentos e especificações? A implementação da regra nova ficou fácil? Acho que sim, tanto que deixo como exercício ao leitor, bem como algumas dezenas de refactorings que vão deixar o código acima decente.
A resposta curta para a thread do GUJ é: geralmente o problema não é seu mas de quem escreveu o código.
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
-Martin Fowler, “Refactoring: Improving the Design of Existing Code “
Usando Netbeans Para Editar Código Ruby? Ainda não…
Sunday, December 9th, 2007Essa semana no trabalho resolvemos (meu par e eu) ceder aos outros 3 pares que trabalham conosco (a rotação de pares infelizmente é baixa por alguns critérios internos) e tentar usar o Netbeans para editar Ruby (ninguém na equipe ou na empresa sonha em usar esta ferramenta para Java). Eu já havia conversado com um pessoal no escritório da TW sobre isso e me pareceu bom dar uma chance.
O Eclipse RDT era nossa ferramenta mas desde que a Aptana “comprou” (usando o antigo vocabulário do Marc Fleury, que Zahl o tenha) o projeto usá-lo é um problema só. Ninguém morre de usar mas dá raiva.
Então vamos lá. Um download gigantesco (normal para as IDEs inchadas de hoje em dia…) e temos o bicho rodando. A versão mais recente, claro. Ops, JVM capotou na primeira tentativa, vamos tentar de novo. Ok, funcionou.
Quase uma semana usando a ferramenta eu posso dizer que o editor para Ruby está muito melhor que qualquer versão do RDT. O code complete, syntax highlight, tudo muito bem. Aí você começa a ter os problemas quando sai do editor (afinal, uma IDE é um ambiente integrado, certo?). A integração com SVN é uma piada, é m parto fazer checkouts e commitar coisas. Os diffs e logs são bem burrinhos. A navegação entre abas e entre arquivos é custosa e muitas vezes não funciona (me parece que você só consegue transitar entre os X últimos arquivos que mexeu). Criar uma source folder para Ruby? Isso não faz sentido. Em Ruby geralmente tudo é código-fonte, da sua task rake até a configuração do banco de dados. Os atalhos de teclado são razoáveis, você só precisa se dar conta que está numa espécie de mundo bizarro do Eclipse, os atalhos são a mesma coisa só que com ALT em vez de CTRL ou coisa assim (para quem fez a migração pra Mac isso não é novidade).
Minha conclusão final é que o editor do Netbeans para Ruby (ao contrário de para Java) é infinitamente superior ao do Eclipse RDT. O problema é que não só o editor faz a IDE, se for para não er o ambiente integrado eu prefiro usar emacs. Acho que dados os pontos fracos de cada um tanto faz ficar com Eclipse ou Netbeans. Eu não ficaria com nenhum.
No Mac eu uso o maravilhoso Textmate. No Windows e Linux eu passei algumas semanas brincando com o OpenKomodo e ele é muito bom, traz os benefícios do Textmate para o ‘PC’ (hoje em dia tudo é PC mas vocês entenderam…)
Já Temos Tecnologia o Suficiente
Monday, December 3rd, 2007Estava pensando sobre o texto que escrevi ontem sobre modelos de negócio afetados por escolhas tecnológicas e acho que posso ter confundido alguém. Minha idéia não é dizer que modelo de negócio não é importante, pelo contrário este é a coisa mais importante numa empresa, apenas atentei para o fato de que as escolhas tecnológicas afetam o modelo de negócios. O caso de exemplo era sobre uma empresa com ótimo modelo e tecnologia não adequada.
Na verdade, provavelmente a tecnologia existente há alguns anos é mais que suficiente para modelar de excelente maneira qualquer domínio. O problema é que ainda somos (como indústria) amadores no desenvolvimento de software.
Veja por exemplo meu primeiro dia no projeto novo. Uma das maiores empresas da Austrália precisa migrar milhões de dados sobre seus clientes do sistema legado para o novo. Eu cheguei no meio do projeto e minha primeira tarefa é atuar no sistema que faz uma checagem ara ver se os dados foram mirados corretamente. Moleza.
Até a hora do almoço meu par e eu tínhamos escrito todo o script Ruby que conecta com o servidor do sistema legado, obtém o resultado da consulta desejada como HTML, faz parsing dele com o hpricot, armazena num banco de dados utilizando ActiveRecord, chaa os scrits e comparação, faz caching em disco e retorna um resultado em XML. Tudo isso rodando numa task do rake e testado com RSpec. Moleza.
O difícil foi fazer os scripts de comparação. A tecnologia já oferece mais que suficiente para criar este mecanismo, já fizemos uma arquitetura baseada no padrão Chain of Responsibility que vai validar todos os casos mas e entender as regras do negócio?
Sempre vai ter aquele que diz “ora, tá tudo documentado em caso de uso, diagrama de domínio e etc.’. Já tive o desprazer de trabalhar em diversos projetos que acreditavam que isso é verdade e invariavelmente o resultado era que o novato só ficava produtivo depois de um mês e pouco.
Hoje, no meu primeiro dia no projeto novo, já consegui ser produtivo e implementar boa parte de uma história. A mágica não está no Ruby, não está no Mac, não está no Java nem no SOA. Está em uma palavrinha que eu coloquei no texto lá no início e talvez tenha assado despercebida:
Até a hora do almoço meu par e eu tínhamos escrito todo o script[...]
Na chegada eu fui recebido com uma visão geral do sistema, seus objetivos e arquitetura. Em uma hora eu estava programando uma parte importante e para me mantêr dentro do domínio havia ma pessoa com anos de experiência na casa pareando comigo. Acredito que amanhã pela manhã tenhamos completado a user story que estávamos implementando.
A tecnologia vai continuar evoluindo e nos levando para luares fantásticos mas o que a maioria das empresas precisa é de uma faxina no modo de pensar das pessoas, tanto do alto quanto do baixo escalão.
Modelo de Negócios e Tecnologia
Sunday, December 2nd, 2007Há alguns anos eu trabalhava para uma grande empresa que cria produtos em um nicho muito específico. Dá última vez que eu vi alguém fazer uma estatística 90% dos produtos eram em C, 5% em C++ (”muito lenta”) e o restante em PERL, Python e Java.
A coisa que eu mais gostava sobre essa empresa era como o modelo de negócios deles era movido por inovação. Quando alguém tinha uma boa idéia ele era convidado a montar um protótipo em laboratório que seria oferecido à clientes. Haviam muitos ganhos para os bem-sucedidos, meu chefe, diretor regional de tecnologia, subiu ao seu cargo após duas idéias convertidas em produto (além de ganhar uma boa grana).
No entanto, apesar da inovação presente nos novos produtos lançados simplesmente não havia inovação técnica. Não importa o software, tudo era feito em C. Eu fui contratado para um novo time que cuidava das alicações Java. Estas aplicações só foram criadas porque os clientes exigiam interfaces web e RMI para os produtos da empresa e porque contratar programadores C sempre foi um problema. Mesmo trabalhando basicamente com Java (e naquela época o sonho de todo mundo era arrumar um emprego “100% Java, nada de PHP ou VB”) boa parte do meu trabalho era escrever e testar interfaces em C que se comunicavam com o sistema “de verdade” (o feito em C).
Certa vez me mandaram por 10 dias, que viraram 20, numa viagem de trabalho. O lugar não era muito amigável com turistas então passei boa parte do tempo no quarto de hotel tentando entender a televisão. Como não tinha Internet liberada eu passava no dia baixando PDs e páginas completas para ler à noite e nos fins-de-semana. Com o tempo pensei: e se eu reconstruisse o sistema em Java? Obviamente que não consegui reproduzir o sistema todo dado o tempo mas se o sistema antigo tinha 5% em Java eu consegui que fosse unas bons 30%. Chegue no escritório doido para mostrar ao meu chefe.
Obviamente foi um banho de água fria. A pessoa ficou feliz por eu me interessar pelos projetos internos e disse que iria ver o sistema, um dia. Esse dia nunca chegou. Após alguns meses eu pedi demissão da empresa.
Dia desses estava falando com um amigo que ainda trabalha lá e soube que 50% dos clientes foram embora. Na época que eu trabalhava nessa empresa ela tinha quase que o monopólio de um dado tipo de sistema, com tempo concorrentes foram surgindo. O sistema da empresa era claramente superior aos outros mas era muito menos flexível. Ele era muito bom no que fazia mas quando precisávamos que ele fizesse a coisa um pouquinho diferente o projeto durava meses. Os concorrentes chegaram com linguagens como C++ e Java e apesar de não terem um produto com 10 anos de bons serviços prestados eles conseguiam mudar rapidamente.
Há dez anos a escolha por utilizar C e IPC de UNIX na mãozona era certa. Nenhuma plataforma da época oferecia o desempenho aceitável. Infelizmente as pessoas acabam construindo as piores coisas do mundo com desculpa de performance e o sistema era completamente monolítico e depende tanto do SO que mudar de uma versão minor para a outra leva um ano com um time de 3 pessoas completamente dedicados.
Se esta empresa acompanhasse os movimentos da indústria veria que existiam plataformas que já ofereceriam performance aceitável (eu já trabalhei em sistemas Java mais eficientes que aquele em ouros lugares) e que iriam oferecer a flexibilidade necessária. Infelizmente só repararam isso quando a concorrência invadiu o mercado.
A empresa continua com produtos ótimos em suas idéias mas ninguém consegue esperar 2 anos para colocar algo no ar. As coisas mudaram e escolher a tecnologia certa para cada caso é cada vez mais o qe define sucesso ou fracasso de um projeto. Ou de uma empresa.
Problemas no WordPress…meio que corrigidos
Sunday, November 18th, 2007No ConexãoJava eu fiz um apelo por alguém que soubesse PHP e, especificamente, WordPress para me ajudar. Nenhuma boa alma :’(
Partindo dia 21 para Melbourne eu estou sem computador, quase sem celular, sem telefone fixo e, por consequência, sem Internet. Aproveitei uma tarde na casa da minha sogra entre um forumlário preenchido e um apartamento para alugar procurado, baixei o putty no computador do meu cunhado e tentei resolver o problema.
O Google não me trouxe nada de útil além de milhares de sites com o mesmo problema. Quando eu tentava atualizar o WordPress recebia a mensagem:
1. WordPress
2.
3. WordPress database error: [Unknown column 'user_nickname' in 'field list']
4. SELECT ID, user_nickname, user_nicename FROM wp_users
Tentei remover todos os plugins. Nada. Remover temas. Nada. No final acabei tentando entender o upgrade.php e percebi que o problema certamente estava em uma variável que guarda a versão do banco de dados, a $wp_db_version. Ela deveria ser menor ou igual à 5183 e tinha valor 1! Não sei exatamente o que ocorreu mas certamente isso não era um estado válido.
Solução? Entrei no MySQL e rodei:
UPDATE `wp_options` SET `option_value` = '5183' WHERE `wp_options`.`option_id` =73 AND `wp_options`.`blog_id` =0 AND CONVERT( `wp_options`.`option_name` USING utf8 ) = 'db_version' LIMIT 1 ;
Eu não tenho a menor idéia das consequências deste hack mas por enquanto tudo funciona. Já fiz backup da minha base de dados, por via das dúvidas…
Tive também que deletar uns 3000 spams que foram postados como comentários neste tempo. O Plugin anti-spam parou de funcionar e eu quase enlouqueci!
Second Life
Monday, November 5th, 2007O G1 acabou com seu blog no Second Life. Ninguém liga mais para Second Life. Uma das coisas mais engraçadas sobre estes “novos” conceitos de Internet é ver um bando de gente das mais variadas áreas falando sobre os temas sem entender quase nada do assunto.
O que move a Internet desde sempre são as possibilidades derivadas do aspecto técnico. O curioso é que o programador não está pronto para lidar com isso, ele passou anos, décadas aprendendo a somente pegar as regras de negócio de alguém e transformá-las em código, quando temos um ambiente como a Internet onde quem sabe mais sobre o negócio é o programador ele simplesmente trava.
Enquanto você não colocar um arquiteto de informação lado a lado com um desenvolvedor você não vai ter nada que preste. É óbvio para alguém que entenda minimamente do que é feita a Internet que o Second Life não ia dar em nada simplesmente porque é uma plataforma de software muito pobre. Não falo dos recursos 3D mas sim da forma de distribuição.
“Não tem ninguém lá”, as pessoas reclamam. É óbvio que não vai ter, quem vai querer fazer o download, criar uma continha, um avatar e ter que abrir aquele programa enorme e lento toda hora para conversar com as pessoas? Pergunte a qualquer programador experiente e ele vai ter dizer que esse problema já matou diversas outras boas iniciativas, se você está querendo introduzir algo novo não obrigue as pessoas a usar algo só para isso.
É só olhar a história dos Instant Messengers. O ICQ é muito melhor que qualquer alternativa (eu acho que já usei todos) exceto o Jabber (que é um protocolo aberto e padronizado, outro nível) mas ainda assim não deu em nada. Quando o conceito de instant messaging ficou popular não foi através dele, foi com MSN, Yahoo! Messenger e agora o Google Talk. Instalar o ICQ e utilizá-lo numa conexão de 33kpbs era uma droga e quando a conexão ficou aceitável a Mirabilis já era passado.
Fale sobre FTP, Gopher,Finger ou qualquer outra coisa que não seja HTML entregue via HTTP que a maioria dos “profissionais de internet” não vai sequer entender. Fazendo uma versão do famoso bordão da comunidade Lisp: Aqueles que não conhecem de verdade a Internet estão fadados a repetir os erros que já foram cometidos.
Programadores Profissionais Escrevem Testes, Ponto Final.
Wednesday, October 31st, 2007O tópico já tem oito páginas. Acho que chega à 10. Por mais que minha mão coce para comentar lá eu não vou, simplesmente porque já tive problemas demais com o pessoal do Mentawai.
De qualquer forma sempre me preocupa a possibilidade de algum desenvolvedor ler o tópico e pensar “Poxa, se esses caras que fazem todos estes frameworks não usam testes por que eu vou usar?”.
Desenvolvedores profissionais escrevem testes. Simples assim.
Uma pessoa que não ganha milhões de dólares mas escreveu uma das obras mais clássicas deste ramo deixa bem claro em sua primeira aula que programar é gerenciar complexidade. Nós precisamos gerenciar complexidade o tempo todo, por isso criamos funções, objetos e tudo mais. Não adianta, mesmo Einstein teve que provar que suas fórmulas e execuções estavam corretas, que poderiam ser verificadas. Na faculdade aprende-se isso desde as cadeiras básicas (e o fato de ser esquecido como “coisa teórica inútil” me faz novamente perguntar sobre o valor do ensino formal).
Existe uma grande diferença entre fazer Test-Driven Development e testar. TDD é sobre modelagem de objetos e especificações, não sobre testes (tanto que Behaviour Driven Development está se consolidando como algo mais eficiente que TDD) apesar de que no final você acaba ganhando uma suíte de testes de graça.
É muito difícil achar um projeto open-source relevante que não tenha testes. Na verdade os projetos decentes só aceitam um relatório de bug ou um patch se vier acompanhando por um caso de testes. Imagine uma aplicação feita colaborativamente por diversas pessoas, como saber que o que eu acabei de fazer commit não vai quebrar o que você modificou ontem? Boas práticas de orientação a Objetos? Não se iludam, OO não foi feita para este tipo de verificação! Com boas práticas você consegue minimizar o impacto de mudanças diminuindo dependências mas você não vai ter certeza disso.
Eu sinceramente não sei que técnica é essa que faz programação defensiva evitar testes. Eu já li bastante sobre Orientação a Objetos e programação defensiva e não vi nada deste tipo, pelo menos não vindo de uma fonte com um mínimo de credibilidade. Um exemplo simples, imagine que o framework web imaginário Pagai possui um código parecido com este:
Acao acaoSendoExecutada = controladorPrincipal.acao(requisicao.acaoDesejada());
Simples, não? Agora imaginemos que o código do método acao(String) seja algo assim:
public Acao acao(String pathInvocado){
//verifica se acao possui o formato desejado, deve ter uma barra e deve ter dois itens separados por barra apenas
if((pathInvocado.indexOf("/") == -1) || (pathInvocado.split("/").size < 2)) throw new IllegalArgumentException("Path invocado ["+pathInvocado+"] nao possui o formato adequado (consulte a documentacao XYZ)");
//lógica...
}
Isso é programação defensiva: eu não estou aceitando o que me passam, eu verifico se é o que deveria e se for eu continuo, se não eu paro ali mesmo e deixo alguém tomar conta do problema, seja a classe em questão ou alguma outra mais acima.
Imagine que eu por engano commitei um código que utilize “” em vez de “/” nesta requisição. Se for numa parte central do código é bem possível que uns testezinhos peguem mas imagine que é utilizado apenas em um caso específico e que, por um acaso, eu baseei meu sistema de controle de jatinhos particulares 9meu chefe tem muitos jatinhos) nele. Quando eu fiz o comit não alertou. Quando eu fiz o build não alertou. Quando eu fiz meus testezinhos não alertou. Quando foi para a produção eu tive erro.
Ok, acontece. Programadores de qualquer tipo cometem erros. Eu vejo o problema muito rapidamente e o corrijo, temos uma versão beta em 15 minutos no ar, fantástico. Aí daqui há um mês outro programador comete o mesmo erro. Quando fizer o build não vai alertar. Quando fizer seus testezinhos não vai alertar. Quando for para a produção… Isso não é profissionalismo.
O que eu preciso é de uma suite de testes, unitários e de integração, que me digam que o sistema está incorreto já no processo de build, sem lançar jars beta, alfa ou gama.
Mas se tem um argumento nessa história toda que realmente me irrita é quando as pessoas dizem que “num mundo capitalizado não há tempo para testes” ou que “o cliente não quer saber como é feito, ele quer que funcione”. O cliente realmente não quer saber como funciona, ele quer que funcione. Mas ele também não vai querer saber que você alterou uma classe que usava barra para barra invertida e tudo parou de funcionar, ele quer que o problema não aconteça e se acontecer que seja corrigido rapidamente. Se seu sistema não tem qualidade -e testes fazem parte de qualidade- você não consegue isso. TI gasta fortuna das empresas reescrevendo sistemas simplesmente porque não foram feitos por profissionais, e profissionais se preocupam com a qualidade do que fazem. E isso inclui testes.
Não seja um amador.