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...

Nenhum comentário:

Postar um comentário