Onde a refatoração e a otimização de código se encaixam tanto na linha do tempo do processo ágil quanto na cascata?

10

Parece haver essa noção entre a equipe de gerenciamento de projetos de que "funciona" significa que deve ser considerado 100% completo. A maioria dos programadores sabe que nem sempre é o caso. Se estou tentando abordagens alternativas para que uma parte da funcionalidade funcione, isso não significa necessariamente que encontrei a melhor solução, ou não será necessário retrabalho após a revisão com outros desenvolvedores. Costumo terminar alguma coisa, dar um passo atrás e depois me perguntar o que posso fazer melhor depois que as regras de negócios forem satisfeitas. Esse tempo de "eu posso fazer melhor" deve se encaixar em algum lugar da linha do tempo? Sou da opinião de que a melhor abordagem é que você sempre deixa o código melhor do que quando o encontrou (até certo ponto), o que pode significar refatoração pós-lançamento. Contudo,


fonte

Respostas:

13

Há um princípio abrangente que governa a necessidade de refatorar e otimizar, tanto em cascata quanto em Agile: YAGNI (você não precisa disso). Um segundo princípio é o corolário do primeiro: "A otimização prematura é a raiz de todo mal", o equivalente de codificação do provérbio geral "o inimigo da excelência é a perfeição".

Vamos pegar os princípios e aplicá-los. Você tem o requisito de criar um algoritmo ETL que pegue um arquivo de um tipo específico, extraia suas informações e as coloque em um banco de dados. Seu objetivo para esta semana (para nossos propósitos, não importa se você está em uma loja Agile ou SDLC) é fazer isso.

Você é um sujeito esperto e teve uma visão geral da situação. Você sabe que esse não é o único tipo de arquivo para o qual o projeto precisará de um ETL. Portanto, considere implementar esse algoritmo ETL para também trabalhar em outro tipo de arquivo, que possui apenas pequenas diferenças. Fazer isso violaria YAGNI. Seu trabalho não é desenvolver o algoritmo para esse outro arquivo; é desenvolver o algoritmo para o único arquivo necessário até o final da semana. Para atingir esse objetivo e passar nos testes de aceitação, você precisa desenvolver esse algoritmo e fazê-lo funcionar corretamente. Você "não precisará" do código adicional para fazê-lo funcionar com o outro arquivo. Você pode pensar que economizará tempo para incorporá-lo agora e pode estar certo, mas também pode estar terrivelmente errado; o algoritmo do outro arquivo pode precisar ser usado em uma área do sistema em que seu código não pode ser usado ou os requisitos para o novo arquivo podem ser diferentes dos do seu, de maneiras que você não conhece (no Agile, esses requisitos ainda não existem). Enquanto isso, você perde tempo e aumenta desnecessariamente a complexidade do seu algoritmo.

Agora, é na próxima semana e, como uma recompensa duvidosa por seu excelente trabalho no primeiro algoritmo, você recebeu a tarefa de criar os algoritmos para dois novos tipos de arquivos. Agora, você precisa de código adicional para fazer seu algoritmo funcionar com mais arquivos. Você pode estender seu algoritmo existente usando um padrão de método de modelo que usará um padrão básico com etapas individuais específicas de arquivo ou simplesmente derivar uma interface comum do algoritmo existente, desenvolver duas novas que seguem a interface e conectá-las ao um objeto que pode escolher qual algoritmo usar.

Durante o desenvolvimento, você sabe que é necessário que o sistema processe 10 KB de dados brutos por segundo. Você faz um teste de carga e acha que seu algoritmo de rascunho inicial lida com 8 KB / s. Bem, isso não vai passar nos AATs. Dê uma olhada e veja que existe alguma estrutura de loop de complexidade O (meu Deus) em seu algoritmo; você simplifica e obtém 12 KB / s. "Muito bom", você pensa, "mas se eu tivesse um loop tão ruim no código, o que mais eu poderia cortar?". buzz Você acabou de violar a regra "otimização prematura". Seu código funciona e passa todos os requisitos. Você está "pronto", até que os requisitos sejam atualizados para exigir 15 KB / s. Se e quando isso acontecer, ENTÃO você recupera o código e procura coisas para melhorar.

Siga esse processo simples durante o desenvolvimento, seja no Agile ou nos SDLCs tradicionais: "Na primeira passagem, faça-o funcionar. Na segunda passagem, faça-o bonito. Na terceira passagem, faça-o SOLID". O que isso significa é que, quando você cria uma linha de código pela primeira vez, faça com que ele funcione corretamente e sem erros, mas não preste muita atenção nas regras de design desse código, pois tudo o que você sabe agora é que você ' Nunca mais tocarei nessa área. Na próxima vez em que você visitar essa linha de código, você apenas estará errado; não é mais uma parte única do sistema. Refatore para legibilidade, concisão de código e / ou princípios DRY (você pode ter copiado e colado algum código para fazer algo cinco vezes; refatorado para um loop e / ou uma chamada de método). Na terceira vez em que você trabalha nessa linha de código,

KeithS
fonte
3
+1, O(my God)-complexityse nada mais, me fez rir!
Joel C
1 para começar a trabalhar primeiro. Muitas pessoas tentam escrever padrões e otimizar prematuramente.
Justin Escudo
Acho que esse é um dos problemas mais difíceis de superar como programador. Os engenheiros têm um desejo inato de experimentar, desenvolver e refinar, mas no final do dia, você está sendo pago pela produtividade. Qual a qualidade de um produto perfeito se você gastar tanto tempo e / ou dinheiro que é cancelado devido a excedentes?
ToddR
Eu gosto da abordagem pragmática, mas tenho um problema com "Na segunda passagem, faça bonito": se a segunda passagem for um ano depois e você não tiver certeza de que os nomes de variáveis ​​e métodos são significativos e os números mágicos foram substituídos por constantes simbólicas você provavelmente tem problemas para entender o código. Como lidar com isso? "Torná-lo bonito" 1 hora depois de "fazê-lo funcionar" é muito mais barato do que "torná-lo bonito" depois de um mês ou depois de um ano. Concordo que "torná-lo bonito" quando a próxima alteração de código for necessária é útil se "torná-lo bonito" não tiver sido feito em primeiro lugar.
k3b
No Agile / TDD, é minha experiência que a segunda passagem geralmente acontece logo após a primeira. Nos SLDCs da Cachoeira, você está mais certo; a função tende a ser escrita uma vez e fica lá até que a próxima rodada de requisitos apareça nesse método. Portanto, algumas boas práticas de codificação precisam acontecer da primeira vez, como o código de auto-documentação, para que, quando você voltar um ano depois, possa se lembrar do que o código faz e por que você o escreveu dessa maneira.
Keiths
10

se funciona e foi testado, por que corrigi-lo?

Isso pode ser contrário ao seu próprio temperamento pessoal como engenheiro / programador, mas se estiver funcionando, que valor comercial há para você continuar refinando? Facilitará a manutenção ao longo do tempo? Nesse caso, trabalhando com a metodologia ágil, você poderá criar novos itens em sua lista de pendências para refinar e refatorar o código existente, e esses serão priorizados com os outros itens da lista de pendências. Isso faz parte do valor do processo ágil: a equipe decide em conjunto o que é mais importante e o que é feito a seguir.

Nossa equipe também rastreia o que chamamos de "dívida técnica"; portanto, se você conseguir algo funcionando, mas souber que isso poderia ser feito melhor, registre-a como dívida técnica. Usamos o scrum e, às vezes, você conclui todo o trabalho em um sprint mais cedo (você deve terminar um pouco mais ou menos na metade do tempo, se estiver bem próximo das estimativas), mas não terá tempo suficiente para obter uma solução completamente nova história do usuário, para que gastemos o tempo extra voltando e diminuindo nossa dívida técnica. Não é rastreado formalmente como nossas histórias de usuários em nossa lista de pendências, e podemos trabalhar nisso sempre que tivermos tempo disponível.

Também é mais ou menos um julgamento de sua parte quando você chama a tarefa de "concluída"; se você não se sentir confortável com o estado em que seu código está, não marque a tarefa como concluída.

Joel C
fonte
2
Tornei-me fã do conceito de "dívida técnica", +1 por abordá-lo neste contexto.
Patrick Hughes
Esqueci completamente a idéia de "dívida técnica"; bom termo. Mas fui ensinado que qualquer coisa que se qualificasse como "dívida técnica", significando que exigiria ciclos significativos de desenvolvedores para refatorar, deveria ser evitada; "faça leve" ainda significava "faça certo", apenas não use "torre de marfim" no código que pode ser único.
21411 KeithS
5

Esse tempo de "eu posso fazer melhor" deve se encaixar em algum lugar da linha do tempo?

Sim.

Pouco antes de começar a codificar o próximo versão.

Não refatorar com base na "intuição".

Refatorar com base nas histórias reais do próximo sprint.

S.Lott
fonte
2

Não marque o código como 100% completo até estar satisfeito com a refatoração. Você só precisa avaliar constantemente o custo / benefício para refatorar o código, porque se você estudar o suficiente, sempre verá maneiras de melhorar o código.

Eu uso o método refatorador verde vermelho do TDD. Portanto, minha refatoração está incorporada no meu desenvolvimento. Para grandes refatorações, como alterar o modelo subjacente ou algo semelhante, eu recomendaria que a gerência passasse o tempo primeiro.

mpenrow
fonte
11
O código não está "100% completo" até que todos os produtos nos quais ele reside estejam mortos. Bem como você não é "completo" como pessoa até que seu coração pare de bater permanentemente; você sempre absorverá novas informações e precisará fazer coisas específicas que nunca fez antes, ou fazer a mesma coisa de uma maneira nova, mais eficiente ou menos dispendiosa. Da mesma forma, sua base de código SEMPRE precisará de trabalho - novos recursos e correções antigas - até que ninguém mais use o software.
12111 KeithS
2

a "refatoração pós-lançamento" tem um custo oculto nos testes de regressão e no tempo de controle de qualidade que você está ignorando, além de ter o custo de oportunidade de não trabalhar nos bugs relatados e nos recursos e alterações novos / solicitados. TANSTAAFL

Se vale a pena fazer, vale a pena fazer uma tarefa para ser priorizada através do seu processo normal e não como uma exceção especial. Você faz parte de uma equipe, afinal, e trabalhar em objetivos comuns e estender arbitrariamente sua programação para acomodar a fixação do código de trabalho também os afeta.

Portanto, para uma resposta real: se você sabe que deseja refatorar, programe esse horário como parte da tarefa. Se você estiver fazendo scrum / ágil, crie uma caixa de tempo com uma tarefa de limpeza. Se você é uma cascata / espiral, faça o refator parte do processo para codificar a revisão e aceitar os módulos.

Patrick Hughes
fonte
0

Se estou tentando abordagens alternativas para que uma parte da funcionalidade funcione, isso não significa necessariamente que encontrei a melhor solução,

... Nesse caso, você ainda não está 100% pronto ...

ou não será necessário retrabalho após a revisão com outros desenvolvedores.

Se as revisões de código e o retrabalho subsequente fizerem parte do seu ciclo de vida de desenvolvimento, novamente o recurso não será concluído até que todos eles estejam concluídos.

Costumo terminar alguma coisa, dar um passo atrás e depois me perguntar o que posso fazer melhor depois que as regras de negócios forem satisfeitas. Esse tempo de "eu posso fazer melhor" deve se encaixar em algum lugar da linha do tempo?

Depende. Se isso significa refatoração, deve fazer parte da tarefa de desenvolvimento original. Se isso significa experimentar um algoritmo potencialmente melhor, pode ser uma tarefa separada.

Sou da opinião de que a melhor abordagem é que você sempre deixa o código melhor do que quando o encontrou (até certo ponto), o que pode significar refatoração pós-lançamento. No entanto, as equipes de projeto geralmente ficam extremamente desconfortáveis ​​com essa abordagem porque, novamente, se ela funciona e foi testada, por que corrigi-la?

Em resumo, porque o código pode ser quebrado em vários níveis.

É uma coisa que funciona agora. É totalmente diferente se é limpo, extensível e sustentável a longo prazo.

Para respostas mais detalhadas, consulte este tópico .

Péter Török
fonte
0

Tanto quanto eu posso ver e ler, esta é uma pergunta instável. Portanto, a evasão responde como "YAGNI" e respostas do tipo faça-o-certo na primeira vez. O fato é que não há um lugar no Agile para refatoração - mas eu diria que deveria haver.

A melhor resposta até agora menciona dívida técnica. Infelizmente, essa é uma triste realidade do software em muitas empresas, onde a pressa de fazer as coisas acontecerem em uma metodologia ágil ou não-ágil é muito comum - mas, sob a Agile, as soluções rápidas e sujas são racionalizados como algo bom: "atende aos requisitos mínimos de negócios" e "YAGNI" (no que diz respeito a manter o código limpo).

Seria ótimo se todos fizessem TDD e seria ótimo se todos os desenvolvedores refatorassem a segunda ou a terceira vez, conforme sugerido por uma resposta. Mas isso simplesmente não acontece no mundo real. Quase sempre se descobre que os desenvolvedores de níveis de habilidade variados cortam os cantos na busca de soluções rápidas. Como resultado, o código se decompõe em montanhas de código não sustentável, que leva os novos dias dos desenvolvedores apenas para decifrar, o que prejudica a produtividade e atrasa os prazos. Por "impossível de manter", quero dizer soluções de copiar e colar, 5000 classes de linha etc. E todo esse código e essas correções nas correções são essenciais para os negócios! - Nesses casos de soluções aditivas, eu diria, não existe YAGNI! Você precisará de um código limpo - SEMPRE. Se o código não estiver limpo, você definitivamente não precisará dele - vê a profecia auto-realizável? Os desenvolvedores se esforçam ao máximo para não usar esse código, porque é muito doloroso de se olhar. E o ciclo vicioso continua e continua até que toda a grande bola de barro precise ser jogada e reescrita.

Então eu digo - apesar de a refatoração de código não ser um conceito ágil apropriado, distinto e digno de ser uma história - devemos dedicar tempo para refatorar. Algumas lojas agora exigem que as equipes gastem 20% de seus sprints em dívidas técnicas. Felizmente, os proponentes ágeis mudarão de idéia sobre YAGNI e criarão um lugar para refatoração como uma atividade separada no tempo. E se eles já ouviram falar e não ouvi falar, por favor, aponte para onde está descrito, porque estou muito interessado em saber.

blindcodifier9734
fonte
"O fato é que não há um lugar no Agile para refatoração" - não acho que seja uma afirmação verdadeira. No ágil, há um lugar para qualquer tipo de desenvolvimento, incluindo refatoração, desde que exista um argumento comercial para isso. Se não há um caso comercial para isso, por que você está fazendo isso?
Bryan Oakley
Eu acho que você tem razão, se é um pouco simplista. Em teoria, um desenvolvedor pode fabricar um caso de negócios para corrigir códigos de má qualidade, mesmo que não produza alterações funcionais, mas isso não se encaixa no espírito de agilidade - usar os negócios como proxy para justificar o trabalho. Eu argumentaria então que a atividade de refatoração está fora do domínio do agile - um tipo de atividade do CYA, se você quiser - fixando código não sustentável, para que não custe os negócios a longo prazo e que os desenvolvedores sejam responsabilizados. Chame de "sprint de refatoração" ou qualquer outra coisa, mas deve haver um lugar formal para isso.
precisa saber é o seguinte