segunda-feira, 26 de abril de 2010

Design Ágil

INTRODUÇÃO
Como desenvolvedor, sempre fui fascinado por design de software. Comumente definida como a atividade de especificar os componentes de software (classes) e suas interações, considero a tarefa desafiadora e bastante interessante. Quando comecei a entrar em contato com princípios de desenvolvimento ágil (em especial SCRUM e XP), percebi que havia uma grande incompatibilidade entre o que aprendi na faculdade (e acreditava ser a forma correta de fazer design) e o que pregam as metodologias.

UP FRONT DESIGN
Aprendi na faculdade que design é fase da engenharia de software que faz a ponte entre a especificação de requisitos e a construção propriamente dita. O analista decide O QUE fazer, o projetista decide COMO fazer e o programador FAZ. O produto da fase de design são documentos e diagramas que o desenvolvedor irá usar para construir o software que o analista idealizou. Esta abordagem hoje é chamada de up front design e sem dúvida não é livre de seus problemas e desafios:

  • É muito difícil (senão impossível) criar antecipadamente um design tal que atenda todos os requisitos (funcionais e não-funcionais) e esteja livre de falhas.
  • Seria necessário criar um design que fosse flexível suficiente para acomodar as temíveis mudanças de requisitos. Mesmo que seja possível, qual seria o custo em complexidade de um design assim?

No SCRUM não há fase de design. Há uma reunião onde o product owner explica para o time em detalhes as características de cada item do sprint backlog e a partir daí analistas começam a documentar, testers especificam casos de testes e programadores começam a desenvolver. Simples assim. Não tem design? Não da forma como aprendi na faculdade.

EVOLUTIONARY DESIGN
Se não é possível gerar um design que atenda a todos os requisitos, seja livre de falhas e se não é possível evitar mudanças de requisitos, o que justifica o esforço (geralmente grande devido a natureza complexa da atividade) despendido na criação de um up front design? Entendendo que codificar é projetar as metodologias ágeis propõem algo chamado evolutionary design.

Nesta abordagem, o design e codificação andam lado a lado. O design evolui de acordo com as necessidades das funcionalidades sendo construídas. Não há o papel formal de projetista nem um momento específico para desenvolver o design: Todos os desenvolvedores fazem e refazem o design todos os dias.

YAGNI
Um dos conceitos mais intrigantes relacionados a evolutionary design é conhecido pela sigla YAGNI (You Aren't Gonna Need It). “Sempre escreva apenas o código que você precisa agora, nunca o que você vai precisar amanhã” Mesmo que você tenha absoluta certeza de que vai precisar daquele trecho de código e que o custo de escreve-lo seja zero: Deixe para fazê-lo quando for necessário.

YAGNI é contra-intuitivo porque vai contra aquilo que acredita-se ser maior benefício de um um bom design: antecipação de complexidade e consequente redução de riscos. Entretanto, existem bons argumentos em favor desta abordagem:

  • Respeito ao ROI do cliente: Escrever código que não agrega valor a funcionalidade em construção é desrespeitar a priorização do product owner e consecutivamente o ROI do cliente.
  • Economia de tempo: O tempo usado para escrever código que só será usado posteriormente pode fazer falta na hora de entregar as funcionalidades previstas para esta iteração.
  • Possíveis mudanças: Escrever código antecipadamente é um risco (desnecessário) porque o entendimento pode ter sido equivocado ou a lógica/regra pode mudar, gerando a necessidade de reescrever o código.  

FAZENDO EVOLUTIONARY DESIGN FUNCIONAR
Neste ponto, o leitor já deve ter percebido que um projeto que usar evolutionary design corre grandes riscos de acabar mesmo é sem design, ou com um design muito pobre.

Críticos acusam evolutionary design de ser super-dependente da maturidade do time, o que tem um fundo de verdade. Neste sentido, o XP define o papel do Coach, que seria um desenvolvedor mais experiente com a responsabilidade de orientar o time nas decisões técnicas (inclusive de design).

Além disso, existe uma série de práticas, do próprio mundo ágil ou não, que acredito devam ser empregadas criteriosamente de forma a manter a qualidade do design:
  • Ênfase em testes (unitários, de integração, etc..): É importante ter uma boa margem de segurança quando são feitas mudanças de design.
  • Integração contínua: Integrar o código do projeto como um todo (mantendo o time em sincronia) buscando detectar o mais cedo possível possíveis problemas de design.
  • Pair program: Se a funcionalidade for muito complexa, colocar 2 desenvolvedores responsáveis por ela pode ser uma boa ideia.
  • Análise caixa branca: Incluir uma tarefa de inspeção de código a fim de detectar design inadequado (devido ao auto custo, a análise poderia ser feita por amostragem apenas)
  • Lista de boa práticas: Manter uma lista de boas práticas que sirva de orientação aos desenvolvedores. Tal lista seria incrementada ao longo do projeto com a experiência adquirida. 

CONCLUSÕES
O mundo ágil não tem lugar para up front design em sua forma conceitual, como uma fase bem definida e buscando “prever” todas as nuances do desenvolvimento de uma funcionalidade, mas poderia se beneficiar de algumas de suas caraterísticas como redução de riscos e forte padronização.

Evolutionary design é a abordagem alternativa que os métodos ágeis indicam, porém ele deve ser empregada em conjunto com outras práticas que garantam a qualidade do design do software a ser construído.

REFERÊNCIAS
Excelente artigo de Martin Fowler sobre design e XP (http://martinfowler.com/articles/designDead.html)

Artigo sobre problemas de up front design (http://architects.dzone.com/news/great-lies-design-vs)












Nenhum comentário:

Postar um comentário