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.

Restrições

Outro dia saindo do trabalho, cruzei com uma mulher parada na frente da catraca/ponto eletrônico da empresa. Achei que ela estava lá simplesmente batendo papo com a recepcionista. Quando passei pela catraca, ouvi ela dizendo “Só mais dois minutos e eu posso passar…”.

Pra bom entendendedor….

Na hora me lembrei de um email que recebi, daqueles estilo corrente, com o tema “Como fingir que está trabalhando”. Basicamente dava dicas do estilo sempre andar com ar apressado e de preferência com várias pastas na mão mesmo que só pra ir ao banheiro, ou deixar a mesa sempre bagunçada, ou sempre deixar o telefone tocar várias vezes antes de atender, e coisas do gênero.

Confesso que eu mesmo já fiz várias coisas dessas.

Fato é que o dia a dia de uma empresa sempre tem duas componentes curiosas: funcionários fingindo que trabalham e chefes fazendo de tudo pra restringir qualquer coisa na esperança de aumentar a produtividade. Quanto mais se restringe pra aumentar a produtividade, mais se finge que se trabalha. Vira um grande teatro. E esse teatro aumenta porque muitas vezes, mesmo que você não tenha nada pra fazer, precisa fingir que está fazendo pra não ser mal visto. Me lembro que uma vez, em uma época de transição de projetos e má organização geral da empresa, fiquei mais de uma semana sem nenhuma tarefa a ser feita. Mesmo assim, se chegasse às 9 em vez de 8h30, pessoas me olhavam com ar de reprovação. Voltar pra casa mais cedo era impensável, mesmo se estivesse a 5 horas na frente do meu computador esperando por uma tarefa e não havia nenhuma num horizonte de 5 dias. E eu passava meu dia inventando tarefas pra não morrer de tédio absoluto. A maioria sem nenhuma ligação com a empresa.

Eu acredito que em ambiente de desenvolvimento de software, controle por ponto, restrições horárias, proibições de acesso a sites e coisas do gênero são a pior coisa que se pode fazer para tentar manter produtividade. Entendo que elas sejam necessárias em alguns casos específicos: restrições de acesso no meu entender são válidas apenas para ambientes que requerem alta segurança, e horários estritos são necessários para pessoas que trabalham com atendimento ao cliente. Mas quando se está desenvolvendo um produto, boa parte do trabalho é solitário, e a meu ver depende muito de inspiração.

E inspiração depende de momento. Tem gente que funciona melhor de manhã, tem gente que funciona melhor a tarde, e outros a noite. Tem gente que prefere trabalhar regularmente 5 horas por dia em vários dias, e conheço pessoas que trabalham por batch: 30 horas ininterruptas. Ou as vezes estamos em dias cheios de problemas pessoais, e as coisas não andam. Daí surge a necessidade de fingir.

Quando falo que sou contra restrições e afins, muitos me falam que o que eu quero é oba-oba, não trabalhar, etc. Muito pelo contrário, eu quero trabalhar e não ter que fingir que estou trabalhando. Mas quero trabalhar no meu ritmo. E como conciliar o meu ritmo com o da empresa ? Metas bem definidas e que devem ser cumpridas. Do ponto de vista do desenvolvimento de um software, uma vez que os requisitos estão bem definidos e cada desenvolvedor sabe o que deve ser feito, pouco importa em qual horário é feito, ou se foi feito em 30 horas seguidas de programação ou em blocos de 5 horas ao longo de 6 dias. Importa que esteja pronto na data, e feito com qualidade. Em termos de quantidade de trabalho, com certeza um sistema de metas agressivas com horários muito flexíveis pode ser muito mais efetivo do que um sistema de horários estritos.

H á alguns meses participei do processo seletivo de uma gigantesca empresa de software multinacional. No meu ponto de vista, uma das melhores. Ao final da entrevista, pude fazer perguntas sobre a empresa. Obviamente perguntei como era o esquema de horários e afins. A resposta foi que por exigência do Ministério do Trabalho, os funcionários tinham que bater ponto (contratação CLT), mas que o ponto era totalmente fantasia. Os desenvolvedores poderiam chegar na hora que preferissem, fazer seu horário, eventualmente trabalhar de casa, eventualmente trabalhar mais em certos dias para não trabalhar em outros. As únicas restrições eram em relação a reuniões de projeto (poucas segundo o entrevistador) e em relação à data de entrega do código. E a coisa simplesmente funciona.

Acho realmente que o melhor modo de estimular a produtividade é instigando o interesse dos colaboradores, estimulando a participação ativa no processo de delineamento de requisitos, oferencedo problemas interessantes a serem resolvidos, e criando um ambiente que estimule a pesquisa por novas tecnologias e idéias. Em outras palavras: acho que oferecer um ambiente cheio de restrições apenas aperfeiçoa a capacidade de teatro dos colaboradores.

Para terminar, sugiro um teste: ofereça a um desenvolvedor que goste do que faz um problema computacional interessante a ser resolvido, determine um deadline e instale-o em uma máquina com MSN/ICQ/GoogleTalk e Orkut liberado. Aposto que em 99% dos casos ele irá esquecer a existência de todos esses sites/programas enquanto o problema não for resolvido.

Miracle

Gerenciamento de projetos - SCRUM

Com o objetivo de melhorar a produtividade da equipe com a qual trabalho, costumo sempre pesquisar acerca de temas em engenharia de software que nos ajude a superar nossas limitações - equipe pequena, pessoas inexperientes, mudanças constantes em projetos, excesso de demandas … na última tentativa recai sobre o tema deste post - gerenciamento de projetos.

Devido ao excesso de mudanças que ocorrem dentro de um projeto (e trabalhamos com vários ao mesmo tempo), o excesso de demandas, e mudanças freqüentes de prioridades, acabamos por não conseguir nos concentrar em um problema tempo suficiente para desenvolver uma solução de boa qualidade. E ainda temos que gastar boa parte de nosso tempo gerenciando estas mudanças, e os problemas que são gerados a partir disto - clientes insatisfeitos (em nosso caso isso é crítico, pois eles estão a dois lances de escada de nós, sempre prontos a exigir que os atendamos), micro-planejamento, etc e tal … e com isso, o tempo que gastamos desenvolvendo diminui ainda mais.

Pensando nisso, pesquisando um pouco aqui e acolá, comecei a me interessar por desenvolvimento Ágil. Li o manifesto, comecei a achar bacana, e fui me aprofundando … até que conheci uma técnica ágil chamada SCRUM, através de um artigo de um cara chamado Henrik Kniberg. Neste artigo, ele descreve como ele implementou o SCRUM em uma dada empresa. O texto é muito bom, e para mim, foi bastante inspirador. Com aquilo, resolvemos experimentar a tal metodologia.

Em linhas gerais, qual a idéia do SCRUM (nota: é o que eu entendi. Pode não refletir a verdade plena)? Você e sua equipe devem desenvolver um produto, cujas demandas vão crescendo com o tempo, conforme você vai entregando porções da solução ao cliente. Ele vê o que você fez, encontra bugs, novas funcionalidades, incoerências com o que ele imaginava … e então você vai acrescentando novas demandas ao seu produto, que vão sendo priorizadas. Com esta lista de demandas, você e sua equipe fazem o planejamento do sprint, que pode ser entendido como um período de tempo onde vocês irão focar no desenvolvimento das principais demandas que vocês se comprometem a entregar ao fim do período (em nosso caso, nossos sprints são de três semanas). Dentro de um sprint, demandas não planejadas podem (e vão) surgir, e vocês podem ou não se dispor a atendê-las (possivelmente comprometendo alguma tarefa previamente planejada). Ao fim, você demonstra tudo o que você fez ao(s) seu(s) cliente(s) - e o que você não fez também. Para tanto, o SCRUM faz uso de algumas pequenas ferramentas:

- Sprint planning: reunião inicial onde a equipe define o que fará no sprint
- Daily Scrum: reunião diária (no máximo 15 minutos) para que a equipe relate o andamento das tarefas
- Sprint demo: reunião com o cliente para apresentar o resultado do sprint

Ao fim de nosso primeiro sprint, pudemos observar algumas mudanças interessantes:
- a equipe parece mais motivada, por participar ativamente das decisões de planejamento
- os clientes parecem mais felizes por receberem feedbacks periódicos sobre os produtos
- conseguimos encontrar problemas em períodos menores de tempo (logo na primeira apresentação de um produto, os clientes relataram uma necessidade crucial, não relatada antes, ao visualizar o protótipo de uma solução)

É claro que nem tudo correu às mil maravilhas. Temos vários problemas ainda, mas estamos empolgados com os primeiros resultados. Ainda temos outros planos, que vão além do SCRUM, que descreverei conforme forem sendo implementados. Mas a mudança já nos deu um gás novo. Isso é muito bom para nós.

Posteriormente, descreverei com mais detalhes como está se dando a implantação do SCRUM aqui, e espero daqui uns seis meses dizer se vale a pena o investimento ou não. Mas já acho que vale a pena tentar.

Frase do dia

There are just two kinds of languages: the ones everybody complains about and the ones nobody uses.”

Por Bjarne Stroustrup, criador da linguagem C++, em entrevista à revista online TechReview do MIT.

Gosto bastante também da seguinte crítica ao processo de desenvolvimento de softwares hoje em dia:

“I think the real problem is that ‘we’ (that is, we software developers) are in a permanent state of emergency, grasping at straws to get our work done. We perform many minor miracles through trial and error, excessive use of brute force, and lots and lots of testing, but–so often–it’s not enough.

Software developers have become adept at the difficult art of building reasonably reliable systems out of unreliable parts. The snag is that often we do not know exactly how we did it: a system just ’sort of evolved’ into something minimally acceptable…”

Turbogears

Recentemente comecei a brincar com Turbogears. É um framework para desenvolvimento de aplicações web em Python seguindo o famoso modelo MVC (Model View Controller). O pacote é baseado em um conjunto de bibliotecas para as diferentes funcionalidades: MochiKit para apresentação (com suporte para AJAX), CherryPy para controle e SQLObject para a parte de persistência. O interessante é que cada uma dessas bibliotecas é um projeto separado, com equipes de desenvolvimento, site, etc..

O Turbogears pode ser integrado com servidor Apache, mas oferece um servidor web caso se deseje rodar standalone.

Comecei a brincar com o Zope, mas achei o ambiente um tanto quanto complexo. O Turbogears é mais parecido com o modelo de desenvolvimento de aplicações Struts, com o qual eu tenho mais experiência.  A vantagem do Turbogears é que ele é bem menos complexo em termos de arquivos de configuração uma vez que as configurações são diretamente codificadas em Python.

Software livre e processos de qualidade de software

A idéia deste post surgiu das duas reclamações que o Miguel já fez neste blog a respeito da falta de documentação em projetos de Software Livre (uma destas reclamações está aqui) e de algumas conversas que tive com ele sobre este assunto baseadas na recente experiência que estou tendo no meu trabalho.

Bom, antes de mais nada, concordo com o Miguel de que falta documentação na maior parte dos projetos de software livre que eu já vi. Quer dizer, depende do que nós estamos acostumados a chamar de documentação. O meu referencial de documentação de um projeto vem dos conhecimentos de Engenharia de Software que eu tenho e da vivência com outras Engenharias. Deste ponto de vista, na minha opinião, documentação é tudo aquilo que te ajuda, de alguma forma, a explicar um sistema, como ele funciona, quais são suas funcionalidades e, talvez o mais importante, como usá-lo de uma maneira correta e eficiente, ou seja, para que o sistema serve.

Acho que a grande falha neste sentido para muitos projetos de software livre está no fato de que muitas pessoas da comunidade acreditam que a documentação é o código-fonte, afinal, que melhor maneira haveria para obter informações a respeito de um sistema do que simplesmente poder ver como o sistema funciona nos mínimos detalhes? A falha neste pensamento, comparado ao que eu disse no parágrafo anterior, está na palavra “ajuda”. A documentação deveria ajudar a entender o sistema e olhar o código fonte nem sempre ajuda muito no início. Em sistemas grandes como o Eclipse, pode-se demorar uma semana ou mais para se pegar o “jeito” e conseguir, a partir de então, obter informações relevantes do sistema a partir do código-fonte. Em projetos grandes, uma semana pode não ser muito tempo, mas isto inibe, por exemplo, que uma pessoa que nunca tenha feito um plugin para Eclipse se aventure a fazer um plugin que lhe pareça útil… simplesmente porque o tempo que ela vai gastar para entender a arquitetura do sistema lhe dá apenas duas opções: ou ela vai utilizar uma parte do seu tempo livre para entender o funcionamento do sistema ou vai se virar sem a funcionalidade que ela queria implementar e, provavelmente, distribuir gratuitamente para uso-fruto do resto da comunidade.

Outra questão importante é: se há documentação, muitas vezes ela não é de fácil acesso. É muito comum os sites que hospedam projetos de software livres terem estruturas complicadas, pouco amigáveis. Apesar de eu achar este um detalhe menor, é importante citá-lo também, pois isso leva com que pessoas que trabalham com software livre se comportem de uma maneira diferente de pessoas que, por exemplo, trabalham com software proprietário.

Quando eu programava em tecnologias proprietárias, minha maior fonte de referência não era o Google. Era muito mais fácil achar referências e soluções para meus problemas na própria documentação gerada pela empresa desenvolvedora do sistema. Tive esta experiência, por exemplo, com Visual Basic 6. Não quero aqui discutir as virtudes ou não desta linguagem e muito menos as virtudes ou não da Microsoft (isto dariam vários outros posts e este já vai ficar grande o suficiente). No entanto, a Microsoft fornece uma documentação muito completa, rica em exemplos e de fácil navegação e busca. Simplesmente isto fazia com que eu dificilmente recorresse a sites específicos a respeito de VB6, ou a fóruns ou ao próprio Oráculo, digo, Google. Isto também faz com que VB6 seja, ainda hoje, uma das linguagens mais conhecidas e mais utilizadas no desenvolvimento de sistemas, mesmo com todas as suas limitações e com o fim de suporte oficial da Microsoft à linguagem.]

Em compensação, todas as vezes que eu trabalho com software livre, “Google is my friend!”. Gosto das listas de discussão também, mas acho que elas são mais complicadas de serem utilizadas, pois existe toda uma etiqueta para participação de listas, o que inclui a leitura dos FAQs e perguntas antigas das listas, o que geralmente eu não tenho muita paciência para fazer. De qualquer forma, poderíamos dizer que neste caso a documentação não está escrita formalmente. Se ela existe, é difusa e esta mal catalogada (por melhor que o Google seja, ele não pode ser utilizado como catálogo de nada, até porque o objetivo dele não é este, por enquanto). Isto, na minha opinião, acaba inibindo alguns novos desenvolvedores a experimentarem o software livre. A filosofia de que a documentação é o código-fonte, para estas pessoas, não funciona.

Os mais puristas em relação ao modelo de desenvolvimento do software livre poderão pensar que eu estou exagerando, e talvez esteja mesmo. Mas eu queria chamar atenção para o fato de que talvez um processo mais elaborado de geração de documentação poderia fazer com que projetos de software livre fossem mais bem vistos por desenvolvedores de uma forma geral e pelas corporações também (afinal, hoje grandes empresas também têm papel decisivo no desenvolvimento de projetos de software livre).

Não estou dizendo também que se deva adotar um processo formal de qualidade de software no desenvolvimento de software livre. Este esquema, na minha opinião, não funciona com o modelo de desenvolvimento criado pelas comunidades de software livre. Um processo exagerado de documentação certamente desmotivaria os colaboradores dos projetos livres, mas alguns controles, como os criados, por exemplo, pelo Gforge, poderiam ser interessantes. Isto sem levar em conta alguns argumentos interessantes da comunidade de software livre para a ausência total de documentação nos projetos de software livre. Algumas que eu acho interessante e faço questão de comentar:

  • Software de qualidade não necessariamente é feito com processos de qualidade e nem todo software feito com processo de qualidade tem qualidade. Isto é uma verdade indiscutível.
  • Processos de qualidade de software como o CMMI focam boa parte do trabalho na definição dos processos pois se a empresa ou o grupo de desenvolvimento tiverem os processos bem definidos, isto significa que, teoricamente, a saída de uma pessoa do grupo e a sua substituição por outra pessoa não deveria interferir na qualidade do software produzido. Isto faz com que as pessoas sejam transformadas em meros recursos, o que, definitivamente, não é a idéia das comunidades de desenvolvedores de software livre, onde os desenvolvedores são os principais atores.
  • Espera-se que a comunidade de software livre tenha colaboradores bons. E uma pessoa que não seja boa o suficiente para ler um código-fonte e entendê-lo não agregará nenhum valor ao movimento. Isto, na minha opinião, é uma verdade pela metade. Uma das grandes batalhas de um dos principais representantes do mundo de software livre, o Linux, é que ele seja um sistema operacional mais aceito e utilizado mundialmente. E, para que isto aconteça, é necessário, antes de mais nada, que o sistema seja fácil de usar e seja entendido por pessoas que não fazem nem idéia do que seja um código-fonte. Qual é a melhor maneira de se fazer entender neste caso? Eu acho que uma boa documentação poderia ajudar bastante nesta hora.
  • Na comunidade de software livre, boa parte dos problemas que seriam resolvidos com processos de qualidade de software são resolvidos pelo mantenedor do projeto. Sem dúvida nenhuma, o mantenedor é uma figura crucial em projetos de software livre e ele é o responsável, como o próprio nome diz, pelo bom andamento do projeto. Dizer que o processo de desenvolvimento de software livre não possui nenhum processo formal de qualidade pode até ser verdade, mas isso não significa que o mantenedor e seus colaboradores não tenham que definir funcionalidades, recursos, estimar tempo de desenvolvimento e definir milestones e releases do produto. Tudo isto também acontece com software livre.

Em suma, acho que o que talvez falte para o software livre seja pegar algumas poucas idéias dos processos complexos de qualidade de software e tentar aplicar estas idéias de uma forma apropriada à sua realidade. Sei que cada projeto é um caso diferente e que as regras não seriam universais, mas alguns conceitos poderiam ser usados para tentar ajudar a vida não só dos desenvolvedores, mas também dos usuários comuns que queiram propagar a filosofia de ser livre.

Tirando agua de pedra

…ou como extrair informações de um cliente para fazer a especificação de um software.Recebi esta tira do Dilbert hoje de manhã, e ela tem tudo a ver com alguns problemas de especificação de software que estou vivendo atualmente. Conseguir extrair informações sobre o negócio de um cliente é uma arte, que requer tempo, perícia e uma boa dose de calma. O grande problema é que pessoas normais (em oposição a desenvolvedores) não conseguem entender o mundo virtual que um software constrói, não entende implicações de decisões erradas de design, e sobretudo nem sempre consegue definir quais são as informações importantes para o design, e quais são totalmente superfluas. E são esses pequenos detalhes esquecidos que em geral irão causar redesign, refactoring, e portanto atraso.

Exemplo prático: ontem, por acaso, descobri que um atributo que eu acreditava estar ligado a uma entidade entidade na verdade era ligada a outra entidade. Detalhe: a questão das entidades foi discutida milhõs de vezes, e o cliente aprovou um documento que explicitava as entidades e seus atributos. Resultado: mudar o atributo de uma tabela de BD para outra é muito simples….o problema é modificar queries, objetos, e validar tudo de novo. No meu caso, 2 dias perdidos praticamente.

O fato é que não se pode esperar que o cliente vá falar sobre tudo sozinho, e de preferência, não se deve pedir pro cliente descrever o seu negócio com a ótica do software a ser produzido…inevitavelmente, ele irá colocar filtros nas informações que em geral não são desejáveis. Quem deve delimitar o escopo do software e as informações realmente relevantes é o desenvolvedor, obviamente com base nas informações do cliente.