Arquitetura evolutiva e design emergente: Considerações ambientais para design, Parte 1

Estimando o design emergente e demonstrando a dívida técnica

Mesmo que gostemos da ideia, o design de software não existe fora de contexto. Este artigo sobre Arquitetura evolutiva e design emergente discute como dois fatores ambientais — estimativa e dívida técnica — podem afetar as decisões sobre design e como os designs emergentes podem sobreviver no difícil cenário político em que eles se posicionam.

Neal Ford, Application Architect, ThoughtWorks Inc.

Neal Ford é um arquiteto de software e Meme Wrangler, na ThoughtWorks, uma consultoria global de TI. Projeta e desenvolve aplicativos, materiais de instrução, artigos para revistas, treinamentos e apresentações em vídeo/DVD, e é autor ou editor de livros que abordam uma variedade de tecnologias, inclusive The Productive Programmer Seu enfoque é o projeto e construção de aplicativos corporativos de grande porte. Também é orador internacionalmente aclamado nas conferências de desenvolvedores ao redor do mundo. Conheça seu Web site.



23/Nov/2010

Sobre esta série

Esta série 5 coisas visa fornecer uma perspectiva atual sobre os conceitos sempre discutidos, mas difíceis de compreender, de arquitetura e design de software. Por meio de exemplos concretos, Neal Ford fornece uma base sólida nas práticas ágeis da arquitetura evolutiva edesign emergente. Ao adiar importantes decisões de arquitetura e design até o último instante, é possível evitar uma complexidade desnecessária com base em questionamentos de seus projetos de software.

Como alguns dos meus leitores já sabem, esta série de artigos está, de certa forma, relacionada a uma conversa que tenho em minhas conferências. Um tema comum que surge durante o momento de perguntas e respostas na conversa refere-se à adaptação do design ágil em um ecossistema que não tenha tomado a pílula vermelha da agilidade. O número de perguntas sobre esse tema me fez perceber o quanto ele é importante.

Os artigos anteriores nesta série abordaram considerações técnicas sobre design emergente, mas os designs de software não ocorrem fora de contexto. As considerações não técnicas também têm um impacto no design. Uma das perguntas mais comuns sobre o design emergente é "Como você faz uma estimativa para isso?" E uma das confusões mais comuns do design emergente é a dívida técnica — compromissos impostos ao seu design visando alguma força externa, como a pressão do planejamento. Este artigo discute como fazer estimativa para o design emergente e como criar um caso convincente para compensar a dívida técnica.

Estimativa para design emergente

Martin Fowler apresentou uma grande analogia em uma ideia conjunta que eu e ele tivemos no começo do ano sobre por que as práticas ágeis funcionam. Imagine, por um momento, um bolo de frutas e os chuveiros de um hotel. Fowler aparentemente tem uma receita de bolo de frutas formidável. Ele o fez muitas vezes e está seguro de que se medir os ingredientes corretamente e assar o bolo a uma temperatura específica no tempo indicado, ele obterá sempre o mesmo bolo de frutas.

Compare esta experiência com a escolha da temperatura correta de um chuveiro de hotel. Seria insensato e perigoso ajustá-lo do mesmo jeito que você faz na sua casa e entrar embaixo dele. Em vez disso, você o liga e testa a temperatura da água por alguns instantes até que ela se aqueça e depois realiza o mesmo ciclo de ajuste e medição até que esteja adequado.

A diferença entre esses dois tipos de processos ilustra a grande diferença entre os projetos indicados e os obtidos por feedback. Se você tiver cozinhado o mesmo prato muitas vezes anteriormente, poderá seguir uma receita com segurança. Da mesma maneira, a estimativa para um projeto de software será fácil se você puder seguir estes critérios:

  • Você está construindo o exato trecho de software que escreveu antes (mais de uma vez).
  • Você tem exatamente a mesma equipe que foi usada para construí-lo anteriormente.
  • O ambiente é exatamente o mesmo.

Escrever um novo software não é exatamente um processo determinístico. Ele é altamente adaptável, o que sugere que uma abordagem baseada em feedback funciona melhor do que uma abordagem prescritiva. O que nos leva de volta à pergunta original, apenas um pouco reformulada: "Como você faz a estimativa para o esforço de design em um sistema altamente adaptável?"

Estimativas de alta granularidade e flexibilidade

Meu empregador (ThoughtWorks) minimiza a natureza altamente variável de projetos de software de várias maneiras. Primeiro, nós convencemos os clientes que a primeira estimativa que fornecemos não será exata. As estimativas exatas em software são, em determinado momento, impossíveis, porque está sendo solicitado que você forneça um dos detalhes mais variados do projeto no momento em que você menos sabe sobre o projeto. Nós dizemos aos clientes de forma sincera que nossa primeira estimativa será baseada na compreensão dos requisitos de negócios de alta granularidade e da arquitetura técnica. (Para saber mais detalhes sobre esse processo, consulte o texto Iteração 0 ao lado.)

Iteração 0

A ThoughtWorks geralmente inicia novos projetos com uma fase de concepção chamada iteração 0. Durante esse período, que varia de duração dependendo do tamanho do projeto estimado, mas que dura entre duas e oito semanas, ocorrem duas atividades simultâneas:

  • Os analistas de negócios definem os requisitos de alta granularidade, tradicionalmente capturados em fichas (escolhidas especificamente porque não é possível inserir muitos detalhes nelas).
  • Os membros técnicos definem a arquitetura ("a coisa que é difícil de alterar depois", conforme definido no primeiro artigo) e todos os requisitos não funcionais (a propósito, um termo que eu desprezo — eu prefiro muito mais qualidade de serviço) como escalabilidade e desempenho.

No final da fase de concepção, as pessoas de negócios e técnicos se reúnem para medir a complexidade de cada história, vagamente baseada nas técnicas definidas no excelente livro de Mike Cohn User Stories Applied: For Agile Software Development (consulte Recursos ).

Assim que a equipe conclui o processo, ela possui uma estimativa da complexidade total do projeto, que permite a criação de gráficos burn-down e outros dados estatísticos sobre o progresso do projeto. Usando um fator de carregamento, o gerente de projeto converte essa complexidade em tempo, indicando uma estimativa aproximada do tempo que levará.

A estimativa de alta granularidade reflete um entendimento inicial do escopo e do esforço. Entretanto, nós não confiamos nessa estimativa por muito tempo, pois nosso entendimento começa a aumentar logo que começamos a trabalhar. Como o desenvolvimento ágil acontece em iterações razoavelmente curtas, ele permite que os gerentes de projeto reúnam estatísticas reais sobre todos os detalhes diferentes de um projeto: a velocidade real desta equipe neste projeto neste ambiente para este domínio de problema. Como as iterações consistem nas mesmas atividades repetidas, os gerentes de projeto podem reunir dados reais imediatamente. Depois de três ou quatro iterações o gerente de projeto terá ajustado o fator de carregamento (o número usado para converter complexidade em tempo) para refletir a realidade deste projeto. Portanto, geralmente atualizamos nossa estimativa após algumas iterações com números mais precisos. Isso é o melhor que você pode fazer em um ambiente altamente adaptável: fazer suposições fundamentadas e começar a aplicar imediatamente os dados reais à medição (e fornecer feedback) quando tiver concluído.

Como a estimativa inicial apresenta alta granularidade, há um nível considerável de flexibilidade para tratar do design emergente, refatoração e outras atividades de limpeza técnica. A menos que envolvam um aplicativo com design excepcionalmente pesado, os projetos da ThoughWorks não reservam tempo especificamente para essas práticas, da mesma forma que não reservamos tempo para outras práticas comuns, como reuniões.

Uma alternativa para amortizar o tempo de design nas estimativas de projeto é criar pontos de verificação de design em seu planejamento. Isso é especialmente atraente nas organizações que estão mudando de uma metodologia Big Design Up Front que reserva uma quantidade de tempo específica para o design. Se esse tempo já for previsto, use essa mesma quantidade de tempo, não execute logo no início. Em vez disso, inclua alguns marcadores em seu planejamento em momentos específicos (como releases ou um pouco de iterações) para rever decisões de design existentes e executar a próxima rodada de microdesign. Aguardando as decisões de design até o último instante, você terá melhor conhecimento e contexto para o verdadeiro impacto da decisão. Ao reservar a quantidade típica de tempo de design inicial e distribuí-la por todo o projeto, você descobrirá que terá muito tempo para tomar decisões relacionadas ao design.

Outra tarefa para a qual os projetos de software sempre precisam de tempo é a de lidar com a liquidação da dívida técnica. A seguir, vou abordar algumas ferramentas e técnicas que podem ajudar você a expor esse problema a colegas não técnicos.


Liquidando a dívida técnica

Eu abordei os tópicos básicos da dívida técnica — uma ótima metáfora explicada por Ward Cunningham (consulte Recursos ) — no primeiro artigo desta série. A dívida técnica lembra a dívida do cartão de crédito: você não possui fundos suficientes no momento, então obtém emprestado para quitar no futuro. Da mesma maneira, não há tempo suficiente para realizar seu projeto corretamente, então, você cria uma solução razoável e espera em algum momento futuro retornar a ela e aperfeiçoá-la.

Martin Fowler escreveu sobre quatro quadrantes de dívida técnica (consulte Recursos ), conforme ilustrado na Figura 1:

Figura 1. Quadrantes da dívida técnica
Quadrantes da dívida técnica

O primeiro quadrante (precipitado e deliberado) acontece de forma consciente. Isso é ilustrado no desenho clássico que mostra um gerente dizendo a um grupo de desenvolvedores "Comecem a trabalhar, eu vou subir e ver o que eles querem". As empresas com muita dívida desse tipo têm pressa. Elas querem trocar a velocidade cada vez mais decrescente por urgência e entrega. Isso obviamente não é sustentável por longos períodos ou grandes códigos bases. O segundo quadrante (prudente e deliberado) é a manifestação mais comum da dívida técnica. E é o que apresenta menos probabilidade de causar grandes problemas mais tarde, quando você perceber que possui uma dívida e que pode pagá-la. O terceiro quadrante (precipitado e inadvertido) é o mais problemático, pois esses desenvolvedores assumem dívidas sem perceber. Um tipo comum de declaração de um desenvolvedor de um tipo de projeto pode ser: "É realmente conveniente ter todas as 5.000 linhas de código integradas no JSP de modo que você possa rolar para cima e para baixo a fim de verificar onde definiu todas as suas variáveis (globais)".

O quarto quadrante (prudente e inadvertido) parece que não deveria existir — se você é prudente, como pode ser inadvertido? Na verdade, esse é um resultado comum nos projetos que possuem designers especialistas. Mesmo os melhores profissionais de design de software não conseguem antecipar tudo o que um design manifestará e desenvolverá com o passar do tempo. Esse último quadrante é um reflexo do fato de que um dos problemas mais complexos em software (para citar a poesia de Donald Rumsfeld) é que não sabemos o que não sabemos. Ou seja, as coisas mais difíceis de lidar são as coisas as quais ainda não sabemos que representam problemas.

A dívida técnica é uma realidade no cenário de software. Ela nunca acaba, porque a pressão de planejamento sempre existirá como reflexo do fato de que as decisões de negócios podem ser tomadas mais rapidamente do que podemos codificá-las em um software. Não há nada essencialmente ruim na dívida técnica, da mesma forma que não há nada essencialmente ruim na dívida do mundo real. E como as empresas prudentes enfrentam a dívida monetária estrategicamente, o mesmo pode ser feito com o software. O problema não é a dívida, é a negociação do pagamento da dívida. Por experiência própria sei que a demonstração supera a discussão. Se você chegar até seu gerente de projeto e disser: "Eu me sinto mal, não consigo dormir à noite. Acho que nosso código está entrando em decadência", seu gerente se exalta: "Você pode provar isso?" Você pode.A seguir, mostrarei duas ilustrações de dívida técnica: a primeira, feita à mão e a segunda usando uma ferramenta chamada Sonar.

Gerando gráficos de dívida técnica

A primeira ilustração foi obtida de um projeto real da ThoughtWorks para um site de mídia voltado para o público, cujo líder técnico Erik Dörnenburg (consulte Recursos ) é bem conhecido na área de métrica e visualizações de software. Nesse projeto, ele criou um gráfico que mostra a dívida técnica crescente, mostrada na Figura 2:

Figura 2. Gráfico da dívida técnica
Gráfico da dívida técnica

Métricas criadas por você

Dörnenburg produziu o gráfico na Figura 2 com uma combinação inteligente de ferramentas básicas. Para gerar números de complexidade ciclomática, ele usou o JavaNCSS (consulte Recursos ). Dörnenburg escreveu um script que efetua o registro de saída da versão 1 do código a partir do controle de versão, executa o JavaNCSS nele para produzir dados e o salva em um arquivo antigo. O script repete esse processo para cada uma das versões no controle de versão. Quando tiver sido concluído, ele terá um grande número de arquivos XML contendo dados brutos. Em seguida, ele escreveu um pequeno script Ruby para nivelar os dados dos arquivos individuais em um arquivo CSV (comma-separated value) e depois carregou no Excel e o transformou em gráfico. Depois de você ter gerado esse gráfico uma vez, poderá aplicar um curto-circuito no processo mantendo os dados brutos disponíveis para construções prévias, de modo que será necessário apenas atualizar os dados por construção, usando a Integração Contínua

O eixo horizontal do gráfico mostra o intervalo de tempo (1º de abril de 2006 a 18 de agosto de 2007), e o eixo vertical mostra a complexidade ciclomática por linha de código.(Este artigo da série aborda a métrica de complexidade ciclomática em uma discussão sobre teste.) Os números em cinza, acima da parte inferior são os releases do projeto.

O primeiro release em operação pública desse código base aconteceu no release número 3. No gráfico, você pode ver a quantidade e a volatilidade de complexidade que surge até esse ponto — um efeito colateral das pessoas de negócios quase literalmente nos ombros dos desenvolvedores, constantemente perguntando "Ainda não está pronto?" Elas não obterão lucros até que o primeiro release entre em operação, portanto, obviamente elas estão preocupadas.

Assim que o projeto teve sua data de remessa, Dörnenburg criou a primeira parte deste gráfico e o mostrou como evidência de montagem da dívida técnica, em seguida, usou isso para negociar algumas breves liberações de manutenção (versões 3.0 e 3.1) e eliminar alguma dívida. A perseverança desse esforço gerou entusiasmo até o release 7, em que a dívida começou a aumentar novamente (embora de maneira mais controlada) por motivos não relacionados.

Ilustrando a dívida com o Sonar

O gráfico na Figura 2 é ótimo, mas ele requer um pouco de trabalho para autoinicializar o processo. Uma alternativa para escrever seu próprio programa é a ferramenta de software livre Sonar (consulte Recursos ). O Sonar captura várias métricas para seu código base e as mostra em gráficos e em outras visualizações. Os criadores do Sonar o executaram em vários projetos de software livre (acessíveis via instância em execução do Sonar em http://nemo.sonarsource.org/), incluindo o Struts. A figura 3 mostra os resultados do Sonar para o Struts:

Figura 3. Sonar mostrando detalhes sobre o Struts
Sonar mostrando detalhes sobre o Struts

O Sonar mostra a saída de ferramentas de qualidade comum no espaço Java, incluindo o CheckStyle (consulte Recursos ), cobertura de códigos e uma ferramenta de sua própria métrica, Calculadora de Dívida Técnica (mostrada no lado direito). Essa fórmula usa um grupo de números derivados de métricas executadas no código do projeto.

O Sonar parece produzir números incrivelmente elevados prontos para serem aplicados. Por exemplo, ele sugere que seriam necessários 572 homens/hora e $ 280.000 para que o Struts liquidasse a dívida, a qual, na minha opinião, está altamente inflacionada. Você certamente deverá ajustar esses números para seu projeto antes de levá-los ao seu gerente. Se você produzir um relatório informando que serão necessários $ 1,2 milhão para obter seu código sem que ele cause problemas, seu gerente saltará pela janela. Ajuste os números para suportar seu caso no qual é necessário incluir alguns recursos de tempo integral na liquidação do débito.

O Sonar também possui outras visualizações interessantes. Considere o gráfico "Máquina do Tempo" mostrada na Figura 4:

Figura 4. Gráfico Máquina do Tempo do Sonar para Struts
Gráfico Máquina do Tempo do Sonar para Struts

Este gráfico mostra três métricas no decorrer do tempo: cobertura de código, complexidade ciclomática e complexidade ciclomática por método. Como você pode ver no gráfico, algo terrível aconteceu ao Struts próximo a 1 de setembro de 2009. Ele aparentemente incluiu outra estrutura que tinha métricas terríveis, que agora são refletidas no código base do Struts. Compare isso com as mesmas visualizações, mas para o Spring Batch, mostrado na figura 5:

Figura 5. Gráfico de Máquina do Tempo para Spring Batch
Gráfico de Máquina do Tempo para Spring Batch

O gráfico na Figura 5 mostra mais do que você gostaria de ver: cobertura relativamente constante, complexidade constante por método e complexidade geral de crescimento lento quando o software suporta recursos adicionais.

Um dos motivos da metáfora de dívida técnica funcionar tão bem está na similaridade do dinheiro para a dívida monetária com o tempo nos projetos de software. Quando você tem uma dívida e recebe mais dinheiro, parte desse dinheiro deve ser para pagamento de juros da dívida. Nos projetos de software, você lida com o tempo em vez do dinheiro. Quando você tem um novo intervalo de tempo para incluir novos recursos, tem que pagar parte desse tempo com tempo extra que é gasto no engajamento de todos os compromissos de design (e outros). Vale a pena desenvolver o caso para empregar esforço em tempo integral na redução da dívida, porque isso permite que todos trabalhem rápido uma vez que ela tenha sido liquidada. A liquidação da dívida técnica permite que a velocidade de toda equipe aumente.


Conclusão

Neste artigo, comecei abordando os fatores não técnicos que possuem um impacto no design emergente. Discuti como fazer uma estimativa do desconhecido e como ilustrar a dívida técnica. No próximo artigo continuarei neste mesmo caminho de preocupações externas em torno do design emergente, inclusive refatorando e isolando mudanças.

Recursos

Aprender

Obter produtos e tecnologias

  • JavaNCSS: JavaNCSS é uma ferramenta de métrica popular para Java que relata (entre outras coisas) a complexidade ciclomática
  • Sonar: Sonar é um kit de ferramentas de software livre para métricas comuns e visualizações avançadas
  • CheckStyle: CheckStyle é uma ferramenta de análise de código de origem estática de software livre

Discutir

  • Participe da comunidade do My developerWorks. Comunique-se com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=588358
ArticleTitle=Arquitetura evolutiva e design emergente: Considerações ambientais para design, Parte 1
publish-date=11232010