Archive for the 'Design' Category

Micro introdução sobre orientação a aspectos (AspectJ)

Eu estava pensando em escrever sobre algumas coisas que têm me interessado ultimamente e que têm alguma relação com o post sobre vazamento de memoria em Java, mas eu percebi que não teria como, sem fazer uma pequena introdução sobre programação orientada a aspectos (aspect oriented programming, AOP). A gente já discutiu um pouco sobre isso no post sobre decorators em python, mas não fizemos nada mais introdutório (se você já tem uma noção do assunto, provavelmente não vai achar esse artigo muito útil). Então nesse post eu vou falar sobre alguns conceitos de desenvolvimento orientado a aspectos(AOSD), mas com ênfase descarada em AOP na forma como implementada em AspectJ. Eu não pretendo cobrir em profundidade o assunto, pretendo somente dar uma idéia da motivação e discutir alguns pontos sobre o paradigma. Além disso, eu vou usar na maioria a terminologia em inglês, pois eu acho estranho traduzir termos tecnológicos. Se alguem tiver interessado em termos em português, o pessoal do workshop em AOP (WASP’04) fez um catálogo de termos.

Motivação e Exemplo

No meu ponto de vista, AOSD não é algo que veio revolucionar o desenvolvimento de software, mas sim um avanço incremental do paradigma de orientação a objetos (OO). Todo bom programador sabe que se deve tentar distribuir as responsabilidades (concerns) do programa em módulos, de forma que cada módulo seja fácil de implementar, entender e reusar. Em C, por exemplo, funções podem ser consideradas módulos. Pra qualquer programa não trivial, você não vai criar somente uma função main(), vai separar a funcionalidade em muitas funções que se chamam pra realizar o objetivo do software. Já OO prega a modularização do software em uma hierarquia de classes e conta com polimorfismo, herança, etc. A motivação de AOSD é que existem algum concerns que entrecortam a hierarquia, ou seja, que mesmo criando essa hierarquia de classes, você não tem como separar dois concerns que deveriam ser separados (para serem melhor implementados, entendidos e reusados).

Pra não ficar somente no abstrato, vamos à um exemplo bem simples, que é utilizado constantemente pra apresentar AOP. Imagine que você tem uma classe que faz o controle do acesso ao banco de dados. O código abaixo é um esboço de como uma classe dessas seria implementada em Java. Você tem um gerente de transações e, em todos os métodos de acesso ao banco de dados, você chama o gerente pra iniciar uma transação e fazer commit se tudo deu certo, ou rollback se deu algum problema. Note que hoje em dia ninguém faria um código assim, já que existem soluções melhores do que ficar escrevendo SQL no seu código (como Hibernate), mas é bem ilustrativo do problema.


public class DB {
	TransactionManager manager = ...;

	public void storeUser(User u) {
		manager.start();
		try {
			// write some sql code storing u into the DB
			manager.commit();
		} catch (DBException e) {
			manager.rollback();
		}
	}
	public void storeAccount(Account a) {
		manager.start();
		try {
			// write some sql code storing a into the DB
			manager.commit();
		} catch (DBException e) {
			manager.rollback();
		}
	}
	...
}

Claramente dá pra perceber que eu tô misturando dois concerns na mesma classe. Um é persistência (salvar o User e a Account no banco de dados) e outro é controle de transações. Em OO, não tem um jeito elegante de separar esses concerns. Você pode até tentar fazer uma interface com uma callback pra tentar minimizar a repetição de código, como no código abaixo, mas não fica ideal.


public interface TransactionalTask {
	public void execute();
}
public class TransactionManager {
	TransactionManager manager = ...;

	public void executeInTransaction(TransactionalTask task) {
		manager.start();
		try {
			task.execute();
			manager.commit();
		} catch (DBException e) {
			manager.rollback();
		}
	}
	...
}
public class DB {
	public void storeUser(User u) {
		manager.executeInTransaction(new TransactionalTask() {
			public void execute() {
				// write some sql code storing u into the DB
			}
		});
	}
	...
}

A idéia de AOSD é criar um novo módulo (chamado aspecto) em que você possa encapsular esses concerns que não tem como você modularizar com classes. AspectJ é a implementação mais conhecida de AOP, tanto por ser a primeira, quanto por ser bem robusta e contar com apoio de diversas empresas. Em AspectJ, que é uma extensão de Java (todo código Java é código AspectJ válido), nós criaríamos um aspecto pra encapsular controle de transações. O pseudo código abaixo mostra a idéia (eu não testei o código, então não garanto copy-and-paste funcionando).


public aspect TransactionManagerAspect {
	TransactionManager manager = ...;

	around(Object o) : execution(public void DB.*(..)) && args(o) {
		manager.start();
		try {
			proceed(o);
			manager.commit();
		} catch (DBException e) {
			manager.rollback();
		}
	}
}

public class DB {

	public void storeUser(User u) {
		// write some sql code storing u into the DB
	}
	public void storeAccount(Account a) {
		// write some sql code storing a into the DB
	}
	...
}

A classe DB agora contém somente código relativo à persistência e o aspecto é responsável pelo controle de transações. Em terminologia de AOSD, around é um tipo de advice e execution um tipo de pointcut. O que esse código tá dizendo é que sempre que a execução do programa for iniciar um método publico, que retorna void, na classe DB, o método deve ser substituído (por isso “around”) por esse advice aqui. O código do advice vai fazer o controle da transação e vai chamar proceed pra executar o código original. Note que o código do advice é muito parecido com a nossa solução usando callbacks. A grande novidade aqui é que usando pointcuts a gente consegue especificar quando que a “callback” deve ser usada, deixando o código da classe DB bem mais limpo.

Esse exemplo mostra a parte dinâmica da história, isto é, como usar aspectos pra “interceptar” alguns pontos da execução de um programa e inserir (ou remover) funcionalidade (código) nesses pontos. Mas AOSD também trata da parte estática ou “estrutural” da coisa. Por exemplo, imagine que no nosso exemplo nós quiséssemos inserir um controle de concorrência bem primitivo, pra garantir que ninguém modificou o User no tempo entre eu buscar no banco e salvar. Pra isso, eu poderia adicionar um campo na classe User com um contador que é incrementado sempre que ele for salvo no banco. Desta forma, na hora de salvar, eu confiro se o valor do contador no objeto que recebi é o mesmo do banco de dados. Se não for, significa que alguém alterou o objeto e eu recebi um objeto inconsistente. Novamente, o problema é que esse campo não faz parte do concern persistência ou modelo de dados. Portanto, não faria sentido eu declarar o contador na classe User. Pra resolver esse problema, AspectJ usa intertype declarations, que permitem a declaracão de campos e métodos em outras classes. Por exemplo, o código abaixo declara e inicializa um campo counter na classe User, removendo dela o concern tratamento de concorrência.


public aspect ConcurrencyManagerAspect {
	long User.counter = 0;
	...
}

Conceitos

Quando eu estava descrevendo o exemplo eu me referi à alguns conceitos de AOSD. Mas acho importante deixar um pouco mais explícito, então seguem algumas definições.

Existem alguns eventos que acontecem durante a execução de um programa que são interessantes de serem interceptados. Esses pontos são chamados join points. Nós vimos que a execução de um método é um ponto interessante quando o objetivo é substituir o método ou introduzir funcionalidade antes ou depois do método. Outros join points, por exemplo, são a chamada de um método (não confundir com a execução), a leitura ou escrita de um campo, ou a inicialização estática de uma classe. Mas esses join points são eventos concretos que acontecem em tempo de execução. Pointcuts são um jeito de especificar de forma abstrata (por exemplo, com regular expressions) quais join points você quer interceptar. AspectJ oferece pointcuts primitivos pros join points mais importantes (como execution, call, get, etc) e outros pointcuts usados pra identificar os objetos envolvidos nos eventos e ligá-los a variáveis. No nosso exemplo, args foi usado pra pegar uma referência ao objeto passado como parâmetro ao método. Outros pointcuts importantes são target (e.g., o objeto que é o destino de uma chamada de método) e this (e.g., o objeto que faz a chamada).

Quando um join point acontece em runtime e ele faz match com um pointcut, então se executa o advice relativo ao pointcut (se tiver algum). Nós vimos como um advice do tipo around funciona. AspectJ também tem advices before e after (que pode ser after throwing ou after returning), que servem pra introduzir código antes ou depois do join point. Intertype declarations também são disponibilizadas por AspectJ pra introduzir novos campos métodos em outras classes, como vimos no exemplo.

Um aspecto é então um módulo usado pra encapsular todas essas construções, do mesmo jeito que uma classe encapsula métodos e campos. O objetivo principal de um aspecto é de modularizar um interesse (concern) que não faz parte da decomposição normal da hierarquia de classes. Esses concerns são chamados de crosscutting concerns, porque eles entrecortam a hierarquia. A implementação de um concern é dita espalhada (scattered) quando ela não está localizada, e entrelaçada (tangled) quando ela está misturada com outros concerns.

Pra quem tiver interesse, o AspectJ Programming Guide é um excelente tutorial com bons exemplos e referências pros diversos tipos de pointcuts, além de explicar alguns problemas que você pode encontrar quando não tiver muita experiência com aspectos.

Discussão

No texto acima eu tratei AOSD e AOP quase como sinônimos, mas eu quero enfatizar que são distintos. Orientação a aspectos surgiu como AOP, pois trazia soluções pra problemas diretamente ligados ao código, como no exemplo sobre controle de transações. Contudo, percebeu-se que seria interessante elevar o nível de abstração e que crosscutting concerns podiam também ser encontrados em design, arquitetura, análise de requisitos, etc. Então AOSD trata não só da programação, mas também de todo o conjunto de metodologias, processos, etc, ligados ao desenvolvimento de software usando a idéia de que crosscutting concerns devem ser tratados como “first class citizens”.

Na minha experiência, AOP como encontrada em AspectJ é utilizada quase que exclusivamente em círculos acadêmicos. Existem algumas empresas que adotam AspectJ para alguns projetos, mas a linguagem está longe de ser adotada em larga escala. Porém, alguns conceitos de AOP são muito usados em alguns frameworks e application servers como Spring e JBoss. Spring, por exemplo, tem o conceito de interceptors, que nada mais são do que pointcuts e advice, mas menos poderosos (não permitem interceptar join points de pouca granularidade, como getters, se não me engano).

Eu acredito que existem atualmente dois grandes impedimentos pra se usar AOP em larga escala. Primeiro é a tecnologia do compilador. Hoje em dia ninguém aceita trabalhar com um compilador que não seja incremental. Quando você usa Eclipse e faz uma alteração no código, o JDT só compila o necessário. O similar para AspectJ, AJDT, tenta fazer o mesmo. Porém, a tarefa é muito mais difícil, pois uma pequena mudança tem que ser verificada perante todos os pointcuts do seu sistema, pois de repente o que você mudou pode agora ser interceptado pelo pointcut. Assim, apesar de ter uma performance relativamente boa, trabalhar com AspectJ usando AJDT não é tao agradável quanto trabalhar com Java usando JDT.

Segundo, AOSD não vai acabar com todos os seus problemas. É difícil pros programadores entenderem os conceitos e leva tempo pra comunidade desenvolver design patterns e entender o que tirar de melhor do paradigma. Pointcuts são atualmente regular expressions, então eles são frágeis e qualquer mudança de nome de um método pode fazer um pointcut não mais interceptar aquele método, e você não tem como perceber que isso aconteceu. Suporte de boas ferramentas é então essencial. Além disso, eu tenho dúvidas de que aspectos sejam bons pra modularizar concerns heterogêneos como “logging”, que foi sempre um dos principais exemplos. O problema é que cada instância de logging é muito específica pro contexto, então não faz sentido você remover todas as chamadas de log e encapsular em um advice, pois o advice teria que ser diferente pra cada ponto que ele interceptasse. Controle de transações é homogêneo, pois o advice sempre faz a mesma coisa, então é um exemplo mais apropriado. Existem estudos que apontam que Mixin Layers são melhores pra concerns heterogêneos como logging, mas isso seria assunto para um outro post.

==========================
Nota no dia 5/11

Conversando com o Miguel eu acabei percebendo algo que talvez não tenha ficado muito claro. AspectJ é uma extensão de Java e precisa de um compilador especial que compila as classes como se fossem Java e depois analisa os aspectos do sistema e faz diretamente as modificações no código (ou introduz testes de tempo de execução quando não tem como verificar estaticamente o resultado). Esse último passo, “introduzir os aspectos”, é chamado weaving.

Existem duas alternativas principais de compiladores pra AspectJ. O ajc é parte do AJDT, que é uma extensão do JDT do Eclipse. Como o JDT, o AJDT contém editor, compilador, debugger, e tudo o mais, implementados em plugins pro Eclipse. O principal objetivo do projeto é que a compilação seja rápida pra que você tenha a mesma experiencia que programando em Java, ou seja, ele tenta ser incremental e o código do compilador em si é otimizado (leia-se, não-facilmente extensível).

A outra alternativa é o abc (Aspect Bench Compiler), que é um compilador acadêmico cujo objetivo principal é ser extensível pra que se possa fazer pesquisa com linguagens de programação, otimização de código, análise estática, etc. Dessa forma, compilar um sistema grande com abc, principalmente usando as otimizações disponíveis, é bem demorado. O ideal é programar usando o AJDT e usar o abc pra gerar o bytecode de produção, já que ele é bem mais otimizado que o gerado pelo ajc.

Além disso, AspectJ não é a única linguagem orientada à aspectos derivada de Java. No site da aosd.net, por exemplo, tem uma lista com alguns sistemas (derivados ou não de Java) e algumas ferramentas orientadas a aspectos.

Qual a fonte?

Essa dica é para amantes de design em geral, e fontes e tipografia em particular. Descobri hoje, lendo a revista Mac+, o site What the Font que oferece uma ferramenta que tenta descobrir a fonte utilizada para escrever texto em um arquivo de imagem.

O processo é simples: faça upload ou passe a URL da imagem que deseja analisar, verifique se os caracteres que ele detectou estão corretos e pronto. O resultado é exibido na forma de uma lista de textos em diversas fontes, e o sistema permite a comparação das fontes obtidas com a sua fonte original mostrando a sua imagem sempre no centro da tela.

Utilizei a ferramenta para tentar descobrir as fontes utilizadas pelo Raphael para fazer o logo do job4dev (ele perdeu o arquivo PSD original…), e o resultado obtido está abaixo:

whatthefont.png

A fonte ATCapone-Light parece a correta!

Frase do Dia

“Customers don’t know what they want, much less what they need, until they see it.”

O que tem de tão legal em usar um DVCS?

Contrariamente aos desejos do nosso editor-chefe, este blog ainda não é o seu ponto único de informação sobre tecnologia. Se fosse, você estaria perdendo muita informação interessante que foi produzida em outros lugares. Por exemplo: muitas pessoas estão passando a adotar software para gerenciamento distribuído de código e controle de versão. Tendo em vista que nosso editor-chefe é um usuário de CVS e SVN, não faz muito sentido para ele acompanhar as experiências das pessoas que estão adotando sistemas que se fundamentam em outra arquitetura básica, logo ele terá pouca oportunidade para escrever a respeito.

Esse não é um texto para falar sobre as vantagens técnicas de usar sistemas distribuídos de versão (Distributed Version Control System - DVCS) como o Git, Darcs ou Mercurial. Já existe muito material que você pode encontrar por aí, como por exemplo uma apresentação em vídeo do próprio Linus Torvalds sobre o Git e suas vantagens. O que eu quero é justamente comentar sobre os princípios que levaram Torvalds a desenvolver um sistema completamente novo. De acordo com Linus, sistemas distribuídos não são melhores por questões tecnológicas ou de engenharia avançada, mas são melhores por princípios da arquitetura: “Com sistemas centralizados”, diz ele, “o desenvolvedor tem que lidar com questões que podem se tornar problemas políticos - saber quem pode ter acesso ao sistema; quem pode ter acesso de escrita; quem vai ser o responsável por determinados subsistemas, etc. Em sistemas distribuídos, isso não acontece. Cada desenvolvedor é dono do seu próprio repositório e decide livremente de quem ele irá puxar suas alterações. Não existe um repositório canônico, oficial. O meu repositório de código é tão bom quanto o dos desenvolvedores que estão trabalhando em repositórios de quem eu colaboro.”

Uma outra questão - fundamentalmente importante - é a questão da confiança. Diz Torvalds: “Eu não preciso mais ficar verificando a qualidade de cada patch que entra na minha árvore de código. Eu posso puxar qualquer coisa que venha da árvore de Andrew Morton (desenvolvedor principal da versão 2.6 do kernel do Linux) sem medo de causar prejuízo em meu código, pois eu confio em Andrew.”

Esse é um argumento estranho, mas muito poderoso: nós podemos confiar em uma, duas, dez pessoas. Mas não podemos confiar em centenas ou milhares de pessoas. Confiança não é escalável. Podemos até confiar em alguém desconhecido indiretamente (o amigo do meu amigo…) mas esse critério não resiste por muitas iterações. É esse o ponto que torna sistemas que se baseiam em arquiteturas distribuídas melhores.

Não importa o quão superior ou madura seja a implementação de um sistema centralizado, ele jamais terá “trabalhe apenas com as pessoas em que você confia” como uma feature. É impossível obter isso em um sistema centralizado, por design. A killer feature de um DVCS é a possibilidade de gerenciar seus projetos usando o seu grau de confiança nas pessoas.

ClockingIT

Existe uma ferramenta muito legal para controle de projetos, bugs, releases e afins disponível na web: ClockingIT.

Este projeto tem uma história bem peculiar: foi desenvolvido por um casal norueguês, Erlend e Ellen Simonsen. Erlend é desenvolvedor e é responsável por toda a parte de programação. Ellen é designer e cuida de toda a parte visual.

O ClockingIT segue a mesma receita de muitos projetos de alta qualidade e valor agregado disponíveis por aí: nasceu de uma necessidade do próprio desenvolvedor. Erlend é um consultor de tecnologia independente e desenvolve projetos sob medida para vários clientes, e sentia a necessidade de ter uma boa ferramenta de gerenciamento de projetos. Seguindo a filosofia do Getting Real, resolveu por a mão na massa e começou a desenvolver o ClockingIT usando a plataforma Ruby On Rails.

O sistema permite o cadastro de diversos projetos e colaboradores. Em cada projeto, é possível criar milestones e tarefas (com diversos graus de prioridade, nível de dificuldade, tempo estimado de execução e data de entrega) e designar um colaborador para sua execução. Além disso, o sistema permite a criação de subtarefas e permite registrar o tempo levado para executar cada tarefa, gerando um log de trabalho. Com estes dados, é possível criar relatórios diversos, como timesheets que são extremamente úteis para consultores que ganham por hora. E o sistema ainda oferece vários modos de visualização de todos estes dados: timeline, schedule, lista de tarefas…

Mas o grande diferencial, aquilo que me faz ter vontade de escrever sobre o ClockingIT neste blog, é a qualidade da interface. O design gráfico é simples, limpo e extremamente intuitivo. E o site faz um uso intensivo e inteligente de scripts e recursos assíncronos. Eu destaquei a palavra inteligente porque hoje em dia vemos muitos sites usando Ajax simplesmente por usar, apenas para baterem no peito e gritar “Eu sou uebi doispontuzeru!!!”. Olhando a interface do Clocking IT, talvez muitos resolvem repensas suas visões. A interação como o site é extremamente ágil e leve, exatamente como em software desktop. Qualquer ação efetuada por algum usuário é imediatamente refletida na tela de outros usuários conectados no mesmo projeto. É possível saber em tempo real quem está conectado no sistema, o que está fazendo, a quanto tempo está fazendo. E graças ao chat embutido, é possível até conversar com outros colaboradores.

Last, but not least, o sistema oferece integração com iCal (pode ser integrado com Google Calendar ou com o calendário da Apple por exemplo), sistema de RSS, um wiki, fórum , e uma speedbar (uma janelinha pequena) que permite que o usuário marque o início e fim de uma tarefa (com botões de start, stop e pause e um cronômetro rodando em tempo real).

É, definitivamente o ClockingIT não deixa nada a desejar de ferramentas tradicionais de gerenciamento de projetos. E com certeza ele é uebidoispontuzero.

Screenshots de IE

Quem desenvolve sites e aplicações web sabe: a coisa mais pentelha que existe é conseguir fazer com que as telas tenham exatamente a mesma aparência em qualquer browser (não, eu não faço parte daqueles que acham que um site deva ser desenvolvido para funcionar bem apenas no navegador que domina o mercado e o resto que se dane, a menos que seja para uma intranet homogênea..call center por exemplo). E para resolver isso, não tem muito segredo: é preciso testar, testar e testar.

Hoje em dia existem vários sites que geram screenshots de um site gerados a partir de vários navegadores e são uma mão na roda. No meu caso, que uso Mac para desenvolvimento de projetos pessoais (como o Job4Dev), eu sinto falta de ver o resultado gerado pelo IE. Por isso, o site http://ipinfo.info/netrenderer/index.php é uma ótima pedida: gera screenshots gerados por várias versões do IE e ainda por cima é extremamente rápido.

Design e simplicidade

Venho por meio desta apresentar apenas o link de um post que eu encontrei no reddit e que sintetiza perfeitamente a questão do design de interfaces, e do design de soluções em geral:

http://stuffthathappens.com/blog/2008/03/05/simplicity/ 

Aliás, o post acima descreve em 3 imagens o que eu me matei para tentar explicar de forma bem meia boca no post Design de Interfaces.

Ainda sobre o MacBook Air

Antes de mais nada tenho que dizer que não acompanho os lançamentos da Apple com muita atenção. Nada contra a Apple em si, mas acabo acompanhando outras coisas que me interssam mais. Mas parece que o maior lançamento deles feito na maior conferência sobre produtos da Apple este ano foi o MacBook Air.

Por fora, como a maior parte das coisas da Apple, o design é muito interessante. Mas confesso que não dou tanta bola pra assim para o design. É claro que gosto de ter coisas bonitas, mas prefiro ter coisas boas antes de ter coisas bonitas. E foi por isso que minha primeira impressão do MacBook Air não foi das melhores. O fato de ele não ter CD/DVD interno me deixou atônito.

Mas ai, pensando um pouco mais, quantas vezes eu uso meu drive de CD/DVD? Poucas… Então porque eu tenho um? Bom, ele de vez em quando é útil, eu diria. E já me salvou algumas vezes.

Mas pensando mais ainda, há muitos anos atrás a Apple foi a primeira fabricante que eu tenho notícia que parou de lançar computadores com drives de disquetes. E, como sabemos hoje, este foi um caminho certo. Eu não tenho drive de disquete há 4 anos. E acho que posso contar nos dedos de uma mão quantas vezes ele me fez falta. E nenhuma dessas vezes eu não consegui outra solução sem usar um disquete.

Seguindo o mesmo raciocínio, talvez as unidades de CD/DVD também estejam com os dias contados. Pelo menos em computadores portatéis.

Tag cloud no Job4Dev

Atendendo ao clamor popular, coloquei no ar ontem um sistema de tag cloud no Job4Dev.

A primeira versão está bem simples: lista de tags ordenada por nome, com o número de anúncios em que a tag aparece do lado. A próxima versão, que deve sair em breve, será del.icio.us like, diferenciando as mais populares das menos populares pelo tamanho da fonte.

De grão em grão…

Especial de Natal Log4Dev: construindo um site de notícias usando Python - Parte 2

Vamos dar uma olhada nos nossos requisitos, e apresentar algumas questões de tecnologia:

  • O site tem que ser capaz de autenticar e identificar unicamente cada usuário que deseja cadastrar links.
  • Deve ser capaz de manter uma lista de quem foi o primeiro a enviar um link, além da data que o link foi enviado.
  • Deve ter um sistema que permita ao usuário indicar se gostou (aprovou) ou não gostou (rejeitou) um link enviado por qualquer pessoa que utilize o serviço.
  • Deve permitir que cada link enviado possua um fórum de discussão.
  • Deve permitir que uma pessoa possa iniciar um tópico de discussão, sem enviar um link. No caso, vamos fazer o seguinte: se o usuário preencher apenas os campos de título e comentário em um formulário de link, mas deixar o campo para a URL em branco, vamos criar um link para um item dentro do próprio site.
  • Deve permitir ao usuário enviar um lote de links a partir de uma fonte que ele já conheça. Isso vai servir para que o sistema, no futuro, tenha uma grande base de links prévios para aprender rapidamente.
  • Deve permitir que o usuário faça o seu voto (aprovado/rejeitado) sem sair da página que está. Para isso, vamos usar uma pitada de AJAX.

Tendo os requisitos delineados, podemos ver que vamos precisar dos sistemas comumente usados em aplicativos web: um banco de dados, um servidor web, um sistema para geração de páginas dinamicamente. Além disso, teremos que usar alguma biblioteca para importar links e parsear RSS.

A parte de programação já foi definida no título: vamos usar Python. É o que estou usando ultimamente para meus outros projetos, é uma linguagem elegante, divertida (sim, diversão conta), dinâmica, com bibliotecas fartas e bem documentadas como parte da biblioteca-padrão. Se nada disso serviu como argumento, diga para o seu chefe que você vai aprender Python pois ficou sabendo que o pessoal do Google usa, e tudo que eles usam tem que ser bom, não é mesmo?

Para o servidor de banco de dados: PostgreSQL. Maduro, estável, bastante documentação. Outros bancos de dados serviriam, mas escolhi PostgreSQL por pura comodidade. Se você quiser portar os scripts SQL que eu colocar aqui para seu banco de preferência, creio que não terá dificuldades.

Para a parte de AJAX, vamos favorecer a prata da casa: Juice Lib é uma biblioteca pequena, mas com funcionalidades bem pensadas para a parte de comunicação assíncrona com o servidor. Eu tenho enchido um pouco o saco do Miguel na questão de manipulação de DOM (a juice faz isso através de extensão de métodos sobre string, o que pode vir a te causar dor de cabeça se o seu código Javascript começar a crescer muito), mas o resultado geral é poderoso o suficiente para que possamos ter o esquema de apresentação da votação em pouquíssimas linhas de Javascript.

Resta falar sobre qual sistema vamos usar para formarmos uma “Aplicação Web” propriamente dita. Controle de sessão, classes controllers, formas para acessar o banco de dados, apresentação de páginas construídas dinamicamente, etc, etc, etc.

Eu já disse que odeio frameworks. O que eu quero é algo que pudesse funcionar como um único módulo ou biblioteca, que pudesse ser importado a partir de um shell Python e me oferecer as funcionalidades necessárias para um webapp.

O que vamos usar, então, é um sistema que seja o anti-framework: esse sistema, para mim, é o web.py

O que diferencia o web.py dos outros frameworks para aplicações web desenvolvidas em Python?

Simples: a filosofia.

Muita atividade ocorreu na comunidade de desenvolvedores Python, buscando uma resposta para o sucesso do Ruby On Rails. Começaram então a pensar em implementar um framework que pudesse ser tão “pragmático” e “rápido” quanto o Ruby On Rails.

E isso levou a uma febre de grupos desenvolvendo frameworks para Python. Sistemas que fazem mapeamento OR. Que abstraem sua camada de dados completamente. Que abstraem a camada de apresentação completamente. Que abstraem a camada de controle completamente. Que escrevem elogios na tela enquanto eles fazem tudo automaticamente para você.

O problema: abstrações excessivas falham. Cada um dos grupos dos grandes frameworks (Turbogears, Pylons, Django) tinha o seu próprio dialeto para o desenvolvimento de aplicações web, alguma coisa parecida com Python, mas não exatamente Python.

Faltava uma solução que se propusesse a alavancar os conhecimentos tradicionais que as pessoas acumulam ao trabalhar com sistemas web.

O web.py tem essa filosofia. Por exemplo: ao invés de se preocupar em implementar um módulo que faça mapeamento OR para você, o web.py te dá um módulo que serve para facilitar o acesso ao banco de dados, diretamente e de forma segura. Ao invés de expor objetos em Python para uma camada de apresentação, o web.py facilita o trabalho de construir uma resposta HTTP. Ao invés de impor uma disciplina de trabalho, ele oferece as funcionalidades básicas para que você use seu conhecimento acumulado com outros problemas que você teve que resolver.

(Justiça seja feita: o Django parece ter aprendido parte dessa lição. Muito dos esforços recentes do Django para que ele chegue na versão 1.0 está sendo feito no sentido de retirar o que é chamado de “código mágico”.)

Isso não quer dizer que o web.py é perfeito. Não é. A última versão lançada possui algumas coisas no design que você pode até estranhar, e vou falar deles. Espero para ver se a próxima versão irá corrigir mesmo esses problemas. De qualquer forma, por se tratar de uma biblioteca de recursos auxiliares - ao invés de um framework - a ginástica necessária para contornar esses problemas é muito menor.

Chega de escrivinhar. Amanhã, vamos ao código.

Sobre Frameworks…

Eu odeio frameworks. Não um ódio assim que faz pensar em mandar emails ameaçadores ao criador do ASP.NET, nem um ódio que me faça pensar colocar um vírus no computador de algum líder do projeto Jakarta que só permita que ele edite seu código usando Notepad (ou edlin) para o resto da vida. É um ódio de quem tem a sensação de que algo está fundamentalmente errado na forma como os desenvolvedores produzem e consomem frameworks de software.

Quando eu digo isso, a reação tradicional é: “Lullis, você quer o quê? Que todo mundo reinvente a roda? O que você sugere?”

Só posso responder com uma outra pergunta: você conhece o Método Socrático? Maiêutica?

Se você sabe, ótimo. Como eu não tenho como conferir sua resposta, vou tentar dar a minha explicação: o método socrático é um modo de tentar produzir novas idéias (complexas) a partir de um jogo de perguntas e respostas para conceitos mais simples que pertencem ao mesmo contexto.

Por exemplo, suponha que você esteja querendo ensinar cálculo de potências para uma criança. Como um matemático “formal” tentaria transmitir esse conhecimento? Apresentando uma série de colorários, princípios gerais e tentando mostrar todas as definições para a criança, até que ela consiga repetir todos os métodos utilizados pelo seu professor na obtenção de respostas para os problemas pré-estabelecidos.

Um professor que estivesse usando o método socrático certamente começaria fazendo perguntas para as quais os alunos já soubessem. “Usando notação matemática, como vocês fariam para escrever ‘quatro vezes quatro vezes quatro’”? “E se eu quisesse repetir a multiplicação 10 vezes?”. “E se eu quisesse multiplicar infinitamente?”. “E se eu quiser dividir repetidas vezes, ao invés de multiplicar?”. “Quanto é 1 multiplicado por 1?” “Quanto é 1 multiplicado por 1 multiplicado por 1… 100 vezes? E 1000 vezes? E 10?”. Ao deixar as crianças responder essas perguntas, elas mesmas passam a observar os princípios gerais por trás das fórmulas
matemáticas. Através da intuição, elas desenvolvem quase que por conta própria uma nova “unidade de conhecimento”, ao invés de tê-la transmitida através de um mestre. Um professor socrático atua muito mais como um guia, do que como uma bússola.

Qual sistema é melhor? Muito depende do seu objetivo. Alunos das duas escolas conseguirão responder que A^(-x) é igual (1/A^x). Um o fará quase que por instinto, condicionamento mental. O outro pode até não ter isso cravado em sua cabeça, mas chegará à resposta se tiver desenvolvido a habilidade de saber fazer as perguntas certas. “Se ao incrementar o expoente eu multiplico a base, o que aconteceria se eu diminuísse?”

Computadores são inúteis. Eles só sabem dar respostas.

No espiríto do Método Socrático, eu pergunto: o que acontece numa situação em que as perguntas não possuem uma resposta catalogada?

Provavelmente, o aluno de métodos mais tradicionais (digamos, alguém que passou tempo demais estudando Kumon) vai travar, ou voltar para o seu mestre, na esperança de obter as respostas que faltam. Ainda que ele seja capaz de responder por reflexo a equações derivadas de segundo grau, ele não saberá por onde começar caso tenha que jogar Petals around the Rose.

Certo. E o que isso tem a ver com frameworks?

Escreva “define: framework” no Google. Um dos termos que você encontrará é “sistema de regras, idéias ou princípios que é usado para planejar ou decidir algo.”

Olha só que interessante: ao tentar explicar para você sobre o Método Socrático, eu acabei achando uma das melhores formas de explicar o meu desgosto por frameworks de desenvolvimento.

Frameworks, em sua essência, acabam sendo um “pacote fechado” de soluções prontas para alguém que tem um problema a ser resolvido. “Se você está desenvolvendo um aplicativo e precisa de uma integração Web, use o framework XYZ que te dá autenticação de usuários, geração de código HTML a partir dos seus dados, servidor HTTPS e no fim do dia ainda te faz uma massagem nas costas”. “Se você quer desenvolver software para sistemas embarcados, use o nosso DevKit e você terá um emulador em seu computador, configuração de diversos setups em software, cross-compiler e no fim do dia ainda te daz uma massagem nas costas.”

Se ao menos as promessas de massagem fossem verdade…

O problema, ao meu ver, é que alguém (indivíduo ou grupo associado) que decide implementar um framework se coloca na posição de detentor de um pilha de conhecimento como se fosse “a única verdadeira solução”, quando na verdade esse alguém possui apenas uma compilação de regras e receitas usadas na resolução dos problemas dele. Ou, pior, é uma empresa que está tentando criar a solução definitiva. E, devemos saber, isso
não existe
.

Outra coisa a se pensar - ao menos para os desenvolvedores web - é que a velocidade do surgimento de tecnologias é muito rápida. Mais rápida até do que a capacidade do grupo de assimilar e sedimentar qualquer forma de conhecimento que possa se transformar em um “pacote fechado.” Aí, logo depois que qualquer sistema começa a se consolidar, já haverá parte do grupo tentando forçar a adoção das novas tecnologias e paradigmas, levando ou a um sistema que é abandonado e preterido em favor da Próxima Grande Tecnologia, ou haverá um produto torto, sem identidade. Jack of all trades, Master of none.

E os desenvolvedores que são usuários desses frameworks, meu Deus? Passam tanto tempo aprendendo a lidar com os problemas, aprendem todas as formas de contornar as falhas de design, decoram tantos lotes de informação que, no fundo, acabam tendo que reaprender sistemas inteiros. Tornar-se verdadeiramente produtivo com o tal framework é quase tão trabalhoso quanto implementar você mesmo as funcionalidades prometidas. Que vantagem há nesse processo?

Qual a alternativa?

Seguindo a analogia, o nosso Software Socrático não é desenvolvido em cima de uma plataforma ou de um framework, mas utilizando pequenos componentes mais simples e que já são conhecidos suficientemente. Esses elementos menores seriam as unidades de conhecimento necessárias para que, através da intuição, possamos chegar a uma solução que produza o resultado esperado.

Um guia, não uma bússola.

Getting Real: desenvolvendo o Job4Dev

True artists ship“, artistas de verdade produzem.

Esta frase, atribuida ao Steve Jobs, me foi dita pelo Raphael. Confesso que ela mexeu comigo. Sempre admirei pessoas que desenvolvem seus projetos computacionais, e fazem deles coisas interessantes. Eu estou numa fase de tentar transformar os meus projetos em coisas reais. Se eles estão se tornando coisas interessantes, é outro papo. O primeiro foi este blog, que com muita perserverança está se transformando em um repositório de textos bem interessantes. Depois, coloquei no ar a JuiceLib, que está num processo bem lento de desenvolvimento. Falta tempo e ajuda. E eu trabalho por lotes….

Mas daí, veio a idéia do job board. O interessante neste caso é que este lance do jobboard, antes de ser um projeto de desenvolvimento, era algo que me martelava a cabeça. Me frustrava não encontrar no Brasil um jobboard que me desse prazer de visitar. E depois de um tempo de maturação, cheguei à conclusão de que se ele não existisse, eu teria que criar um. Lembrei de um cara chamado Richard Stallman que não encontrou nenhum editor de textos com os recursos que ele procurava, e daí ele escreveu o Emacs. Citando uma outra referência mais moderna, o livro Getting Real do pessoal da 37 Signals:

A great way to build software is to start out by solving your own problems. You’ll be the target audience and you’ll know what’s important and what’s not. That gives you a great head start on delivering a breakout product.

Muito bem. Eu tinha um problema a resolver. Resolvi atacá-lo de frente. E de quebra, poderia me aprofundar mais em Python. Restava definir o resto do meu ambiente. O editor seria o Emacs, por ser extremamente versátil, ter uma quantidade incrível de ferramentas úteis e poderosas, e ser bem leve. O banco de dados escolhido foi PostgreSQL, por ser um banco free, de ótima qualidade, com portes para Linux, Windows e Mac (ambiente primário de desenvolvimento) e pelo fato de eu ter trabalhado com ele por muito tempo.

O mais difícil foi definir um framework/lib de desenvolvimento web. Comecei avaliando o Turbogears. No início achei interessante, mas por vários motivos não gostei de como ele evoluiu. O Raphael tentou me convencer a me usar o web.py, uma lib bem leve de desenvolvimento web, que eu acabei não escolhendo por achar a doc bem fraquinha. Daí eu descobri o Django, que possuia uma documentação bem completa, um conceito bem legal de oferecer muitos recursos para minimizar a parte CRUD do sistema e um ótimo case de implementação: o site washingtonpost.com.

O desenvolvimento se deu em 3 grandes blocos de trabalho.

O primeiro foi a parte de design de base de dados e entidades, além de primeiros contatos com o ambiente de desenvolvimento. Demorou 3 dias mais ou menos. Boa parte da demora foi pelo fato de eu estar descobrindo o Django ao mesmo tempo que fazia o design da solução. Neste ponto, eu sabia muito bem o que eu queria obter, e sobretudo sabia o que eu NÃO queria! Citando mais uma vez o Getting Real:

Sometimes the best way to know what your app should be is to know what it shouldn’t be. Figure out your app’s enemy and you’ll shine a light on where you need to go.

O segundo bloco de trabalho foi a integração com o design gráfico. E nesta fase aconteceu uma coisa interessante. O Raphael fez um design que se encaixou perfeitamente naquilo que eu tinha em mente. E ao mesmo tempo ele tinha feito uma versão funcional do board em web.py. Rolou então uma competição saudável: roubei o design dele, e durante alguns dias desenvolvemos o mesmo sistema em ambientes diferentes e em paralelo. O que um fazia, o outro corria atrás para fazer melhor. Um impulsionou o outro. Nesta fase, foram feitas as telas principais, o sistema de submissão, e o primeiro RSS. Foram dois ou três dias de trabalho bem intenso, e confesso que fazia muito tempo que não me divertia tanto escrevendo um software. O meu deadline era segunda feira dia 26 de novembro. Neste dia tínhamos um demo rodando.

Foi aí que veio o terceiro bloco de trabalho. Chamamos amigos e conhecidos para serem beta testers. A meta: colocar o site no ar, para o público, com domínio próprio e tudo mais no dia 3 de dezembro. Nesta semana, várias pessoas testaram o sistema, acessando a listagem, as páginas de anúncios, submetendo anúncios novos e sobretudo reportando bugs e mais bugs. Este era o objetivo. Nos final de semana anterior à minha data limite de “lançamento”, passei horas e mais horas escrevendo código, debugando, testando.

No dia 3, o Job4Dev estava no ar. O Log4Dev ganhou um irmãozinho, e eu ganhei mais um filho. Como disse anteriormente, fazia muito tempo que não tinha tanto prazer em fazer algo relacionado a software. Não pela complexidade do sistema em si, mas pelo fato de ter uma meta a ser alcançada, e de produzir um sistema pequeno, leve, eficiente e útil. E sobretudo de ter a sensação de ter gerado algo que pode ser útil para resolver um problema real.

Otimização “madura”

Aconselho a leitura do artigo Mature Optimization, escrito por Mick West.

Ele aborda uma questão interessante: otimização no inicio do projeto é sempre ruim?

Citando Donald Knuth:

We should forget about small efficiencies, say about 97% of the time. Premature optimization is the root of all evil – Knuth, Literate Programming, 1992, p28.

O autor tenta mostrar que, as vezes, otimizações no final do projeto podem ser problemáticas:

Towards the end of the project we profile the code, and find that 20% of our CPU time is taken up by a function […] then we fix it. Then we tackle our next function on the profiler’s list; maybe one that takes 10% of the CPU time. We fix that[..] Our game now runs 30% faster[…] However, if after that the code is still too slow, you will now find it is not because of a few weighty functions, but rather a general problem with all of the code. The code is just generally inefficient. By ignoring optimization until the end of the project you have ended up with “sick code” that contains multiple inefficiencies too deeply ingrained within the fabric of the code to be removed in a timely manner.

A idéia do texto é mostrar que existem duas categorias de otimizações a serem consideradas. A primeira, considerada precoce e ruin, é aquela que é feita sem um real entendimento da necessidade dela e sobretudo do efeito final. As vezes, gastamos um grande tempo otimizando uma função cara que, no final das contas, será chamada apenas uma ou duas vezes durante a execução do programa sem afetar na performance geral.

A segunda categoria é chamada pelo autor de otimização madura. Ela cuida de problemas bem conhecidos em certos domínios de software, que são recorrentes e sobretudo previsíveis em vários projetos. Em geral, são otimizações estruturais que envolvem decisões de arquitetura e que dificilmente podem ser corrigidas ao final do projeto. O autor cita vários exemplos aplicados ao desenvolvimento de jogos, onde performance é crítica. Um exemplo bom é a questão de alocação de memória: é muito mais eficiente utilizar um sistema de pool de objetos do que ficar executando alocação repetitiva e constante na pilha.

No domínio de software que eu tenho trabalhado, o grande gargalo pode ser a quantidade de dados gravados. Uma simples listagem pode ser um pesadelo caso não seja feita seguindo certas regras simples: usar paginação na base de dados (e nunca na camada de aplicação), tentar filtrar ao máximo os dados extraídos da tabela (extrair apenas o necessário para exibição, evitandoo aumento desnecessário da quantidade de dados). Pode parecer bobo, mas outro dia me deparei com uma listagem simples que demorava em torno de 15 minutos pra rodar…

O problema acima não se encaixa tão bem no quesito “decisão estrutural”, porque ao final do código é relativamente simples mudar sem grande impacto no sistema. É apenas chato ter que passar por todas as queries, reescrever e retestar tudo. Sem contar que em geral o problema irá aparecer apenas depois do sistema ter sido instalado no cliente, ou estar em produção (afinal, ele está diretamente ligado à quantidade de dados da base). Mas com certeza é o tipo de problemas que pode ser facilmente mapeado no inicio do projeto e que não impacta em nada no desenvolvimento, se bem organizado.

Design de interfaces

Aproveitando o artigo do Raphael sobre o design de um produto ou de uma solução, quero falar aqui sobre o design de um dos aspectos de um produto de software, que é a interface homem máquina.

Se perguntarmos para 100 pessoas qual a principal característica da Apple por exemplo, muito provavelmente 98 dirão que é o design de seus produtos (os 2 outros dirão que é o preço absurdo..mas isto está mudando!). Tudo o que sai da empresa do Tio Jobs prima pela beleza, atenção nos detalhes e simplicidade de uso. Nada mais simples e clean do que um iPod shuffle, com seus 4 controles. Alguém me disse um dia que primeiro eles definem como o produto vai ser, depois eles pensam como fazer para que ele seja daquele jeito. Não duvido disso.

A Google é outra que merece destaque no quesito interfaces. Não pela beleza: as interfaces deles são muitas vezes feias. Mas eles inovaram no quesito simplicidade, usabilidade e interatividade, mostraram ao mundo um novo jeito de interagir com sites na internet. O melhor exemplo disso é a tela inicial do motor de busca, uma tela branca e um campo de texto (na verdade, o motivo inicial desta tela espartana foi a falta de conhecimento de HTML dos fundadores Brin e Page). E nada mais eficiente, rápido e leve do que a interface do GMail, ou do Google Maps. E basta ver a quantidade de ofertas de empregos para engenheiros de interação em Seattle ou New York.

E existem muitas outras empresas que claramente se preocupam com a qualidade da forma como os usuários irão interagir com seus produtos. Flickr, Adobe, 37 signals…

Ok, back to Brazil.

A minha experiência pessoal é de que interface é encarada como um mal necessário na maioria dos projetos. Sobretudo em projetos para empresas. Infelizmente ainda não tive a oportunidade de trabalhar em projetos para o grande público, ou pelo menos em projetos onde quem paga é efetivamente quem usa. Talvez seja diferente. Mas em projetos enterprise, é assim.

Em projetos web, o melhor que podemos ter é uma interface construída em photoshop e um web designer para dar um ar mais profissional para a coisa. Daí o cliente vê a interface (em geral photoshop), e usa todo o seu conhecimento (em geral inexistente) em interação para aprovar. Por fim pegam algum computeiro que esteja sem nada melhor pra fazer e mandam ele implementar a interface.

Eu posso contar nos dedos de uma mão o número de desenvolvedores que eu conheço que gostam de trabalhar com interfaces. Acho que não preciso discutir os problemas de pôr alguém pra fazer algo que não gosta, e que acha que é um mal necessário. Preciso?

Sem contar que a maioria das vezes, as interfaces se resumem a listagens gigantescas e formulários. Nada contra eles, muitas vezes resolvem. A questão é quando tratamos com quantidade gigantescas de dados (o que é bastante comum hoje em dia, tanto em sistemas empresariais quanto em sistemas para o grande público). Grandes chances de que muito rapidamente se perceba que a interface é pouco produtiva, lenta…

Não estou aqui advogando pela otimização precoce de um sistema. Estou advogando pelo estudo cuidadoso de projetos de interface e interação quando a questão da quantidade de dados/eficiência de uso é algo facilmente previsível e sobretudo crítico para o sucesso do projeto. Exemplos de interfaces que requerem um certo estudo? Que tal uma tela que tenha que sintetizar graficamente uma tabela de excel de 500 colunas por 3000 linhas, permitindo que decisões possam ser tomadas a partir de uma análise rápida do conjunto ou então que dados isolados sejam facilmente encontrados e manipulados em um mesmo ambiente? Ou então uma listagem com milhares de nomes acessada centenas de vezes por dia, onde seja imperativo encontrar um nome específico ou conjunto de nomes que atendam certas características de forma rápida?

Um bom projeto de interface requer uma equipe especializada nisso, que saiba lidar com aspectos teóricos (usabilidade, acessibilidade, modelos mentais, metáforas, affordance), com aspectos técnicos (Javascript, HTTP, programação backend eficiente), e com aspectos gráficos e de layout (cores, fontes, posicionamento de elementos). Requer gente que tenha interesse pelo assunto, e que se preocupe com detalhes. Requer estudos, protótipos, testes. Requer coerência com o resto do sistema, e com o tipo de usuário que deverá utilizar o sistema. Requer pensar um pouco out of the box: muitas vezes, as soluções padrão não resolvem o problema adequadamente.

Resumindo: requer dedicação e tempo. Não pensar nisso pode ser o barato que sai caro.

Sugiro, a quem tiver interesse em trabalhar com design de interfaces, dar uma lida no texto do Joel Spolsky sobre tema: User Interface Design for Programmers.

Startup Mantra I: Design é tudo que importa

Já reparou que há algumas coisas no mundo de tecnologia que tiveram sucesso por solucionar um problema e empregavam milhares de pessoas, mas que hoje não são mais realmente problema nem solução? Já reparou também que esses mesmos produtos desenvolvidos por milhares de pessoas, mesmo quando são excelentes obras de engenharia, não caem no gosto do público?

Por exemplo: sistemas operacionais. POSIX ganhou há tempo. O Windows XP é um sistema que está longe de ser perfeito, mas ele se mantém utilizável e estável o suficiente para boa parte das pessoas. Ele resolveu um problema que um sistema operacional deve resolver: permitir que uma pessoa possa rodar seus programas e oferecer suporte básico de operações de computador.

E o Windows Vista? Bem, pode até ser que alguns tarados que tenham olhado as fotos das telas, gritado “Shiny Boxes!” e saído correndo para fazer o upgrade. Com certeza a máquina de marketing de Microsoft vai funcionar a ponto de convencer muitas pessoas que elas têm que ter janelas translúcidas e que elas têm que estar prontas para um mundo de 64 bits. Mas isso é uma grande bobagem. E isso se refletiu nas diversas análises que foram feitas. “Não há nada que justifique o upgrade”. “O maior ponto do Windows que precisa ser corrigido, a segurança, já está abalado pelas novas ameaças.” Não foram poucos os casos que escutei de pessoas que compraram um computador com Vista e voltaram atrás. Certamente a Microsoft vai conseguir com que o Vista se pague em pouco tempo, e seus acionistas vão adorar. Mas com certeza, a dominação que a MS tem não vai ser ampliada em função de seu novo produto.

Outro exemplo? Videogames. Um mercado bilionário, com MS e Sony se debatendo sobre formatos, preços, exclusividade de títulos, tamanho do HD… e quem está levando a parada é a Nintendo. Com certeza os fanboys do PS3 e do XBOX sairam correndo para as lojas gritando “Shiny Boxes!”, vitimados pela máquina de marketing. Mas depois da euforia, o que sobrou?

O Léo com certeza vai deixar um comentário falando que a estratégia da Sony e da MS era outra, de dominar a central de entretenimento da casa. Ele tem razão. Mas o engraçado é que a liderança de mercado ficou com a empresa que não se preocupou em ser a líder de mercado. O grande diferencial da Nintendo é que ela se propôs a fazer algo que fosse da vontade do público consumidor, não da vontade dos acionistas.

A lição que se tira dessa observação: na Economia Digital, não é a tecnologia, per se, que adiciona valor na cadeia de produção. O que adiciona valor é a forma com que a tecnologia (nova ou já existente) é usada para resolver um problema. Com a comoditização tanto de software (graças ao Open Source) quanto de Hardware (graças a lei de Moore), o único ponto de valor agregado está no serviço prestado.

E o que isso implica para aqueles que trabalham com o desenvolvimento de tecnologia? Significa que não basta mais saber como programar, é necessário também ser capaz de saber o quê programar.

Design é tudo que importa para separar os bons desenvolvedores dos operários de luxo.

Se você é um desenvolvedor de verdade, e não um simples digitador de luxo, daqueles que recebe uma especificação pronta e tem que transformar diagramas UML em código Java, você já aprendeu que a parte realmente difícil de se fazer certinho em um software está no design. Não é na implementação, tampouco a parte de debugging. É claro que há os dias que gastamos horas e horas tentando resolver aquela porcaria de bug que nem o seu ursinho de pelúcia ajuda, mas isso é o trabalho braçal da coisa, e não o trabalho difícil da coisa. O trabalho que justifica o salário estratosférico que te pagam e os bônus de fim de ano e a máquina de café expresso que colocaram no escritório só para te manter acordado é o trabalho difícil, que só você, campeão, pode dar conta.

Com as linguagens de alto nível, com poder de hardware sobrando nas máquinas de hoje, com bibliotecas que resolvem problemas já conhecidos e com o Google tendo informação sobre os HOW-TOs de praticamente qualquer coisa já bolada no mundo, a parte de implementação em um projeto de software é muito mais um processo de encaixar peças de quebras-cabeças do que de realmente construção propriamente dita. Ainda não chegamos na fase de “Lego Programming”, mas essa é uma tendência clara.

O que resta? O design. O design é aquela fase onde o analista precisa fazer uma coisa esquisita: sair da frente da IDE e conversar com o cliente. Para efeito de ilustração, cliente pode ser traduzido como “o cara que tem que aprovar o software se eu quiser continuar com o salário estratosférico que me pagam e os bônus de fim de ano e a máquina de café expresso que colocaram no escritório só para me manter acordado durante um trabalho difícil, que só eu, o campeão, posso dar conta.

A fase do design é justamente a fase dos requisitos. É a fase onde o cliente vai te pedir que o sistema seja simples, mas que tenha um monte de recursos. Que seja capaz de resolver todos os 13795 problemas que ele acha que tem ao toque de um botão. Um único botão. Que todos os usuários possam acessar o sistema sem precisar de formas complexas de autenticação, ao mesmo tempo que o sistema precisa proteger o arquivo que seja eventualmente apagado por uma secretária estressada, vingativa e sem aumento há mais de 2 anos.

Design é a arte de saber encontrar soluções adequadas para requisitos conflitantes. E os processos e metodologias para desenvolvimento de software acabam se dividindo em dois campos: os que assumem que não vão encontrar uma solução ótima, e trabalham por aproximações sucessivas (as metodologias agéis), e os que tentam investir tempo e dinheiro para descobrir o ponto ótimo antes mesmo de tocar em uma linha de código (o pessoal das escolas Big M de metodologias: CMM, RUP e outras sopas de letrinhas).

O ponto maior desse post que já está ficando longo: não há metodologia ou processo de software que vá te ensinar a encontrar os requisitos, muito menos um método que vá te mostrar qual é o melhor ponto para cruzar os requisitos conflitantes.

Nas empresas do Brasil que lidam com outsourcing, muito se fala da concorrência de empresas da China e Índia, onde a mão-de-obra é mais barata.

Deixe eu reescrever o paŕágrafo acima: em qualquer lugar do mundo se fala da China e da Índia, por ser um lugar com mão-de-obra barata.

E realmente, a Índia é um lugar onde impera a Ditadura do Processo. É lá que se concentram o maior número de empresas com CMM nível 4 e 5. É para lá que vão os grandes call-centers de empresas multinacionais. É para lá que vão os projetos de software com baixo valor agregado. Se você quiser algo feito com baixo custo e com controle de qualidade absoluto, a Índia é o lugar.

Até a indústria de cinema deles é assim. Bollywood produz 800 filmes por ano, mas é um processo tão maduro e estabelecido que você poderia jurar que é o mesmo filme, feito 800 vezes. É ISO 9000 em película: música maluca, mocinha em perigo, mocinho que salva a mocinha depois de fazer uma coreagrafia tirada de algum clipe do Menudo, mocinho salva a mocinha da maldição. Mais músicas e coreografias de Ricky Martin. Créditos do filme. Próóóóóximo…

Domínio do processo é um passo inicial, importante. Mas se pararmos aí, ficamos sempre dependentes de alguém que possa nos dar ordens e indicar o que devemos fazer. A pergunta: o que vai ser da Índia e da China quando a tecnologia de geração de código chegar num nível elevado o suficiente para que tenhamos o “Lego Programming”? O que será dos milhões de profissionais treinados em resolver problemas que já foram resolvidos?

Eu sei que o leitor do log4dev é inteligente e provavelmente já sabe que design é o que realmente importa, mas quero deixar essa idéia bem clara e justificada para um próximo post, com outras idéias: que senso de design é algo que pode aprimorado, que design é o único ponto onde uma startup pode se preocupar, e que o design está nos detalhes.