13 outubro 2008

Design planejado e evolucionário

Então, continuando a série...

Nesse artigo vou descrever dois estilos como design é feito em desenvolvimento de software. Talvez o mais comum seja design evolucionário. Essencialmente design evolucionário significa que o design do sistema cresce à medida em que o sistema é implementado. Design é parte do processo de programação e à medida em que o programa evolui o design muda.

Em seu uso comum, design evolucionário é um desastre. O design acaba virando a agregação de um monte de decisões táticas ad-hoc, onde cada uma delas torna o código mais difícil de alterar. Em muitos sentidos, você poderia argumentar que isso é ausência de design, é claro que normalmente isso leva a um design pobre. Como Kent costuma dizer, o design existe para possibilitar que você continue mudando o software facilmente no longo prazo. Quando o design deteriora, vai junto sua habilidade de fazer mudanças efetivamente. Chega-se ao estado de entropia de software, ao longo do tempo o design torna-se pior e pior. Isso não apenas torna o software mais difícil de mudar, mas também torna os bugs mais fáceis de se reproduzirem e mais difíceis de achar e matar de forma segura. Esse é o pessadelo do "code and fix", onde os bugs se tornam exponencialmente mais caros de corrigir à medida em que o projeto evolui.


Design planejado é um remédio para isso, e contém uma noção nascida em outros ramos da engenharia. Se você quer construir uma casinha de cachorro, basta pegar um pouco de madeira e construir uma forma rude. Todavia, se você quer construir um arranhacéus, você não pode trabalhar assim - ele vai simplesmente desabar antes que se chegue na metade. Então você começa com desenhos de engenharia, feito em um escritório de engenharia como aquel em que minha esposa trabalha no centro de Boston. Enquanto ela faz o design ela considera todos os detalhes, parcialmente por meio de análises matemáticas, mas principalmente usando códigos de construção. Códigos de construção são regras sobre como desenhar estruturas baseado em experiência do que funciona (e alguma matemática subjacente). Uma vez que o design está pronto, então a companhia de engenharia dela pode passar o design para outra empresa construir.

Design planejado em software deveria funcionar da mesma forma. Designers pensam as grandes questões antecipadamente. Eles não precisam escrever software porque não estão construindo o software, eles estão projetando. Então eles podem usar técnicas de design como UML que deixam de fora alguns detalhes de programação e permitem que os designers trabalhem em um nível mais abstrato. Uma vez pronto o design, eles podem passá-lo para um outro grupo (ou até outra empresa) para construir. Já que os designers estão pensando em larga escala, eles podem evitar toda a série de decisões táticas que levam à entropia de software. Os programadores podem seguir as diretrizes do design e, uma vez que sigam o design, chegar a um sistema bem feito.

Então a abordagem do design planejado vem sendo usada desde a década de 70, e um monte de gente a usou. Ela é melhor em muitos sentidos que o design evolucionário "code and fix". Mas ela tem algumas falhas. A primeira é que é impossível pensar em todos os detalhes com que se precisa lidar na hora de programar. Então é inevitável que na hora de programar você encontre coisas que questionem o design. Entretanto, se os designers já tiverem terminado e se engajado em outro projeto, o que acontece? Os programadores começam a codificar por fora do design e a entropia se estabelece. Mesmo se o designer não tiver ido embora, leva tempo para organizar as questões de design, e então mudar o código. Normalmente faz-se um conserto mais rápido pela pressão. Entropia (de novo).

Ademais, há normalmente um problema cultural. Designers se fazem designers pela habilidade e experiência, mas eles estão tão ocupados trabalhando nos designs que não têm mais tanto tempo para codificar. No entanto, as ferramentas e materiais de desenvolvimento de software mudam rapidamente. Quando você não programa mais, não apenas fica defasado com o fluxo tecnológico, mas também perde o respeito daqueles que programam.

Essa tensão entre os construtores e designers acontece na construção civil também, mas é mais intensa em software. Isso porque existe uma diferença chave. Em construção civil existe uma divisão clara entre aqueles que projetam e aqueles que constróem, mas em software não é bem assim. Qualquer programador trabalhando em ambientes de alto design precisam ser muito habilidosos. O bstante para questionar as decisões de design, especialmente quando o designer conhece menos sobre a realidade do dia a dia e a plataforma de desenvolvimento.

Agora veja, esses problemas podem ser corrigidos. Talvez consigamos lidar com a tensão humana. Talvez consigamos designers habilidosos o bastante para lidar com a maioria dos problemas e tenhamos um processo disciplinado o suficiente para mudar os desenhos. Há ainda outro problema: mudanças de requisitos. Mudanças de requisitos são a causa número das enxaquecas nos projetos de software.


Uma forma de lidar com mudanças de requisitos é embutir flexibilidade no design de modo que se possa mudá-lo facilmente à medida que os requisitos mudam. No entanto isso requer insight sobre que tipos de mudanças se espera. Um design pode ser planejado para lidaar com áreas de volatilidade, mas enquanto isso pode ajudar para as mudanças previstas, não pode ajudar (e pode atrapalhar) as mudanças imprevistas. Então é preciso entender os requisitos suficientemente bem para separar as áreas voláteis, e a minha experiência é que isso é muito difícil.


Alguns desses problemas de requisitos são causados por não entender os requisitos de forma clara o suficiente. Então um monte de gente se foca em processos de engenharia de requisitos para obter requisitos melhores, na esperança que isso previna a necessidade de mudar o design depois. Mas até esse caminho pode não levar a uma cura. Muitas mudanças de requisitos imprevistas ocorrem devido a mudanças no negócio. Essa não podem ser evitada, por mais cuidadoso que seja o seu processo de engenharia de requisitos.

Tudo isso portanto faz o design planejado parecer impossível. Certamente esses são grandes desafios. Mas não estou convencido de que o design planejado é pior que o design evolucionário, da forma como é normalmente praticado de maneira "code and fix". Então eu prefiro design planejado a "code and fix". No entanto, estou ciente dos problemas do design planejado e estou procurando um novo caminho.

continua...

05 outubro 2008

O design está morto?

Começo com esse post a tradução de um dos melhores artigos que conheço a respeito de design ágil de software: "Is design dead?" do Martin Fowler.

Vou traduzir o texto em vários posts, para preservar um pouco do meu tempo, e pra adaptar o discurso longo a um formato mais curto, mais apropriado ao blog.

Para os que já conhecem, é uma ótima oportunidade para recordar. Pra quem nunca leu, meu conselho é que corra logo e leia a versão em inglês no blog do autor
(que com certeza é bem melhor que a minha tradução).

Mas se ainda não mexi com sua curiosidade o bastante para vencer a preguiça, acompanhe a série de posts que farei aqui, ou espere até o final da tradução e confira o texto completo, que será publicado junto às outras traduções.


Se por acaso alguém achar que a tradução não ficou boa, e quiser deixar alguma sugestão, será muito bem vinda nos comentários.

Vamos à seção que introduz o artigo, apresentando sua questão central.

(apenas a titulo de registro, estou traduzindo a versão de maio de 2004)

Para muitos que têm seu primeiro contato com Extreme Programming, parece que XP prevê a morte do design de software. Não somente a maioria das atividades de design é ridicularizada como "Big Design Up Front", mas ainda técnicas como UML, frameworks flexíveis, e até mesmo design patterns são pouco enfatizadas ou totalmente ignoradas. Na verdade XP envolve muito design, mas o faz de um modo diferente dos processos de software estabelecidos. XP rejuveneceu a noção de design evolutivo com práticas que tornam a evolução uma estratégia de design viável. Ela também apresenta novos desafios e habilidades já que os designers precisam aprender como fazer um design simples, como usar refactoring para manter um design limpo, e com usar patterns em um estilo evolucionário.

(Esse artigo foi escrito para minha apresentação na conferência XP 2000 e sua forma original foi publicada como parte dos anais.)

* Design planejado e evolucionário
* As práticas habilitadoras de XP
* O valor da simplicidade
* O que diabos é simplicidade, afinal
* Refatoração viola YAGNI?
* Patterns e XP
* Cultivando uma arquitetura
* UML e XP
* Sobre metáforas
* Você quer ser um arquiteto quando crescer?
* Reversibilidade
* A vontade de projetar
* Coisas que são difíceis de refatorar
* O design está ocorrendo?
* Então o design morreu?
* Créditos
* Histórico de revisões

Extreme Programming (XP) desafia muitas das suposições sobre desenvolvimento de software. Uma das mais controvérsas é sua rejeição a esforços significativos em design prévio, em favor de uma abordagem mais evolucionária. Para seus criticos isso é um retorno ao desenvolvimento "code and fix" - normalmente conhecido como hackear. Para seus fãs é frequentemente visto como uma rejeição das técnicas de design (como a UML), princípios e padrões. Não se preocupe com design, se você escutar o seu código um bom design surgirá.

Eu me encontro no centro desse argumento. Grande parte da minha carreira envolveu linguagens gráficas de design - a linguagem de modelagem unificada (UML) e seus precursores - e padrões de projeto. Eu escrevi livros sobre ambos: UML e patterns. O meu envolvimento com XP significa minha renúncia ao que escrevi sobre esses assuntos, livrando minha mente de todos esses conceitos contra-revolucionários?

Bem, não vou conseguir mantê-los nesse suspense. A resposta curta é não. A resposta longa é o resto desse artigo.

A resposta longa será publicada aqui, seção por seção.

Continue lendo a segunda parte: Design planejado e evolucionário