BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos O Design Está Morto?

O Design Está Morto?

Para muitos que entraram rapidamente em contato com Extreme Programming, parece que o XP chamado por a morte do design do software. Não somente é uma atividade de design ridicularizada como "Big Up Front Design", mas tal técnicas de design como a UML, frameworks flexíveis e até mesmo os patterns são re-enfatizados ou puramente ignorados. Na verdade o XP envolve muitos designs, mas faz de uma maneira diferente do que é estabelecida pelo processo de software. O XP tem rejuvenescido a noção de design evolucionário com práticas que permitem evoluir para se tornar uma estratégia de design viável. Ele também fornece novos desafios e habilidades como os designers precisam para aprender como fazer um simple design, como usar refactoring para manter o design limpo e como usar dos patterns em um estilo evolucionário.

Extreme Programming (XP) desafia muitos conceitos comuns sobre desenvolvimento de software. Destes, um dos mais controversos é a rejeição de um esforço grande no projeto inicial, favorecendo uma abordagem mais evolucionária. Para seus opositores, esse é um retorno à técnica do "codifique e corrija" - comumente conhecida com ironia como hacking. Para seus fãs ela é comumente vista como uma rejeição das técnicas de projeto (por exemplo, UML), princípios e patterns. Não se preocupe com o projeto, se você ouvir o seu código, um bom projeto vai aparecer.

Eu me localizo no centro desse argumento. Muito de minha experiência profissional tem envolvido linguagens gráficas - a UML e seus descendentes - e patterns. Além disso, eu escrevi livros sobre UML e patterns. Por acaso, minha adoção de XP significa que eu deva repudiar tudo o que escrevi sobre isso, varrendo de minha mente todas essas noções anti-revolucionárias?

Bem, eu acho que não posso deixar você se debatendo sobre esse assunto. A resposta curta é não. A mais longa é o restante desse artigo.

Voltar ao topo

Design Planejado e Evolucionário

Nesse artigo, vou descrever dois estilos de como o design tem sido feito no desenvolvimento de software. Talvez o mais comum seja o design evolucionário. De modo resumido, o design evolucionário significa que o design do sistema cresce à medida que o sistema é implementado. Design é parte dos processos de programação e o design muda junto com a evolução do código.

No seu uso mais comum, o design evolucionário é um desastre. O design acaba tornando-se uma combinação de um conjunto de decisões táticas tomadas conforme a necessidade, onde cada uma delas torna o código mais difícil de ser alterado. Sob vários aspectos, você pode dizer que isso não é um design, e certamente essa situação nos leva a um design pobre. Como Kent observa, o design existe para permitir que você continue modificando o software com facilidade a longo prazo. À medida que o design se deteriora, sua capacidade de fazer mudanças com segurança também deteriora. Você vivencia o estado de entropia do software e com o passar do tempo o design fica cada vez pior. O resultado não é apenas um software mais difícil de manter, mas também beneficia o aparecimento de bugs, ao mesmo tempo em que fica mais difícil encontrá-los e corrigí-los. Esse é o pesadelo do "codifique e corrija", onde os bugs tornam-se exponencialmente mais caros de corrigir, à medida que o projeto continua.

O Design Planejado é o oposto disso, e traz um conceito herdado de outras áreas da engenharia. Se você quiser construir uma casinha de cachorro, pode ajuntar alguns pedaços de madeira e terá uma coisa esquisita. Entretanto, se você quiser construir um arranha-céu, você não pode trabalhar desse jeito - ele vai cair antes de chegar na metade. Dessa forma, você começa com desenho de engenharia, elaborados por um escritório de engenheiros parecido com o que minha esposa trabalha, no centro de Boston. Enquanto prepara o design ela resolve todos os problemas, alguns por análise matemática, mas a maioria deles usando códigos de construção. Os códigos de construção são regras sobre como projetar estruturas baseados na experiência do quê funciona (e alguma matemática também). Quando o design estiver pronto, os engenheiros podem entregá-lo para outra empresa construí-lo.

O design planejado de software deveria funcionar do mesmo jeito. Os designers pensam no problema como um todo, antecipadamente. Eles não precisam escrever códigos porque não estão construindo o software, eles o estão projetando. Portanto, eles podem usar uma técnica de design como UML que os libera de certos detalhes de programação e permite que trabalhem em um nível mais abstrato. Uma vez que o projeto estiver pronto, eles podem entregá-lo para um grupo separado (ou mesmo uma outra empresa) construí-lo. Já que os designers estão pensando em uma escala maior, eles podem evitar uma série de decisões táticas que levam à entropia do software. Os programadores podem seguir a direção do projeto e, considerando que sigam mesmo, terão um sistema bem construído.

A abordagem do design planejado existe desde os anos 70, e muita gente o tem usado. Ele é melhor em muitos aspectos do que o "codifique e corrija". Mas ainda tem algumas falhas. A primeira é que é impossível imaginar todos os problemas que você vai encontrar quando estiver programando. Portanto, seguramente você vai encontrar problemas durante a fase de programação, que irão questionar o projeto. E se os designers não fizerem mais parte da equipe, ou foram deslocados para outro trabalho, o que acontece? Os programadores começam a codificar por fora do projeto e a entropia se instala. Mesmo se o projetista ainda estiver por perto, leva tempo para resolver os problemas, modificar os diagramas, e então alterar o código. Normalmente existe uma correção mais rápida e a pressão do tempo. Olha a entropia (novamente).

Além disso, existe o problema cultural. Projetistas tornam-se designers por causa dos seus conhecimentos e experiência, mas eles andam tão ocupados trabalhando nos projetos que eles não têm muito tempo mais para codificar. Entretanto, as ferramentas e materiais para desenvolvimento de software mudam muito rápido. Quando você não codifica mais, você não apenas deixa de acompanhar o fluxo das mudanças que estão acontecendo, você perde o respeito de quem ainda codifica.

Essa tensão entre quem constrói e quem projeta acontece na área de construção civil também, mas é mais intensa na área de software. Ela é intensa porque existe uma diferença fundamental. Na construção civil há uma divisão clara nos níveis de conhecimento entre aqueles que projetam e aqueles que constroem, mas esse não é o caso na área de software. Qualquer programador que trabalhe em ambientes com projetos de níveis mais altos, precisa ser bastante experiente. Experiente o suficiente para questionar o projeto do projetista, especialmente quando o esse tem menos conhecimento do dia-a-dia da plataforma de desenvolvimento.

Mas esses problemas podem ser corrigidos. Talvez possamos lidar com a tensão humana. Talvez possamos ter designers com conhecimento suficiente para mudar os diagramas. Mas ainda existe outro problema: mudança dos requisitos. A mudança dos requisitos é o problema que mais causa dor de cabeça nos projetos de software que eu tenho trabalhado.

Uma forma de lidar com essas mudanças é prever flexibilidade no design de forma que ele possa ser modificado quando a mudança ocorrer no requisito. No entanto, para fazer isso é necessário que você saiba que tipo de mudança virá no futuro. Um projeto pode estar preparado para lidar com áreas de volatilidade, mas isso não vai ajudar se as mudanças vierem de um lugar inesperado. Portanto, você tem que entender muito bem os requisitos para separar as áreas de volatilidade, e isso, na minha visão, é muito difícil.

Alguns desses problemas de requisitos são oriundos da falta de compreensão completa dos mesmos. Dessa forma, muita gente foca nos processos de engenharia de requisitos, achando que isso vai evitar a mudança do projeto mais tarde. Mas mesmo essa direção pode não levará à solução completa do problema. Muitas mudanças nos requisitos ocorrem porque o negócio mudou. Elas não podem ser evitadas, portanto tenha cuidado com seu processo de engenharia de requisitos.

Com tudo isso, parece que o design planejado torna-se impossível. Certamente esses são grandes desafios. Mas eu não estou propenso a dizer que o design planejado seja pior do que o design evolucionário, já que este último é praticado na abordagem "codifique e corrija". E eu realmente prefiro o design planejado do que o "codifique e corrija". Entretanto, estou ciente dos problemas do design planejado e estou procurando uma nova direção.

Voltar ao topo

As Práticas para Utilização do XP

XP é controverso por muitas razões, mas um dos principais alertas em XP é defender o desenvolvimento evolutivo ao invés do planejado. Como sabemos, o design evolucionário pode não funcionar devido a decisões específicas de desenvolvimento e entropia do software.

No centro do entendimento deste argumento está a curva de mudanças do software. Esta curva diz que, enquanto o projeto é executado, se torna exponencialmente mais caro fazer mudanças. Ela é comumente expressada na frase "uma mudança que custa 1 dólar em tempo de análise, custará 1000 para ajustar em produção". É irônico como a maioria dos projetos ainda trabalham em um design de soluções específicas, que não tem uma fase de análise, mas a exponenciação está lá. A curva exponencial de mudanças significa que o método evolutivo pode não funcionar. Também mostra porque projetos planejados devem ser feitos cuidadosamente. Qualquer erro em métodos planejados sofrem a mesma exponenciação.

O fundamento por trás do XP é que é possível suavizar a curva, o suficiente para fazer o método evolucionário funcionar. A suavização na curva é tanto possibilitada quanto explorada por XP. Isto é parte do agrupamento das práticas do XP: especificamente, você não pode praticar partes do XP que se aproveitam da "curva suavizada" sem fazer as tarefas que preparam e permitem a suavização. Esta é uma fonte comum de controvérsia sobre o XP. Muitas pessoas criticam a exploração sem o entendimento de como a permitir. Frequentemente, as críticas partem de pessoas que tiveram experiências onde não aplicaram as práticas de preparação que permitem que as técnicas de exploração funcionem. Como resultado eles se queimaram e quando veem XP se lembram do fogo.

Existem muitas muitas peças para as práticas preparatórias. Na parte central estão as práticas de Testes e a de Integração Contínua. Sem a segurança fornecida pelos testes o restante das técnicas XP seriam impossíveis. A Integração Contínua é necessária para manter o time em sincronia, para que assim se possa fazer uma mudança e não se preocupar com a integração com outras pessoas. Juntas estas práticas podem ter um grande efeito na curva de mudanças. Fui lembrado disso novamente aqui na ThoughtWorks. A introdução de testes e a integração contínua deu um ganho de mercado no esforço de desenvolvimento. É certo, a ponto de se questionar seriamente a assertividade do XP, que é preciso aplicar todas as práticas para se ter os grandes ganhos.

O refactoring tem um efeito similar. Pessoas que refatoram seus códigos, de forma disciplinada como sugerido pelo XP, descobrem uma diferença significante na sua efetividade comparado a fazer livremente, ainda que de forma mais ad-hoc. Esta foi certamente a minha experiência, uma vez que Kent me ensinou a refatorar corretamente. Contudo, somente uma forte mudança me motivaria a escrever um livro inteiro sobre o assunto.

Jim Highsmith, em seu excelente sumário de XP, usa a analogia de conjunto de escalas. Em um lado está o design planejado, no outro o refactoring. Em uma visão tradicional, o método planejado domina devido a assumir que não se pode mudar de idéia posteriormente. Com a diminuição do custo da mudança, então, pode-se fazer mais do seu plano depois como refactoring. O design planejado não foge completamente mas, agora há o balanço de duas abordagens para se trabalhar. Para mim, parece que antes eu fazia todo o meu plano incompleto.

Estas práticas preparatórias de integração contínua, testes e refactoring, provêem um novo ambiente que faz o desenvolvimento evolucionário plausível. Contudo uma coisa que não ainda descobrimos é onde fica o ponto de equilibrio. Estou certo que, apesar da primeira impressão, XP não é apenas testar, codificar e ajustar. Há espaço para planejamento antes da codificação. Parte disto é antes de qualquer codificação, muito ocorre nas iterações antes de se codificar uma determinada função. Mas existe um equilibrio entre planejamento antecipado e o refactoring.

Voltar ao topo

O Valor da Simplicidade

Dois dos maiores chamarizes do XP são os slogans "Faça a coisa mais simples que poderá eventualmente funcionar" e "Você não precisará disto" ("You Aren't Going to Need It" ou YAGNI). Ambos são manifestações da prática no XP de Simple Design.

A forma como o YAGNI é normalmente descrita diz que, não se deve adicionar hoje nenhum trecho de código que será usado por uma característica necessária amanhã. Aparentemente, isto soa simples. A questão complica com coisas como "frameworks", componentes reusáveis e "design" flexível, estas são complicadas de construir. Paga-se um custo antecipado para as construir na expectativa que se tenha o retorno de custo posteriormente. Esta idéia de flexibilidade de construção antecipada é vista como parte chave para "design" de software efetivo.

Contudo, XP adverte que não se constrói componentes e frameworks flexíveis para o primeiro caso que precisa desta funcionalidade. Deixe estas estruturas crescerem de acordo com a necessidade. Se quero uma classe "Dinheiro" que executa soma, mas não trabalha multiplicação, então, construo apenas a soma em minha classe. Mesmo se estou certo que precisarei da multiplicação em minha próxima iteração, sei o quanto é fácil e rápido para fazê-lo, ainda assim, deixo para minha próxima iteração.

Há uma razão para esta economia. Se faço um trabalho que será usado por uma característica necessária amanhã, significa um desperdício de esforço nas características necessárias na iteração atual. O plano de entregas diz o que precisa ser trabalhado agora, trabalhar em itens futuros é contrário ao acordo entre desenvolvedor e cliente, há um risco que estórias da iteração não possa ser completado. Mesmo se as estórias da iteração não estiverem em risco, cabe ao cliente decidir qual esforço extra deve ser feito – e pode ser que este ainda não envolva a multiplicação.

Este desincentivo econômico é devido à chance que podemos não compreender a necessidade correta no momento. Especialmente porque não detalhamos os requisitos ainda. Por mais certos que possamos estar sobre como isto vai funcionar, podemos ainda entender erroneamente – especialmente enquanto ainda não temos os requisitos detalhados. Trabalhar na solução errada antecipadamente é mais desperdício do que trabalhar na solução correta posteriormente. Os "XPerts" geralmente acreditam que é muito mais provável que estejamos errados do que certos (e concordo com este sentimento).

A segunda razão para o simple design é que soluções complexas são mais difíceis de entender. Qualquer modificação no sistema é mais difícil quando se aumenta a complexidade. Isto gera custos adicionais no período entre quando o design complicado foi feito e quando ele foi necessário.

Este aviso atinge muitas pessoas como absurdo. Elas estão certas de pensar assim, se imaginar o mundo de desenvolvimento comum, onde as práticas preparatórias para o XP não estão implantadas. Contudo, quando o equilibrio entre os designs planejados e evolucionários se alternam o YAGNI se torna uma boa prática (e somente então).

Sumarizando, você não quer desperdiçar esforço, adicionando novas características que não serão necessárias até a próxima iteração. E mesmo com custo zero, você ainda não quer fazê-lo devido ao custo de modificá-lo, mesmo quando o custo para colocar foi zero. Contudo, você somente poderá agir assim quando estiver usando XP, ou uma metodologia similar que reduza os custos da mudança.

Voltar ao topo

O que é Simplicidade Afinal

Então nós queremos que nosso código seja o mais simples possível. Parece ser difícil discordar, afinal quem quer ser complicado? Mas claro que isso provoca a pergunta "o que é simples?"

Em Extreme Programming Explained - (XPE) Kent mostra quatro critérios para um sistema simples. Em ordem (mais importante primeiro):

  • Roda todos os Testes
  • Revela toda a intenção
  • Sem duplicação
  • Menor número de classes ou métodos

Rodar todos os testes é um critério bem simples. Sem duplicação também é bem direto, embora muitos desenvolvedores precisem de ajuda para conseguir. O complicado é revelar a intenção. O que exatamente isso significa?

O valor básico aqui é a clareza do código. XP dá muito valor ao código que é fácil de ler. Em XP "código esperto" é um termo abundante. Mas a revelação da intenção no código de algumas pessoas é a esperteza de outras.

Neste artigo da XP 2000, Josh Kerievsky aponta um bom exemplo disso. Ele olha o código XP possivelmente mais público de todos - JUnit. JUnit usa decorators para adicionar funcionalidade opcional para casos de testes, como sincronização concorrente e setup de código em batch. Separar este código em decorators torna o código mais claro do que seria de não fizesse isso.

Mas você tem que se perguntar se o código resultante é realmente simples. Para mim é, mas eu estou familiarizado com o padrão Decorator. Mas para muitos que não estão é meio complicado. Similarmente JUnit usa métodos plugáveis que eu percebi que a maioria das pessoas inicialmente acham muito difícil. Então devemos concluir que o design do JUnit é mais simples para designers experientes, mas mais complicados para pessoas menos experientes?

Eu acho que o foco em eliminar duplicação, tanto com "Uma e Apenas Uma Vez" do XP e o DRY (Don't Repeat Yourself - Não Se Repita) do Pragmatic Programmer é um dos conselhos mais óbvios e mais maravilhosamente poderosos. Somente seguir isso pode te levar longe. Mas não é tudo, e simplicidade é ainda uma coisa muito complicada de se achar.

Recentemente eu estava envolvido em algo que estava planejado demais. Foi refatorado e algumas das flexibilidades foram removidas. Mas como um dos desenvolvedores disse "é mais fácil refatorar design exagerado do que refatorar design nenhum." É melhor ser um pouco mais simples do que você precisa, mas não é um desastre ser um pouco mais complexo.

O melhor conselho que ouvi sobre isso tudo veio do Uncle Bob (Robert Martin). Seu conselho era não se preocupar muito sobre o que é um simple design. Afinal de contas você pode, deve, e irá refatorá-lo depois. No fim a vontade de refatorar é mais importante que saber o que é mais simples logo de cara.

Voltar ao topo

O Refactoring Viola YAGNI?

Este tópico surgiu na lista de discussão de XP recentemente, e vale a pena mostrar enquanto vemos o papel do design em XP.

Basicamente a questão começa com o ponto que o refactoring leva tempo mas não adiciona funcionalidades. Uma vez que o ponto do YAGNI é que você deve fazer o design para o presente e não para o futuro, isso é uma violação?

O ponto do YAGNI é que você não adiciona complexidade que não é necessária para as histórias atuais. Isso é parte da prática do simple design. Refatoring é necessário para manter o design o mais simples possível, então você pode refatorar quando você se der conta que pode fazer de uma maneira mais simples.

Simple design explora as práticas do XP e também é uma prática facilitadora. Somente quando você tem testes, integração contínua e refactoring você pode praticar simple design efetivamente. Mas ao mesmo tempo manter o simple design é essencial para manter a curva de mudanças reta. Qualquer complexidade desnecessária torna o sistema mais difícil para mudar em todas as direções exceto aquela que você antecipa com a flexibilidade complexa que você coloca. No entanto as pessoas não são boas em antecipar, então é melhor ir pelo caminho da simplicidade. No entanto as pessoas não terão a coisa mais simples da primeira vez, então você precisa refatorar para chegar mais próximo ao objetivo.

Voltar ao topo

Patterns e XP

O exemplo do JUnit me leva inevitavelmente a mencionar patterns. O relacinamento entre patterns e XP é interessante, e é uma questão comum. Joshua Kerievsky diz que os patterns são subenfatizados em XP e ele o faz eloquentemente, então não quero repetir. Mas vale a pena ter em mente que para muitas pessoas, patterns parecem estar em conflito com XP.

A essência desse argumento é que os patterns são utilizados em excesso. O mundo está cheio de programadores legendário, desde a primeira leitura do GOF que inclui dezesseis patterns em 32 linhas de código. Eu me lembro de uma noite, regada a um ótimo single malt, escrevendo com Kent um artigo a ser chamado "Not Design Patterns: 23 cheap tricks" Nós estávamos pensando em coisas como usar um if em vez de uma estratégia. A piada tinha uma razão, patterns são usados em excesso, mas não fazem deles uma má ideia. A questão é como você os usa.

Uma teoria disso é que as forças do simple design vão te levar aos patterns. Muitos refactorings fazem isso explicitamente, mas mesmo sem eles, seguindo as regras do simple design você chegará aos patterns mesmo sem conhecê-los. Isso pode ser verdade, mas essa é mesmo a melhor maneira de fazer? Certamente é melhor se você souber mais ou menos onde você está indo e ter um livro que o ajude nos problemas em vez de ter que inventar tudo você mesmo. Eu certamente ainda consulto o GOF toda vez que sinto que vou precisar de um padrão. Para mim, design efetivo diz que precisamos saber se o preço de um padrão vale o preço - isso é a sua habilidade. Similarmente, como Joshua sugere, nós precisamos estar mais familiarizados com a facilidade de usar um padrão gradualmente. Nesse aspecto XP trata como usamos patterns diferentemente do jeito que algumas pessoas usam, mas certamente não tira seu valor.

Mas lendo algumas das listas de discussões eu tenho a impressão de que muitas pessoas veem XP como pattern desencorajador, apesar da ironia que muitos dos proponentes do XP eram líderes do movimento dos patterns também. Seria porque eles enxergavam além dos patterns, ou porque patterns estão tão embutidos no seu pensamento que eles nem mais percebem? Eu não sei as respostas para os outros, mas para mim patterns ainda são de importância vital. XP pode ser um processo para desenvolvimento, mas patterns são a espinha dorsal do conhecimento em design, conhecimento que é valioso qualquer que seja seu processo. Processos diferentes podem usar patterns de maneiras diferentes. XP enfatiza tanto o não uso de um padrão até que necessário quanto evoluir até um padrão usando uma implementação simples. Mas patterns são ainda uma peça chave de conhecimento para se adquirir.

Meu conselho aos usuários de XP usando patterns seria

  • Invista tempo aprendendo sobre patterns
  • Concentre-se em quando aplicar o pattern (não muito cedo)
  • Concentre-se em como implementar o pattern na sua forma mais simples primeiro, depois adicione complexidade.
  • Se você colocar um pattern, e depois perceber que ele não está dando conta - não tenha medo de retirá-lo.

Eu acho que XP deveria enfatizar mais o aprendizado de patterns. Não estou certo de como eu encaixaria isso nas práticas do XP, mas tenho certeza que Kent pode achar um jeito.

Voltar ao topo

Desenvolvendo uma Arquitetura

O que queremos dizer com uma Arquitetura de Software? Para mim, o termo arquitetura transmite uma idéia de elementos que formam o núcleo do sistema, as peças que são difíceis de alterar. Uma fundação na qual o resto deve ser construído.

Que papéis uma arquitetura desempenha quando se utiliza design evolucionário? Novamente os críticos do XP afirmam que o XP ignora arquitetura, que o método do XP é cair na codificação rapidamente e confiar que o refactoring resolverá todas as questões de design. Curiosamente, eles estão certos, e esta pode ser exatamente a fraqueza. Com toda certeza, os praticantes de XP mais agressivos - Kent Beck, Ron Jeffries e Bob Martin - estão empregando cada vez mais energia em evitar qualquer design de arquitetura precoce. Não coloque um banco de dados até que você tenha certeza que você precisa dele. Trabalhe com arquivos primeiro e refatore a entrada do banco de dados durante uma iteração posterior.

Eu sou famoso por ser um praticante de XP covarde, e em vista disso eu preciso discordar. Eu acho que existe espaço para uma arquitetura ampla usada como ponto de partida. Coisas como afirmar a priori como as camadas da aplicação, como você irá interagir com o banco de dados (se você precisa de um), que abordagens usar para lidar com o servidor web.

Essencialmente eu acho que muitas destas áreas são patterns que aprendemos ao longo dos anos. Conforme seu conhecimento de patterns cresce, você deve ter uma hipótese razoável em como usá-los. Entretanto, a diferença principal é que estas decisões arquiteturais precoces não devem ser imutáveis, ou em outras palavras, o time sabe que eles podem errar nas suas primeiras decisões e devem ter coragem para arrumá-las. Outros contaram a história de um projeto próximo da entrega em que se decidiu que EJB não era necessário e ele foi removido do sistema. Foi um refactoring significativo, foi feito tardiamente mas as práticas presentes não o fez somente possível, mas também o fizeram valer a pena.

Como isso funcionaria de forma contrária? Se você decidisse não usar EJB, seria difícil adicioná-lo mais tarde? Você não deveria, então, nunca iniciar com EJB até que você tenha tentado outras alternativas sem ele e considerado-as insuficientes? Essa é uma questão que envolve muitos fatores. Claro que trabalhar sem um componente complexo aumenta a simplicidade e acelera as coisas. Entretanto, as vezes é mais fácil usar algo assim do que introduzir algo novo.

Meu conselho é começar avaliando o que a provável arquitetura será. Se você ver uma grande quantidade de dados com múltiplos usuários, vá em frente e use um database a partir do primeiro dia. Se você identifica uma lógica de negócios complexa, coloque um modelo de domínio. Entretanto, em respeito aos deuses do YGANI, quando em dúvida erre pela simplicidade. Também esteja pronto para simplificar sua arquitetura assim que você identificar uma parte que não está adicionando valor a nada.

Voltar ao topo

UML e XP

De todas as perguntas que me fazem sobre o meu envolvimento com XP, uma das maiores gira em torno da minha associação com a UML. Os dois não são incompatíveis?

Há diversos pontos de incompatibilidade. É fato que XP possui muito pouca ênfase em diagramas. Embora a posição oficial é a de "usá-los quando eles forem úteis", há uma mensagem implícita que diz que "verdadeiros adeptos de XP não fazem diagramas". Esta conclusão é reforçada pelo fato de que pessoas como Kent não se sentem confortáveis com diagramas; na verdade eu nunca vi Kent voluntariamente desenhar um diagrama de software em uma notação determinada.

Penso que o problema tem duas causas distintas. Uma delas é o fato de que algumas pessoas consideram diagramas de software úteis e outras pessoas não. O perigo é que aqueles que gostam de diagramas acham que os que não gostam deveriam gostar, e vice-versa. Em vez disso, devíamos apenas aceitar que algumas pessoas irão utilizar diagramas e outras não.

A outra causa é que diagramas de software tendem a ser associados a processos muito complexos. Gasta-se muito tempo desenhando diagramas para tais processos, e esses diagramas não ajudam e ainda podem causar danos. Então, acho que as pessoas devem ser aconselhadas sobre como usar diagramas e evitar as armadilhas, em vez de receberem a mensagem irresoluta "só se for necessário" que normalmente os XPerts dizem.

Então aqui vai meu conselho para a boa utilização de diagramas.

Primeiro, tenha em mente por que você está desenhando os diagramas. O valor primordial é a comunicação. Comunicação eficaz ocorre quando se seleciona as coisas importantes e se negligencia as menos importantes. Esta seletividade é a chave para utilizar a UML bem. Não desenhe cada classe - apenas as mais importantes. Para cada classe, não mostre cada atributo e operação - apenas os mais importantes. Não desenhe diagramas de sequência para todos os casos e cenários - somente ... ah, você já entendeu. Um problema comum com o uso de diagramas é que as pessoas tentam fazê-los muito abrangentes. O código é a melhor fonte de informação abrangente, pois o código é a coisa mais simples de se manter em sintonia com o código. No caso de diagramas, abrangência é a inimiga da compreensibilidade.

Uma utilização comum de diagramas é a de explorar um projeto antes de começar a codificá-lo. Muitas vezes se tem a impressão de que essa atividade é ilegal em XP, mas isso não é verdade. Muitas pessoas dizem que quando você tem um tarefa complicada, vale a pena ajuntar para fazer uma sessão de design rápido primeiro. No entanto, quando você fizer estas sessões:

  • Mantenha-as curtas
  • Não tente endereçar todos os detalhes (apenas os mais importantes)
  • Trate o design como um rascunho, e não como um design final 

Vale a pena expandir esse último ponto. Ao fazer design antes de qualquer coisa, inevitavelmente, você descobrirá que alguns aspectos do projeto estão errados, e você só descobre isto quando codifica. Isso não é um problema, contanto que você mude o projeto. O problema surge quando as pessoas pensam que o design está pronto, e então não usam conhecimento obtido com o código e para melhorar o design.

Mudar o design não significa, necessariamente, alterar os diagramas. É perfeitamente razoável desenhar diagramas que ajudam a compreender o design e, em seguida, jogar os diagramas fora. Fazer o design foi algo útil, e isso é suficiente para que valha a pena. Eles não precisam se tornar artefatos permanentes. Os melhores diagramas UML não são artefatos.

Muitos adeptos de XP utilizam cartões CRC. Isso não entra em conflito com a UML. Eu uso uma mistura de CRC e UML o tempo todo, usando a técnica que for mais útil para o trabalho a ser feito.

Outra utilização de diagramas UML é ter uma documentação em andamento. Em geral este é um modelo que reside em uma ferramenta CASE. A idéia é que manter essa documentação ajuda as pessoas a trabalharem no sistema. Na prática, muitas vezes, não ajuda em nada.

  • Leva muito tempo para manter os diagramas atualizados, de modo que eles deixam de estar em sincronia com o código
  • Eles estão escondidos em uma ferramenta CASE ou em uma grandiosa documentação impressa, e ninguém olha para elas 

Então, o conselho para documentação em andamento decorre destes problemas observados:

  • Só utilize diagramas que você consegue manter atualizado "sem doer muito"
  • Coloque os diagramas onde todos possam vê-los facilmente. Eu gosto de publicá-los em uma parede. Incentive as pessoas a editarem a cópia na parede com uma caneta quando houverem mudanças simples.
  • Preste atenção se as pessoas estão usando-os, se não jogue-os fora. 

O último aspecto da utilização da UML é de documentação na situação de passagem ou entrega de um software, por exemplo, quando um grupo passa um produto para outro. Neste caso, o ponto é que produzir documentação é uma história como qualquer outra, e assim o seu valor para o negócio é determinado pelo cliente. Mais uma vez, a UML é útil aqui, contanto que os diagramas sejam selecionados de forma a ajudar a comunicação. Lembre-se que o código é o repositório de informação detalhada, os diagramas servem para resumir e destacar as questões importantes.

Voltar ao topo

Sobre Metáforas

Ok. Eu posso dizer publicamente - Eu ainda não estou à vontade com essa coisa de metáforas. Eu vi que funcionou e bem no projeto C3, mas isso não significa que eu faça alguma idéia de como fazer isso, muito menos de explicar como fazer.

O uso de metáforas no XP é baseado em um sistema de nomes proposto por Ward Cunningham. Você inicia com um conjunto bem conhecido de nomes que serve como vocabulário para se falar sobre um determinado domínio. Esse sistema de nomes é usado para nomear classes e métodos em um sistema.

Eu já criei um sistema de nomes construindo primeiro um modelo conceitual do domínio. Fiz isso com experts no domínio usando UML ou seus predecessores. Percebi que você tem que ser cuidadoso ao fazê-lo. Você precisa se ater a um conjunto mínimo de notações simplificadas, e não permitir que qualquer questão técnica se "enfie" no modelo. Mas se você desenvolve esse modelo, percebi que pode usá-lo para construir um vocabulário do domínio que o experts nesse domínio podem entender e utilizar na comunicação com os desenvolvedores. O modelo não iguala perfeitamente com o design das classes, mas é suficiente para dar um vocabulário comum ao domínio como um todo.

Eu não vejo razão para que esse vocabulário não possa ser metafórico, como a metáfora do projeto C3 que transformou uma folha de pagamento em uma linha de montagem de uma fábrica, mas também não vejo porque basear o sistema de nomes no vocabulário do domínio seria má idéia. Também não estou inclinado a abandonar uma técnica que funciona bem pra mim na obtenção do sistema de nomes.

Alguns criticam o XP baseado em que você necessita de pelo menos algum design inicial do sistema. Os praticantes de XP respondem "Aí está a metáfora". Mas ainda penso não ter visto o uso de metáfora explicado de maneira convincente.

Voltar ao topo

Você Quer ser um Arquiteto Quando Crescer?

Por quase toda a última década, o termo arquiteto de software tornou-se popular. É um termo pessoalmente difícil pra mim de utilizar. Minha esposa é engenheira estrutural. O relacionamento entre engenheiros e arquitetos é digamos, interessante. Minha frase favorita era "arquitetos são decoradores que queriam ser engenheiros". A noção é que os arquitetos vem com todos aqueles desenhos bonitinhos, mas são os engenheiros que têm que garantir que aquilo realmente ficará de pé. Sendo assim, tenho evitado o termo "arquiteto de software". Afinal de contas, se minha esposa não pode me tratar com respeito profissional, que chance terei com outras pessoas?

Em software, o termo arquiteto significa muitas coisas (em software qualquer termo significa muitas coisas). Em geral, entretanto, ele traz consigo um certo status, como em "Eu não sou um mero programador, sou um arquiteto". Isso pode se traduzir em "Eu sou um arquiteto agora, sou muito importante pra ficar apenas programando". A questão então é se separar-se do esforço mundando da programação é algo que você deve fazer quando quiser exercitar uma liderança técnica.

Esta questão gera grande quantidade de emoções. Tenho visto as pessoas ficaram muito bravas com a idéia de que elas não têm mais um papel como arquitetos. "Não há lugar no XP para arquitetos experientes" é a choradeira que ouço com frequência.

Mais na área do design em si, não acho que seja o caso do XP não valorizar experiência e boas habilidades. Na verdade muitos dos proponentes do XP - Kent Beck, Bob Martin, e é claro Ward Cunningham - são aqueles dos quais aprendi muito sobre o que é o design. Entretanto, isso não significa que sua função seja diferente do que muitas pessoas veem como a função do líder técnico.

Como exemplo, vou citar um dos nossos líderes técnicos na ThoughtWorks: Dave Rice. Dave assumiu extra oficialmente a função de líder técnico de uma equipe de projeto com 15 pessoas. Sua função como líder implica em gastar um bom tempo com todos os programadores. Ele vai trabalhar com os programadores quando eles precisarem de ajuda e ele é que irá verificar quem precisa de ajuda. Um sinal significativo é onde ele se senta. Como funcionário "antigo de casa" ele poderia muito bem ter a sala que quisesse. Por um tempo, ele compartilhou uma com Cara, a gerente de configuração. Entretanto, nos últimos meses, ele foi para a área das baias onde os programadores trabalham (ao estilo "central de comando" do XP). Isso é importante porque dessa maneira ele vê o que está acontecendo e fica disponível para dar uma "mãozinha" sempre que necessário.

Aqueles que conhecem XP vão perceber que estou descrevendo explicitamente o papel de "Coach" do XP. Na verdade, um dos muitos jogos de palavras que o XP faz é denominar a figura do líder técnico de "Coach". O significado é claro: no XP, a liderança técnica é mostrada ensinando os programadores e ajudando-os a tomar decisões. Isto é algo que requer tanto habilidade com pessoas quanto habilidade técnica. Jack Bolles, na conferência XP 2000, comentou que existe pouco espaço atualmente para o "Mestre Solitário". Colaborar e ensinar são chaves para o sucesso.

No almoço da conferência, Dave e eu conversamos com um oponente do XP. À medida que discutíamos o que fazíamos, as semelhanças nas nossas abordagens eram marcantes. Todos nós gostávamos de um desenvolvimento interativo, adaptativo. Teste era importante. Assim, ficamos intrigados com a veemência dessa oposição. Então veio a frase "a última coisa que eu quero são meus programadores refatorando e macaqueando com o design". Agora estava claro. A incoerência conceitual foi explicada depois pelo Dave dizendo "afinal de contas, se ele não confia em seus programadores, porque os contratou?". No XP, a coisa mais importante que um desenvolvedor experiente pode fazer é, tanto quanto ele puder,  passar suas habilidades para os desenvolvedores júnior. Ao invés de um arquiteto que toma todas as decisões importantes, há o coach, que ensina os desenvolvedores a tomar as decisões importantes. Como aponta Ward Cunningham, fazendo isso, ele amplia suas habilidades e adiciona mais ao projeto do que faria um "herói solitário" qualquer.

Voltar ao topo

Reversibilidade

No XP 2002 Enrico Zaninotto deu uma palestra fascinante que discutiu o vínculo entre métodos ágeis e manufatura lean. Sua visão foi que um dos aspectos principais de ambas as abordagens foi que eles resolvem a complexidade reduzindo a irreversibilidade no processo.

Nesta visão uma das fontes principais de complexidade é a irreversibilidade das decisões. Se você pode alterar facilmente suas decisões, isto significa que é menos importante de corrigí-las - o que torna sua vida muito mais simples. A consequência de um design evolucionário é que os designers precisam pensar a respeito de como eles podem evitar a irreversibilidade de suas decisões. Ao invés de tentar corrigí-las na hora, procure de alguma maneira de postergar a decisão até o ultimo momento (quando você tiver mais informações) ou tome a decisão de maneira que seja possível revertê-la posteriormente ou sem muita dificuldade.

Esta determinação de suportar reversibilidade é uma das razões que os métodos ágeis colocam muito em ênfase em sistemas de controle de versão, e de incluir tudo em um sistema deste tipo. Enquanto ele não garante reversibilidade, particularmente para decisões em longo prazo, ele não provê uma base que dá confiança ao time, mesmo se for raramente usado.

Fazer um design para reversibilidade também implica em um processo que mostra os erros mais rápidos. Um dos valores de desenvolvimento iterativo é que iterações rápidas permitem aos clientes que eles vejam o sistema conforme ele cresce, e se um erro for cometido nos requisitos ele pode ser identificado e ajustado antes que o custo de alteração se torne excessivo. Essa rápida identificação é também importante para o design. Isto significa que você tem que preparar o ambiente de maneira que as áreas sejam testadas rapidamente de forma que seja possível visualizar os problemas que aparecem. Significa também que vale a pena fazer experimentos para ver o quão difícil pode ser fazer mudanças no futuro, mesmo que você não faça a alteração real neste momento - fazer efetivamente um protótipo descartável em um pedaço do sistema. Diversos times têm reportado que estão tentando fazer mudanças futuras previamente utilizando protótipos para ver o grau de dificuldade.

Voltar ao topo

O Desejo de Design

Enquanto eu tenho concentrado uma porção de técnicas práticas neste artigo, uma coisa que é muito fácil de deixar de fora é o aspecto humano.

Para funcionar, um design evolucionário precisa de uma força que o guie para uma convergência. Esta força pode vir somente das pessoas - alguém no time tem que ter a determinação de assegurar que a qualidade do design continue alta.

Isto não tem que partir de qualquer um (apesar de que seria legal se fosse), geralmente somente uma ou duas pessoas em um time tomam a responsabilidade de manter todo o design. Esta é uma das tarefas que geralmente cai sobre o termo 'arquiteto'.

Esta responsabilidade significa manter os olhos constantemente na base de código, vigiando para ver se alguma área do código esta tendo degradação, e então tomar ações rápidas para corrigir os problemas antes que se fique fora de controle. Os mantenedores do design não têm que ser as pessoas que o reparam - mas eles têm que assegurar que ele é corrigido por alguém.

Uma falta de desejo de fazer um bom design é a maior razão do porquê o design evolucionário pode falhar. Mesmo que as pessoas sejam familiares com os termos que tenho tratado neste artigo, sem este desejo o design não terá espaço.

Voltar ao topo

Coisas que são Difíceis de Refatorar

Podemos utilizar refactoring para lidar com todas as decisões de design, ou existem alguns problemas que são tão pervasivos que são difíceis de adicionar posteriormente? No momento, a ortodoxia XP diz que todas as coisas são fáceis de adicionar quando você precisa delas, então YAGNI é sempre aplicável. Eu imagino se há alguma exceção. Um bom exemplo de algo que é controverso de adicionar em um momento posterior é a internacionalização. Por acaso é tão doloroso iniciar esta atividade em um segundo momento que você deveria iniciar ela agora?

Eu já posso imaginar que existem algumas coisas que se encaixam nesta categoria. Entretanto a realidade é que nós ainda temos poucos dados. Se você tem que adicionar algo, como internacionalização, posteriormente você estará mais consciente do esforço que a atividade irá tomar. Você estará menos consciente do esforço que ela realmente leva, semana após semana, de incluir esta atividade e mantê-la antes que seja realmente necessário. Você também esta menos consciente do fato que você pode ter entendido de forma errada, e assim precise efetuar de qualquer maneira algum refactoring.

Parte da justificativa do YAGNI é que muitas destas necessidades em potencial terminam não sendo muito necessário, ou pelo menos não da maneira que você espera. Não fazendo, você irá poupar um esforço considerável. Apesar de que haverá um esforço necessário para refatorar uma solução simples para o que você realmente necessita, este refactoring é para ser menos trabalhoso do que construir todas as funcionalidades questionadas.

Outro problema a se pensar relacionado, é se você realmente sabe lidar com isto. Se você já fez internacionalização diversas vezes, então você irá saber os patterns necessários a serem empregados. Levando em conta que você quer fazer da maneira correta. Adicionar estruturas antecipadas é provavelmente melhor se estiver nesta condição, do que se você fosse novato com o problema. Então meu conselho seria este, se você sabe como lidar com isto, então esta em posição de julgar os custos de se fazer isto agora ou depois. Entretanto se você nunca fez isto antes, você não só estará incapacitado para mensurar o esforço necessário como também estará incapaz de fazer da maneira correta. Que neste caso o correto é postergar esta atividade. Se você iniciar esta atividade, e achar difícil, então provavelmente será melhor do que ter feito anteriormente. Seu time estará mais experiente, você conhecerá melhor o domínio, e terá um maior entendimento dos requisitos. Geralmente, nesta posição você olha para trás e vê o quanto fácil poderia ter sido com retrospectivas 20/20. E poderia ter sido muito mais difícil de executar previamente do que se imagina.

Isto também esta vinculado com a questão sobre a ordem das estórias. Em um Planejamento XP, Kent e eu mostramos abertamente nosso desentendimento. Kent é a favor de deixar o valor do negócio ser o único fator que guia a ordem das estórias. Após um desacordo inicial com Ron Jeffries agora concordamos neste ponto. Eu ainda tenho minhas dúvidas. Acredito que é um balanceamento entre o valor do negócio e o risco técnico. O que poderia me levar a aplicar um pouco de internacionalização antes para mitigar este risco. Contudo isto seria somente verdade se a internacionalização fosse necessária no primeiro release. Chegar a um release o mais rápido possível é de suma importância. Qualquer complexidade adicional vale a pena fazer após a primeira entrega se isto não for necessário para o primeiro release. O poder da entrega, do código rodando é enorme. Foca a atenção do cliente, aumenta a credibilidade, e é uma fonte massiva de aprendizado. Faça o que for preciso para trazer esta data o mais próximo possível. Mesmo que haja esforço maior para adicionar algo após o primeiro release, é melhor lançar antes.

Como qualquer técnica nova, é natural que suas idéias sejam incertas sobre os limites de suas condições. A maioria dos XPerts tem dito que o design evolucionário é impossível para certos problemas, somente para descobrir depois que é possível. A conquista de situações 'impossíveis' leva a confiança de que qualquer situação pode ser contornada. Claro que você não pode generalizar, mas até que a comunidade XP chegue ao limite e falhe, nós nunca teremos certeza onde podemos chegar, e é correto tentar e ultrapassar as potenciais fronteiras que os outros possam enxergar.

(Um artigo recente de Jim Shore discute algumas situações, incluindo internacionalização, onde as fronteiras em potencial no final das contas acabaram não sendo consideradas barreiras.)

Voltar ao topo

Design está Acontecendo?

Uma das dificuldades do planejamento evolucionário é constatar se ele está acontecendo de fato. O perigo é que o desenvolvimento pode acontecer sem ele - esta é a situação onde o planejamento evolucionário diverge e falha.

Se você está em uma equipe de desenvolvimento, então conseguirá sentir quando o planejamento está acontecendo ao avaliar a qualidade do código fonte. Caso este esteja se tornando complexo, então a análise não está sendo feita adequadamente. Infelizmente, isto é subjetivo. Não temos métricas confiáveis para avaliar, de modo objetivo, a qualidade da análise.

Se esta falta de visibilidade é um problema sério para o pessoal da área técnica, é ainda mais alarmante para os que não são. Se você é um gerente, ou um cliente, como saberá se a análise do software está sendo bem feita? Isto é um problema por quê análise mau feita tornará os custos de manutenção mais altos no futuro. Não existe uma resposta fácil para a questão, mas aqui estão algumas sugestões:

  • Ouça a área técnica. Se estiverem reclamando da dificuldade em implementar mudanças, leve-os a sério e dê-lhes tempo para os devidos consertos.
  • Preste atenção na quantidade de código que está sendo descartada. Um projeto que refatora de modo saudável irá descartar código ruim de modo contínuo. Caso não haja código sendo apagado, é um sinal quase certo de que o refactoring não está acontecendo - o que conduz há uma degradação da análise. Entretanto, como qualquer outra métrica, abusos podem ocorrer, a opinião de um bom técnico suplanta qualquer medição, por mais subjetiva que seja.

Voltar ao topo

Então a Análise está Morta?

Não exatamente, mas sua natureza mudou. Análise XP busca pelas seguintes habilidades

  • Constante desejo de manter o código o mais claro e simples possível.
  • Habilidades com refactoring, assim poderá implementar melhorias quando ver a necessidade.
  • Bom domínio dos patterns: não bastando conhecer as soluções, mas saber quando utilizá-las e como alcançá-las.
  • O design com um olho para mudanças do futuro, sabendo que decisões tomadas agora terão que ser mudadas no futuro.
  • Saber como transmitir os resultados da análise para as pessoas que precisam compreendê-lo, usando código, diagramas e acima de tudo: conversa.

Esta é uma seleção assustadora de habilidades, mas ser um bom analista sempre foi tarefa árdua. De fato, XP não torna as coisas mais fáceis, pelo menos não pra mim. Mas penso que ele oferece uma nova maneira de pensar sobre a eficiência da análise por que torna o planejamento evolucionário uma estratégia plausível novamente. E sou um grande fã da evolução - afinal, quem saberia o que eu poderia ser?

Voltar ao topo

Agradecimentos

Nos últimos anos escolhi e roubei muitas boas ideias de muitas pessoas boas. Muitas delas estão perdidas na obscuridade da minha memória. Mas lembro de ter afanado boas ideias de Joshua Kerievsky. Também me recordo de vários, e prestativos, comentários de Fred George e Ron Jeffries. Não posso esquecer das boas ideias que continuam vindo de Ward e Kent.

Serei sempre agradecido por aqueles que questionam e corrigem nossa tipografia. Tenho sido relaxado sobre manter uma lista de agradecimentos, mas eles incluem Cragi Jones, Nigel Thorne, Sven Gorts, Hilary Nelson e Terry Camerlengo.

Tradutores

A InfoQ Brasil agradece à todos os editores que participam ativamente da tradução de notícias e artigos do InfoQ Brasil, nesse artigo em especial: Samuel Carrijo, Carlos Mendonça, Ricardo Yasuda, Acyr Tedeschi, Wagner Santos, Vinicius Assef, Rafael Riberto, Marcelo Marques e Flávia Oliveira. Obrigada à todos!

Voltar ao topo

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT