Archive for the ‘unix’ Category

Arquiteturas Simples Duram Mais

Wednesday, October 24th, 2007

Um amigo outro dia me perguntou que tipo de arquitetura eu usaria num caso bem peculiar. Basicamente ele foi encarregado de definir a arquitetura corporativa de um grande banco, ou seja: definir hoje a forma como aplicações serão construídas pelas próximas décadas. Basicamente ele vai se ro cara que vai ser xingado por algumas centenas de programadores nos próximos tempos, não importa que arquitetura escolha.

Há poucos dias atrás falamos aqui sobre arquiteturas de referência e seu efeito danoso. Geralmente quando alguém tem à frente um desafio desse ele logo pensa em um modelinho que mostra obriga o uso de uma meia dúzia de frameworks e padrões (clássico moderno: Struts/JSF e JPA, clássico vintage: Struts 1.1 e EJB/DAO). Para melhorar ainda é incorporado um conjunto de classes “utilitárias” feitas com práticas que talvez tenham servido para um projetinho piloto mas hoje em dia só atrapalham.

Ainda assim uma arquitetura corporativa é algo interessante. Quando empresas grandes não possuem uma macro-arquitetura acabam crescendo de maneira desordenada e criando dezenas de aplicações redundantes e gambiarras de integração entre sistemas. Note no entanto que uma arquitetura corporativa não é uma arquitetura de referência, a arquitetura corporativa não fala sobre como implementar aplicações mas sim provê guias sobre como integrá-las, define as relações previstas em no ecossistema que é uma grande empresa.

Quais são as melhores macro-arquiteturas que você conhece? Eu consigo pensar em algumas: Apache, UNIX, World Wide Web… Nestes ecossistemas aplicações novas surgem, são alteradas e morrem todos os dias há décadas, um sistema criado com a tecnologia mais recente de 2007 vai rodar tranqüilamente neste ambiente. Por quê?

Porque estas arquiteturas se baseiam em primitivas e contratos, não em especificações rígidas. Criar um módulo para o Apache , um programa para rodar em UNIX ou uma site é basicamente criar um programa de computador em uma das plataformas suportadas que obedeça a um contrato.

Uma boa arquitetura corporativa vai definir algumas políticas e contratos para a aplicação se relacionar com o meio-ambiente e só isso. No caso do banco, poderíamos definir que uma aplicação deve disponibilizar via uma interface POX/REST seus WebServices, que ela deve utilizar a API do Mogile FS para guardar dados em disco, que cache deve ser feito utilizando a API do memcached.

E se o arquiteto quiser sair do padrão? Ótimo, saia, mas ele deve oferecer compatibilidade com o ambiente.

E se eu já tiver comprado um sistema que faz WebServices via SOAP? Eu preciso criar um meio de disponibilizar estes serviços via POX/REST também. Pode ser uma adaptador simples, um ESB, o que quer que seja. É como quando você compra um equipamento eletrônico com tomada americana, você não vai mudar uma tomada na sua casa para o padrão exótico, vai é comprar o adaptador necessário para plugar ele nas tomadas do seu ambiente.

Mas e se não precisarmos de filesystem distribuído? E se já estivermos utilizando uma solução de cache que faz mais sentido nesta aplicação?

Ótimo, use. O uso de filesystem X, cache Y, banco de dados Z deve ser um guia. Toda vez que alguém precisar de uma solução de cache, filesystem, etc. ele olha o guia da empresa, se não servir ele usa algo que sirva. O que importa é que o uso fique encapsulado no sistema. Imagine que ao invés do Oracle 10g eu resolva usar um MySQL na minha aplicação. Está ótimo mas eu devo manter essa peculiaridade interna à minha aplicação. Os outros sistemas que vierem a se comunicar com o meu não devem precisar saber sobre a existência deste banco, eu não posso usar este banco para comunicação entre aplicações (o que já é uma coisa péssima para se fazer de qualquer forma).

O que importa é:

  1. O arquiteto tem liberdade para resolver seu problema da maneira mais adequada
  2. O novo sistema é compatível com o meio-ambiente

Para ser um bom arquiteto não é necessário ter tanta experiência assim, basta saber olhar os casos de sucesso e aproveitar o que funciona. Geralmente as técnicas utilizadas nestas arquiteturas são também catalogadas como Padrões Arquiteturais em livros. Um bom arquiteto tem que ser um ávido leitor de livros e de código.

Anotações sobre Language-Oriented Programming (LOP)

Friday, October 12th, 2007

Como alguns sabem eu tenho um blog em inglês onde o foco é na minha linha de pesquisa atual: Domain-Specific Languages e Language-Oriented Programming. Eu venho psotando sobre minhas experiências brincando com este “novo” paradigma e acabo de postar o rascunho de um primeiro artigo sobre o tema. Comentários são mais que bem-vindos.

Sistemas Simples, como Portais por exemplo

Sunday, October 7th, 2007

Esse debate no GUJ me mostrou umas coisas engraçadas. Eu já tinha idéia de como as pessoas não têm noção das dificuldades em manter um portal no ar, porque eu mesmo não sabia e porque entrevistei algumas dezenas de pessoas neste meu ano no setor, mas não deixa de ser engraçado.

Quando eu trabalhava numa pequena agência web, lá pelos idos de 2000-2002, eu atendi a muitos grande clientes. Petroleiras internacionais, bancos de investimento, bancos convencionais, fundos de pensão… para todos eu participei do desenvolvimento de sistemas web às vezes muito simples, ás vezes muito complexos. Existia um padrão neste segmento de sites institucionais feitos por pequenas agências, não sei se é assim hoje em dia mas era:

  1. Escolha um gerenciador de conteúdo (CMS)
  2. Escolha a tecnologia para construir o resto do site (se o CMS deixar)
  3. ‘Customize’ (yuck!) os templates (também conhecido como: Corrija os bugs do CMS)
  4. Entregue o site

Eu trabalhei com diversos CMS, na época todos os que prestavam eram pagos e caros. Para clientes pequenos usávamos o Publique!, para clientes maiorzinhos o Calandra, para clientes maiores o Vignette, para monstros que precisavam não de um portal mas de GED o Dcomentum e algumas vezes os caras pediam para trabalhar com Microsoft SharePoint. Minha opinião após algumas dezenas de projetos: Nenhum deles prestava (e duvido que prestem hoje).

Quando fui convidado para entrar para o mundo dos portais fiquei um pouco preocupado. Desde meus tempos na agência eu já havia trabalhado com sistemas de billing, telecom, logística, análise de risco e vários outros domínios complexos com sistema mega-complexos que de tão caros são cobrados em Euros e não dólares. Milhões de Euros, na verdade. Mas topei porque quem me fez a indicação é uma pessoa que sei que não me indicaria uma furada.

Veja só minha surpresa quando descobri que para um destes mega-portais de Internet um CMS não é opção. Ok, muitos deles até usam soluções dessas, meu empregador inclusive, mas apenas para uma parte muito pequena e repetitiva do trabalho. Para tudo que não puder ficar em cache o buraco é bem mais embaixo.

Mesmo para conteúdo cacheado, você acha que é simples manter uma página sendo acessada por milhões de pessoas num intervalo de tempo muito curto? Eu vejo quando uma pessoa na minha equipe evoluiu porque ela começa a ler sobre redes, gerenciamento de memória, etc. Outro dia um cara muito bom mas muito focado em Java que trabalha comigo recebeu uma reclamação de que a aplicação estava gerando um load muito alto nos servidores. Ele teve que se virar para entender o que é o load de um servidor e porque o CPU não fica em 100% mesmo quando o load atinge duas casa decimais. Daí a coisa evoluiu para entrar no servidor e ficar tirando thread dumps (que muitos nem sabem o que é) para analisar o sistema, depois olhar o fonte do java.util.HashMap e identificar um problema de loop infinito que acontecia nesta classe somente quando havia uma grande concorrência. É engraçado, o cara entra com aquela mentalidade de ‘analista/desenvolvedor JEE’ e sai como um profissional de verdade. Eu acho que todo mundo devia trabalhar num lugar assim, ou fazer estágio ao menos.

E aí as pessoas dizem que os nove sites citados lá pelo estudo são simplezinhos e por isso usam LAMP. Isso é muito protecionismo, meu Zahl…

Java é uma boa plataforma para vários casos, mas não para todos. O modelo de IPC pobre, o deployment caixa-preta e a falta de uma meta-programação de verdade afetam fortemente a plataforma mas não é nada que não se consiga viver com. O ponto é que as outras plataformas possuem também suas diversas vantagens em vários casos, entre eles sites como os citados. Cada vez mais os portais possuem maior lógica na Camada (Tier) de apresentação. Os sistemas que temos desenvolvido no meu dia-a-dia de portal geralmente são compostos por um site que possui lógica de aplicação e acessa vários serviços.

A lógica de aplicação eu sinceramente mudaria para Rails sem pensar meia vez. O único ponto que me faria ponderar a princípio seria performance, ironicamente Java é hoje uma das mais performáticas plataformas disponíveis, mas mesmo hoje performance é garantida através de outros meios como caches e hardware (nota: existem poucas coisas que deixam um sistema tão lento quanto construí-lo usando um CMS).

A parte de trás da aplicação, onde ficam os serviços, não seria tão simples. Alguns serviços podem ser migrados para plataformas leves sem pensar duas vezes (muitos deles já estão em PERL e PHP, na verdade) mas assim como faz o Flickr eu usaria Java em alguns deles (o flickr é em PHP e usa Java para upload).

O ponto não é usar ou não Java. O ponto não é Ruby on Rails ganhar de Java no caso XYZ. O ponto é usar ferramentas certas nos lugares certos. Devia fazer parte da ética profissional este tipo de coisa…

Introduzindo Agilidade num Ambiente

Wednesday, August 15th, 2007

Toda empresa em que eu já tenha trabalhado, atendido como fornecedor ou prestei consultoria até hoje tem o mesmo discurso: esse negócio de [qualquer novidade] é legal mas aqui dentro não funciona. Pode até funcionar nas empresas certinhas, mas aqui nosso negócio é muito específico, nossa tecnologia é muito específica, nossos banheiros são muitos específicos…. Tenho uma notícia para quem pensa assim: não existe empresa certinha. Todo mundo acha que é diferente dos demais.

Ainda bem que no meu trabalho as coisas não são assim. Todo mercado é dinâmico mas o de Internet chega ao ridículo, da noite para o dia todos os paradigmas mudam. Ao mesmo tempo nós somos o braço de Internet de um dos maiores grupos de mídia do mundo e temos que seguir os mesmos critérios de qualidade, agilidade e inovação dos nossos “irmãos” nos canais de TV, Jornais e Rádios.

Quando fui contratado um dos requisitos era exatamente trabalhar o processo de desenvolvimento da empresa. Não somos diferentes de ninguém, temos um processo que foi criado e adaptado por sete anos e está longe de ser perfeito, como em qualquer lugar padrão. Após algum tempo observando como as coisas funcionam começamos a introduzir mudanças.

Somos uma equipe grande (incluindo alguns colegas blogueiros) que tem como trabalho cuidar de diversos sistemas entre sites, ferramentas de edição e produção de conteúdos e utilitários diversos.

Antes da mudança que introduzimos nosso fluxo de trabalho era o mais caótico possível: alguém enviava um e-mail com algo que estava errado ou precisava ser feito. Este e-mail originava uma tarefa num Gantt Chart. Uma das minhas tarefas diárias era correr atrás da equipe com o cronograma na mão perguntando o que estavam fazendo, depois sentar na minha mesa e atualizar o cronograma. Cada desenvolvedor pegava uma tarefa, ocasionalmente dois dividiam uma mais complexa. Ao terminar o desenvolvedor enviava um pacote para a equipe de testes (nenhum teste além do eventual feito pelo desenvolvedor era feito por aqui) que testava e homologava. Eventualmente o pacote voltava e ia para produção.

A primeira providência foi acabar com o cronograma. Nós temos uma licença do Jira, que apesar dos seus problemas funcionais é um dos melhores issue trackers disponíveis. O fluxo mudou: agora o cliente enviava um e-mail, este entrava no Jira e era designado para a pessoa que dava um prazo para a solução.

Dentro os diversos problemas que ainda tínhamos era colocar coisas em produção. Para homologar, agendar para subir em uma janela, acompanhar a janela, etc etc perde-se muito tempo e a cada tarefa concluída o ciclo era repetido. Solução? Só subir software a cada 15 dias. Em vez de mandarmos 5 ou 7 pacotes por todo o processo mandávamos apenas um e desta forma economizamos muito tempo. Eventualmente conseguíamos fazer mais coisas por parar menos com distrações do processo.

O próximo problema era no mundo das prioridades. Antes alguém mandava um e-mail e olhávamos para ele. Se fosse algo muito grave no nosso ponto de vista (ou se o cliente ligasse reclamando) nós colocávamos a alteração no topo da lista, caso contrário ia para quando “tivéssemos tempo” (i.e. nunca). Obviamente o cliente não ficava satisfeito com essa priorização e nós perdíamos muito tempo trabalhando no que era importante para nós sem saber se era importante (ou mesmo útil!) para o cliente ou não.

Solução? Jogo do Planejamento. Temos diversos clientes internos (e alguns milhões de externos) então elegemos o grupo que realmente representa nossos clientes. Em reuniões semanais de uma hora nós passávamos todas as issues abertas (depois da primeira reunião isso foi rápido) e agendamos possíveis subidas para estas. O cliente pode alterar qualquer iteração, menos a que está em execução. Quando o sistema vai para o ar o cliente recebe uma lista com todas as modificações que subiram para testar e mandar o feedback.

Estava melhor mas ainda não era o ideal. Nossos projetos ainda eram planejados em extensos Microsoft Projects que em algumas semanas perdiam sua sincronia com… o mundo real. A visão era de que o esquema de Jira/Jogo do Planejamento/Release de 15 dias funcionava bem para a manutenção mas não para projetos.

Então mudamos algumas coisas. Após quatro membros da equipe participarmos do curso de Scrum da Teamware nós resolvemos colocar em prática alguns conceitos, melhorando o processo utilizado para manutenção de maneira que servisse para nossos projetos.

Colocar em prática? Como assim?!? O projeto já possui cronograma definido, equipe definida, o escopo vêm sendo discutido há meses! Por que não esperar uma boa oportunidade, com tudo calmo? Simples: porque ela não vai acontecer. Qualquer empresa que queira se manter competitiva vai estar sempre bolando algo novo e mantendo suas pessoas ocupadas com isso. Oportunidade não se espera, se cria.

Para minimizarmos o risco da adoção nós introduzimos as coisas aos poucos. O foco não era implantar o processo X ou o processo Y mas sim coisas que nos ajudassem. O Scrum é um bom molde, um bom guideline. Vamos tentar implantar o molde, se virmos algo melhor ou ruim no caminho adaptamos. Vamos seguir, devagar quando necessário, mas movendo para frente.

Primeiro precisamos diminuir a importância do Jira em favor de post-its. Issue trackes são ferramentas bem interessantes, com o passar dos releases fizemos os usuários aprenderem a abrir issues no jira e acompanhar o andamento por ele (muito menos telefonemas de ’status report’!). Um dos problemas da ferramenta era presença. Para termos o Jira numa reunião precisamos de um notebook e nem todos poderiam utilizar a ferramenta ao mesmo tempo. Outro problema era a granularidade das tarefas. Outro era que cada um tinha sua lista de issues para resolver então eu passava horas (eu diria quase que 8) todo santo dia priorizando todas as issues abertas para cada desenvolvedor.

Picture 001

Para os desenvolvedores deixar o Jira um pouco de lado está sendo simples. Eles já não atualizavam o status dele mesmo! Eu tinha que encher o saco diariamente. Para os outros interessados no andamento do projeto não, após termos ensinado a todos a utilizar a ferramenta falar para olharem para uma outra não seria muito bem recebido. Além disso, muitos dos nossos clientes estão em outros prédios da empresa e não conseguem olhar nosso quadro. A solução encontrada foi mantêr as user stories no Jira, mas não as tarefas.

As user stories passaram a ser blogs. Quando alguém enfrenta uma dificuldade e resolve o problema ele “bloga” um comentário, mas não chega nem a atualizar o status. O uso passou a ser muito mais documental e menos de visão de status. Quando alguma story atinge o status de ‘done’ eu atualizo o status no Jira. A documentação não é tão util, já temos um wiki com especificações técnicas (segundo princípio de Agile Modeling, geralmente fotos dos whiteboards e descrições de alto nível apenas) e estou louco para me ver livre da obrigação de sincronizar com o issue tracker todo dia.

Um dos problemas é que não tínhamos espaço disponível. O escritório oferece uma boa disposição de mesas em baias de 4 pessoas, mas não há paredes disponíveis para pregarmos cartazes.

Picture 009
(desconte a poluição visual da minha mesa)

A solução imediata foi pregar o cartaz com os post-its num rack de servidores para desenvolvimento que fica no corredor.

DSC00460

Hoje já pegamos um antigo laboratório para nossas reuniões mais importantes, mas ficamos um bom tempo apenas com o rack e ainda o utilizamos. Salas de reunião ou mesmo o laboratório são fechadas e os cartazes lá dentro não estão 100% do tempo visíveis. Seguimos com o planejamento do sprint atual no rack e os outros cartazes e artefatos no laboratório. Antes que alguém pergunte tudo é registrado em câmeras digitais e como já me reportou uma vez o Vinícius sobre suas experiências as fotos nunca foram usadas além de decorar Flickrs e 8Ps.

Então todos os dias nos reunimos em frente ao rack para nosso Daily Scrum, uma reunião rápida diária. Um dos problemas que as pessoas sempre levantam para fazer este pequeno “compartilhamento de status” é a hora. Fazer muito cedo as pessoas podem não chegar, muito tarde não vai ser produtivo… bem, aqui a coisa é bem pior. Nossa equipe não exige a priori nenhuma restrição de horário, trabalhamos com pessoas que criam software e soluções, não com recepcionistas que precisam atender o telefone. Como consenso decidimos que as 11 da manhã todos estaríamos aqui. Temos ainda problemas, alguns dias falta um ou outro mas no geral vamos bem.

DSC00462

A reunião dura quase que exatos quinze minutos, para evitar que as pessoas se dispersem precisamos conversar algumas vezes e explicar que o foco é nos objetivos, não no desenrolar das tarefas. Outro ponto foi esclarecer que a equipe se reporta a ela mesma, não a mim. Eu viajei bastante nas últimas semanas e eles precisaram tocar sozinhos, o que fizeram com maestria.

O projeto já estava com as entregas definidas e renegociar não era uma opção. Infelizmente não conseguimos fazer reuniões de priorização com o cliente mas o responsável pela definição de negócio senta aqui do lado e nossos Sprint Backlogs, a lista de coisas que implementaremos a cada Sprint, já estavam bem definidas, com pouca margem para reagendamento (que foi devidamente utilizada).

Para fazer o pouco de planejamento que restava nós nos trancamos numa sala e estimamos todas as tarefas. Nas primeiras iterações mesmo explicando que um Story Point é dado por relatividade (primeiro você acha o mais simples depois estima os outros usando da métrica do “o quanto mais difícil é fazer X do que fazer aquele mais fácil?”) o time surgiu com valores quase que aleatórios para as tarefas, basicamente marcaram um número muito alto para todos. Nas iterações seguintes as estimativas foram ficando mais reais e hoje todos fazemos piada dos valores originais. Descobri que incluir uma reavaliação das estimativas na reunião de retrospectiva pós-sprint é útil para termos um melhor critério.

Na reunião de planejamento de Sprint nós deveríamos fazer uma versão inicial das listas do que precisamos fazer (tarefas) para atingir o objetivo (user story) de cada item do Sprint Backlog. Com medo de introduzir muita coisa nova eu optei por fazer apenas a lista da primeira Story. No final isso se mostrou irrelevante.

DSC00455

A empresa possui seu fluxo de processo já estabelecido e precisamos fazer nosso processo ser compatível com o das outras equipes, que inclui um grande teste de homologação no final. Antes das mudanças o desenvolvedor não executava teste algum, a equipe de QA era a responsável. Com o tempo percebemos o quanto isso era trabalhoso e propenso à erros. Uma das soluções que buscamos é ter testadores na nossa equipe mas enquanto isso não acontece nós mudamos a forma de pensar.

Lá no início da jornada o Guilherme e eu introduzimos testes unitários com JUnit no build. Demorou um pouco mas fatalmente as pessoas começaram a fazer (e as palestras do Guilherme fizeram com que pessoas de outras equipes começassem a fazer testes unitários por si só!). Quando o Bruno entrou na equipe, antes do projeto, uma das primeiras tarefas que dei para ele foi configurar o CruiseControl para fazer build e executar testes unitários. Mais problemas: não havia um servidor disponível para instalar. Conversa aqui, conversa ali conseguimos espaço num servidor de testes que roda diversas máquinas virtuais de VMWare, instalamos Ubuntu e o dito cujo (hoje usaria o Buildx), pronto. Após o CruiseControl o Bruno tratou de integrar o Fit ao nosso processo para fazermos testes de integração, e rodando com o CruiseControl.

Como ninguém tinha experiência com o Fit, o Bruno trabalhou em par com quem pegava a tarefa de implementar os testes. Com uma semana as pessoas estavam escrevendo Fixtures razoáveis, mesmo os estagiários.

Outro ponto que precisávamos testar era a interface, quase sempre web. Avaliamos o Selenium e mesmo com limitações ele parecia razoável mas não ideal. O Tiago investiu um dia integrando o Selenium no nosso build e trabalhando com test-cases em XSTL e fez o mesmo esquema que o Bruno para passar conhecimento. Agora nosso desenvolvimento só está “pronto” quando o código foi criado, com JUnit, com testes no Fit e com Selenium. O último QA achou apenas um bug em um módulo que alguém esqueceu de testar com caracteres especiais.

No primeiro Sprint eu não fiz reunião de revisão. Foi um erro cometido pela pressa mas imperdoável. No segundo nós fizemos uma reunião extremamente útil, levantamos pontos bons e ruins e colocamos num quadro (cuidado, termos fortes abaixo. ambiente irreverente é assim mesmo):

Picture 029

A maior parte dos pontos ruins (no “nem F$#%endo”) eram interrupções externas que eu preciso trabalhar. Minha viagem (que era um dos pontos ruins) recente fez com que os desenvolvedores respondessem por compromissos meus (outro ponto: reuniões que duram dias inteiros) , além de deixá-los sem proteção de interrupções externas (outro ponto citado) como telefonemas e até suporte a outras equipes integrando com nossos sistemas. Tirei daí que se precisar me ausentar preciso deixar alguém como Scrum Master, ainda que o time perca um membro ativo. Diluir o papel de Scrum Master causa mais prejuízos do que tirar uma pessoa do time de desenvolvedores.

Os pontos positivos incluíram o trabalho em equipe, os mecanismos de teste que ajudaram no desenvolvimento, o QA não ter encontrados bugs, a janela para produção ter sido tranquila e outras coisas que basicamente derivam da nova maneira de trabalhar.

Dos pontos ruins o que me preocupou mais foram os referentes a plataforma tecnológica da aplicação. Fizemos uma mudanças grande na direção de uma arquitetura SOA e como qualquer empresa não temos tempo de treinar todo mundo rapidamente.

O desenvolvimento desta arquitetura foi feita basicamente antes do projeto iniciar. Eu incubi o Guilherme de levantar possíveis soluções para nossos problemas de integração e esboçamos o projeto dos WebServices com tudo que tínhamos de melhor, incluindo REST. O primeiro uso desta infra-estrutura foi num projetinho bem curto que realizamos no início do ano e ela se mostrou muito boa.

O problema foi que neste projeto apenas o arquiteto (o próprio Guilherme) e eu metíamos a mão neste sistema. Quando começamos o projeto maior os conceitos ali dentro precisavam ser espalhados. Na primeira iteração com algumas cabeçadas conseguimos um desempenho bom mas ainda não o suficiente. Também vimos alguns pontos onde a arquitetura estava diminuindo muito a produtividade das entregas e que a introdução dos conceitos de WebServices REST, Hibernate/JPA, caches distribuídos e outras coisas menores precisa ser feita com mais cuidado. Algumas pessoas aprendem rápido e sozinhas, outras não e isso não tem a ver com habilidade técnica e sim com perfil (coisa, aliás, que defendo aqui desde sempre).

A solução que pensamos foi adicionar como tarefa um workshop arquitetural. Eu não queria cometer o mesmo erro e trancar o projeto na mão de um membro do time apenas (ou alguns), então nos reunimos durante a tarde. Na primeira parte da reunião o Guilherme explicou a arquitetura do início, mesmo para quem teoricamente já sabia foi útil.

Picture 019

Para estruturar a coisa eu pedi ao Guilherme quatro visões: a estrutura lógica (componentes), a estrutura física (servidores, bancos de dados, etc.), a de pacotes (como os módulos são divididos) e a de caso de uso (descrição do que acontece numa user story relativamente complexa do início ao fim).

Depois nós realizamos um exercício que aprendi no curso da TeamWare: cada um recebeu um bloco de post-it e uma caneta. Por cinco minutos escrevemos tudo que atrapalha nossa produtividade rapidamente, se alguém não pensasse em nada escrevia “nada” no papel. Depois discutimos cada ponto destes sorteando um de forma aleatória. Da forma escolhida para sortear surgiu o nome interno da técnica: a Dança do Siri (derivado da maneira “curiosa” de obter os papéis pelo Tiago):

Picture 027

Houveram poucos pontos técnicos, a maioria de infra-estrutura. Neste meio surgiram também coisas de processo como o papel dos estagiários no time. Um dos pontos levantados é de que nosso time não é tão homogêneo (e qual é?) e nem todos conseguem trabalhar em todas as partes do sistema. Uma estratégia que definimos foi de fazer pares quando ocorrerem estes casos e se tudo mais falhar partir para outra tarefa. O importante é quebrarmos os feudos de sistemas.

Todas foram discutidas, os pontos cabíveis foram anotados e mantivemos o histórico:

Picture 028

Na reunião para a entrega do primeiro pacote tínhamos um problema: descobrimos um erro no cronograma inicial (criado antes do projeto iniciar e antes de adotarmos o processo novo) que iria atrasar o projeto em oito dias. Começamos a reunião com uma descrição do processo de desenvolvimento para os clientes (aqueles que não participam no dia a dia do produto), revisão dos fatos ocorridos que desencadearam no atraso, o que faríamos para voltar ao rumo e a demonstração das funcionalidades. Para nossa surpresa a resposta foi excelente. Os clientes elogiaram a transparência do desenvolvimento, elogiaram o fato de verem algo em produção tão rapidamente e terminamos tendo que responder a uma pergunta: mas por que não fizemos assim antes?

Nós não implementamos o Scrum por completo (me viu falar em burndown chart aqui?), ainda falta bastante. Também não conseguimos eliminar problemas de prazo, tivemos que trabalhar algumas horas extras no último Sprint e possivelmente neste também. Algumas pessoas não se adaptaram aos novos processos e deixaram a equipe. Mas o importante aqui é que elevamos a qualidade do nosso trabalho consideravelmente -a ponto do cliente perceber- e as pessoas estão felizes em trabalhar desta forma, tanto as de fora quanto as de dentro. Paramos de correr atrás do prórpio rabo resolvendo problemas aleatórios diários e estamos trazendo resultados.

Engraçado que outro dia alguém falou comigo no corredor “Poxa, tô sabendo que vocês estão indo muito bem no projeto, heim? Perguntei pra Fulana -uma cliente- e ela disse: ‘É, eles estão gerenciando na linha dura desta vez, estilo sargentão’”.

Será?
Picture 023

Construindo Expressividade com Linguagens Elegantes

Friday, July 27th, 2007

Ainda não vi uma definição sobre o que seria uma linguagem elegante, então lá vai a minha:

Uma linguagem elegante é baseada em primitivas simples e extensíveis e, principalmente, sem muitas exceções.

Segundo esta definição Ruby, Smalltalk e LISP são elegantes. Java é um pouco, C# com suas centenas de exceções (sobrecarregar + é diferente de sobrecarregar [], dentre outras várias exceções) não é.

Uma linguagem elegante é simples e compacta. É de se esperar que não tenha sobrecarga de operadores, mas isso não é verdade. O problema das pessoas com sobrecarga de operadores é porque elas vêem isso como uma quebra da rule of least surprise. Essa regra diz (implora, eu diria) para não surpreendermos nossos usuários modificando o mundo que eles já conhecem para que uma ação traga consequências não esperadas. Por exemplo imagine que você vai modificar um programa como o ls para dar mais performance (uau, você é bom!). Faça o que quiser mas não mude os parâmetros de entrada e saída ou você vai quebrar um zilhão de programas e scripts pelo mundo todo. Caso introduza uma feature nova faça o usuário explicitamente solicitar por ela (passando um flag no estilo ls -lira –my-fancy-new-feature) e mantenha o default como o antigo.

E onde entra sobrecarga de operadores nisso? Lá no seu primeiro curso de programação (ou no seu primeiro livro se você opta pelo caminho mais difícil) deve ter aprendido sobre literais, variáveis, condicionais e… operadores. Operadores são caracteres especiais com uma função bem definida na linguagem, por exemplo o operador de divisão, de resto, de adição…

Em Java, quando você chama:

String texto = "abc".toUpperCase();

É fundamentalmente diferente de quando chama:


int numero = 12 + 24;

Porque um método e um operador são coisas diferentes e você aprendeu a pensar desta forma. Se amanhã eu puder sobrescrever o operador + para que escreva algo na tela você vai se surpreender porque não era isso que o manual da linguagem te disse.

Ainda assim, existem muitas ocasiões onde sobrecarga de operador são mais que convenientes, são semânticos. Imagine o exemplo do nosso BigDecimal:


BigDecimal a = new BigDecimal("100");
BigDecimal b = new BigDecimal("300");

Some os dois. Ok, você é um programador Java esperto e sabe que vai ter que fazer algo como:


BigDecimal resultado = a.add(b);

Mas disso até me dizer que é melhor que usar ‘+’ é outra história.

Mas e a simplicidade? Não é legal termos um conjunto pequeno de operadores que faz coisas previsíveis e que servem na maioria das vezes? Sim, é! Mas num mundo onde tudo migra para mais expressividade, com Model-Driven Development e Domain-Specific Languages ter este tipo de limitação não é interessante. As melhores linguagens para construir DSLs são as mais flexíveis e por acaso as mais elegantes, que coincidência, não? E como Ruby, que se enquadra nestes dois aspectos, lida com isso?

Simples. Em Ruby não existem operadores, pelo menos não como você está acostumado em Java, operadores são apenas apelidos para métodos. A vantagem disso é que se muda o modelo mental, a partir do momento que você sabe que um operador e um método são a mesma coisa você tem com operadores o mesmo cuidado que tem com métodos. Ao chamar add() do BigDecimal você tem que saber se o método vai retornar o resultado como um objeto separado, se vai modificar os objetos passados como parâmetros, etc. Como você faz isso? Lendo a documentação até se familiarizar com a classe e seu idioma. Após familiarizado você começa a usar sem pensar.

E quando você espera estar lidando com uma classe que sobrescreve um operador e na verdade recebe como parâmetro uma subclasse dela? Sem problemas! Se o autor seguiu os princípios básicos da Orientação a Objetos, que derivam do Design by Contract e o Princípio de Substituição de Liskov a subclasse tem que obedecer o contrato da classe-pai, e se você obedeceu os mesmos princípios não precisa de nada que não esteja no contrato.

Esse tipo de resistência com funcionalidades é o tipo de coisa que se elimina aprendendo várias linguagens e estudando suas motivações. Existem algumas linguagens como as citadas que merecem ser estudas ainda que você nunca as vá utilizar de fato. Elas abrem a sua cabeça.

Sobre Hackers e Talkers

Tuesday, July 3rd, 2007

É impressionante o que se consegue com um time de qualidade. Independente de qualquer ponto que qualquer um (inclusive este que vos escreve) tenha contra o Mono,a implementação livre do Microsoft .Net Framework, o time do conturbado Miguel de Icaza mostrou uma excelente performance ao implementar em dias uma especificação nada simples.

Utilizar um time composto por hackers minuciosamente selecionados é algo inviável no mercado comum -simplesmente não existem profissionais suficientes e geralmente temos um hacker cercado por um oceano de Morts- o que faz este acontecido ainda mais louvável.

Encapsulando o Futuro Incerto

Tuesday, June 26th, 2007

Após as turbulências voltamos ao normal, ou quase. O número de visitas caiu pela metade neste período, então por favor avisem a seus amigos que o blog mudou: blog.fragmental.com.br. As URIs antigas devem funcionar mas esta é a oficial.

Nestes últimos dias acabei migrando para o Gnome. Eu nunca fui muito com a cara do gerenciador, mas acho que sempre foi por birra minha com o Miguel de Icaza. Eu nunca engoli direito a história de se implementar as pseudo-especificações da Microsoft como Software Livre em vez de investir em uma plataforma como Java, Python, Ruby ou Strongtalk, mas enfim, hoje em dia eu até Mono uso…

O Gnome segue um paradigma mais minimalista, quem está acostumado com muitas opções sofre um pouco mas anda fácil depois de um tempo. Eu não diria que é melhor ou pior que o KDE< é questão de costume e gosto apenas. O problema que eu venho experimentando não está no Gnome ou KDE e sim nos softwares que os acompanham. Para a maioria das pessoas que usam um computador as configurações de fábrica são mais que suficientes. para um programador este não é o caso. Nós sempre temos que experimentar,t estar e acabar com um HD torrado ou algo parecido. No caso destes ambientes, "algo parecido" geralmente é uma aplicação travando. O problema acontece mais frequentemente com aplicações pequenas, aquelas que ficam nas respectivas docks. É interessante que na maioria dos casos as aplicações funcionam normalmente, mas basta quebrar uma dependência, tentar algo muito diferente e elas desabam. Aí você procura uma solução na internet e descobre que aquele comportamento se deve ao fato da aplicação fazer várias suposições sobre o ambiente que roda, por exemplo que está no KDE ou Gnome. E falha.

Vivi um caso parecido há poucas horas. Era uma página de Internet simples, o problema consistia apenas em XHTML e JavaScript. Uma determinada <div> continha uma objeto flash dentro de si e em alguns casos especiais ele deveria ser substituído por outro. Aí entra o problema. O objeto original faz parte de um determinado framework de anúncios, o novo faz parte de outro. Ao trocar o conteúdo havia um problema de JavaScript que só se manifestava no pior browser: Internet Explorer 6.0. Este browser possui recursos pífios de depuração e por anos é a dor-de-cabeça do pessoal de implementação client-side. Eventualmente, após muitos alert()s, descobrimos que o problema era que o framework original estava no time dos que fazem diversas suposições sobre o ambiente. Ele supunha que existiria um objeto com determinado nome, que uma determinada função estaria disponível, etc. etc. etc.

Estes são dois exemplos simples que mostram o quanto encapsulamento é importante. Você não precisa de objetos para ter encapsulamento (apesar de que se você tem objetos deveria ter encapsulamento), você pdoe encapsular algo como o que sua aplicação expõe e espera encontrar do lado de fora ou como seu JavaScript reage a mudanças na página - Web 2.0, meus caros, Web 2.0 -, o que importa é que seu código abstraia a implementação do que acontece no exterior (uma <div> é uma <div>, não importa se dentro possui o objeto A ou B), qual a implementação das coisas (KDE e Gnome fazem basicamente a mesma coisa) e, principalmente, colabore com as outras aplicações escondendo delas os detalhes da sua implementação.

A “culpa” da quebra de encapsulamento geralmente não está na classe que usa outra e sim na que não oculta dos seus clientes os seus segredos mais íntimos: como diabos ela é implementada.

Linux No Desktop

Thursday, June 14th, 2007

Já que começamos o tema vamos prosseguir para o GNU/Linux no desktop. Minha opinião? Linux no desktop é para quem tem pelo menos tempo (e interesse) de saber minimamente como um computador funciona. É simples: se você é um programador (ou se diz um) e não saber utilizar um GNU/Linux como desktop você está no caminho errado da carreira. Vamos lá, o GNU/Linux não tem nada de novo em termos de sistema operacional. Se você estudou SO em algum lugar (faculdade, livro, cadeia, etc.) você consegue saber como um UNIX funciona, se você acha que “perdeu tempo” estudando S.O. saia desta carreira e deixe os profissionais assumirem.

Mas… minha mãe não. Minha mãe trabalha com projetos, ela não tem tempo nem interesse em aprender como um computador funciona. Durante alguns anos ela usou GNU/Linux alegremente, quando eu morava com ela e dividíamos o computador. Ela já usou diversas distribuições e nunca reclamou. Por que? Porque eu configurava todo o computador, saia no tapa com winmodems e parâmetros bizarros e quando ela usava a máquina ela estava funcionando. Isso explica porque GNU/Linux para desktops corporativos funciona bem: quem toma conta não é o usuário. Agora minha mãe mora sozinha, eu deixaria um GNU/Linux instalado lá? Se eu não tenho tempo de a administrar (ainda que remotamente) não.

E não, não é mérito do Windows, é vergonha do GNU/Linux. Exemplo? Pegue um usuário leigo, deixe ele usando Mac OS X e depois pelo mesmo tempo seu sabor favorito de Linux. Sabe qual ele vai preferir? Eu já fiz essa experiência e te digo: o Mac. As interfaces GNU/Linux, por mais que KDE e Gnome sejam ótimos, não estão prontas para o usuário comum. Neste instante alguém diz: ah, é porque a documentação é para Windows.

Vamos lá, minha mãe não lê o manual do DVD player dela para saber o que o botão XYZ do controle remoto faz, você acha que ela procura na Internet como resolver um problema? A coisa tem que ser intuitiva e como eu disse acima um sistema UNIX é extremamente intuitivo para quem tem a mínima noção de como funciona um SO, mas não o contrário. Minha mãe não consegue diferenciar a rede local da Internet, como ela conseguiria conectar um modem ADSL para dois computadores? E estamos falando de uma pessoa que lida diariamente com computadores diversos há uns bons quinze anos, tanto no trabalho quanto em casa, e já passou por todos os sabores de Windows e antes dele o DOS e OS/2.

Eu não entendo como alguém pode aceitar as limitações de um sistema Windows enquanto desenvolve software (tanto que mesmo quando programo em .Net uso o Mono), mas realmente não consigo conceber um usuário doméstico, sem administrador, usando GNU/Linux.

Kickin’

Saturday, June 9th, 2007

Tem alguns meses que eu voltei apra o paraíso que é trabalhar apenas em GNU/Linux. No trabalho e em casa tenho um Kubuntu e para as aplicações que preciso de Windows (alguém disse MS Project?) eu rodo uma VM no qemu.

Ontem eu fiz a atualização periódica do meu sistema. É muito difícil, você precisa abrir um terminar e digitar:


$apt-get update
$apt-get upgrade

Sim, isso tudo.

Depois eu descobri que o Firefox não estava se entendendo com o kicker (a “barra do botão iniciar” do KDE). O kicker simplesmente travava. Pelo log do processo tinha algo errado na minha configuração do X misturada com a do Beryl. Depois de ler alguns históricos e fóruns eu descobri a solução adicionando uma linha nova na configuração para suportar um módulo novo qualquer, pronto. Tempo total: 45 minutos.

O que?!! 45 minutos para consertar um bug do sistema?! Sim. Mas pense bem: se isso acontece num sistema onde você não tem controle (nem digo um sistema de código fechado, esse não é o problema, o problema é não ter controle) você só ia ter uma opção: reinstalar o sistema. E sim, eu poderia reinstalar o sistema e ia demorar muito menos, já que eu talvez só precisasse reinstalar o KDE e não todo o SO como acontece com o Windows (acrescente duas linhas na sequência acima e pronto).

Aqui em casa temos um espaço com dois desktops, o da minha esposa e o meu. Ela roda Windows (mas está querendo migrar para Mac, não aguenta mais) e dia desses eu passei várias horas fazendo algumas manutenções no PC dela após uma sequência que começou com spyware e terminou com um computador sem som e que não reproduzia DVDs. Após a luta para salvar as fotos dela, arquivos, etc. eu formatei a máquina toda, depois tive que baixar aqueles programas que reconhecem o hardware para baixar de 3 sites diferentes os drivers de todos os periféricos, além da grana em anti-vírus.

Este não é um post do tipo “mude para Linux” porque eu já passei desta fase, mas é só uma demonstração de como os problemas que existem em ambas as plataformas são tratados.

Microsoft: RIP?

Monday, June 4th, 2007

Paul Graham e Martin Fowler decretaram o fim da MSFT. Não é a primeira vez que isso acontece mas desta vez são grandes nomes, um sempre escandaloso e um geralmente bem imparcial, na ordem. Como falamos aqui nos últimos meses, Redmond tem surpreendido a comunidade de desenvolvimento (como nota Fowler) com novidades realmente interessantes mas… Microso$oft é MSFT, não tem jeito. Após tantos anos jogando com as peças erradas vão ser necessários muitos milhões de dólares e neurônios para virar a mesa, e por mais que dólares não faltem neurônios ainda são muito caros para Redmond, já que seu preço varia com o freguês.

Enquanto Graham se atêm às perdas de mercado na computação de desktops Fowler fala sobre a perda de mercado da plataforma .Net. Vai ser necessária muita inovação, tanto em SO quanto em plataforma de desenvolvimento, para reverter o jogo. Em Plataforma temos visto aqui que realmente eles estão tentando, e muitas vezes conseguindo. A parte de SO é a antítese: cópias de recursos com mais de dez anos de existência.

Dado que a MSFT prende sua plataforma ao seu SO, o sucesso ou fracasso de um influencia o outro. Este risco sempre esteve presente para o programador .Net mas antes ele era tão irreal que era simplesmente desconsiderado. Agora ele está aí nas mãos dos milhares de MacBooks nas mãos de quem mora em países civilizados (do tipo que não faz um MacBook custar R$6.500,00) e dos sabores de GNU/Linux que alimentam os datacenters. Na lista do Graham sobre como salvar a MSFT eu incluiria abrir sua plataforma para externos. Por mais que o Windows continue caindo pelo menos uma parte da empresa estará a salvo.