Como lidar com a refatoração que leva mais de um sprint?

49

Eu trabalho com uma base de código com mais de 500 mil linhas de código. É uma necessidade séria de refatoração. Foram identificados esforços de refatoração que levarão mais tempo do que o sprint normal de duas semanas. Eles não podem ser divididos em tarefas menores, como já vi sugerido em outras respostas neste site. O produto precisa funcionar no final da iteração, e a refatoração parcial deixará o sistema em um estado inutilizável, pois a dependência entre os itens é horrível. Então, qual seria a melhor maneira de abordar esse obstáculo? Mais uma vez menciono, dividi-lo em pedaços menores não é uma opção, isso já foi feito.

Atualização: as pessoas parecem precisar de uma explicação de por que isso não pode se encaixar em um sprint de duas semanas. Há mais envolvimento em um sprint do que apenas escrever código. Temos uma política de nenhum código sem testes. Essa política nem sempre existia e uma grande parte da base de código não a possui. Além disso, alguns de nossos testes de integração ainda são manuais. A questão não é que a refatoração em si seja tão grande. É com o fato de que pequenas mudanças afetam muitas partes do sistema e precisamos garantir que essas partes ainda funcionem corretamente.

Não podemos adiar ou estender um sprint porque temos hotfixes mensais. Portanto, essa alteração que se estende além de um sprint não pode impedir que o outro trabalho seja adicionado ao hotfix.

Refatoração versus reprojeto: Só porque nosso processo de desenvolvimento não é eficaz o suficiente para lidar com essa refatoração em um ciclo de duas semanas não garante a renomeação para um reprojeto. Gostaria de acreditar que, no futuro, poderemos realizar exatamente a mesma tarefa dentro de um ciclo de duas semanas, à medida que nosso processo melhorar. O código em questão aqui não teve que mudar há muito tempo e é bastante estável. Agora, conforme a direção da empresa está se tornando mais adaptável à mudança, queremos que essa parte da base de código seja tão adaptável quanto o resto. O que requer refatoração. Com base nas respostas aqui, está se tornando aparente a falta de andaimes necessários para fazer essa refatoração funcionar no período de sprints normais.

Responda:

Vou fazer a abordagem de ramificação e mesclagem sugerida pela Corbin March pela primeira vez, para que possamos aprender mais sobre essas áreas problemáticas e como identificar os testes ausentes. Penso que, seguindo em frente, devemos adotar a abordagem sugerida por Buhb para identificar as áreas que estão faltando nos testes e implementá-las primeiro, depois refatorar. Isso nos permitirá manter nosso ciclo de sprint normal de duas semanas, assim como muitos aqui dizem que sempre deve ser o caso da refatoração.

Charles Lambert
fonte
23
Como observação lateral, isso é por definição um redesenho em larga escala, não uma refatoração . Espero que você não tome isso como picuinhas - IMHO é importante para usar a terminologia clara a problemas de comunicação evitar :-)
Péter Török
9
@Charles, "A refatoração geralmente é feita em pequenas etapas. Após cada pequena etapa, você fica com um sistema funcional que não funciona. " Citado na página que eu link acima.
Péter Török
2
@ Charles: a refatoração sempre pode ser feita de forma incremental, mantendo o sistema funcionando. coloque um grande comentário "Refatoração em andamento" na parte superior da classe / pacote / módulo que está sendo refatorado e faça as partes uma por vez. Se você cortar uma liberação provisória enquanto o modelo de objeto estiver em transição, tudo bem.
Sean McMillan
7
Se você está executando etapas tão grandes que não pode ter um código de trabalho regularmente, essa é a própria definição de quando a refatoração se torna um novo design. Por favor, não fique com raiva das pessoas por ter chamado você de mau uso da palavra. Não há nada errado em perguntar sobre o redesenho. Os comentaristas estão apenas tentando indicar que você não obterá as respostas que deseja, porque está usando mal a palavra, que é o que já aconteceu.
jprete
5
Sei que é um pouco estranho, mas você me deixou curiosa sobre quais são as circunstâncias que impossibilitam a refatoração em pequenos passos. Compartilhe um pouco mais sobre isso.
Buhb

Respostas:

14

Se você tiver o luxo de adiar a refatoração, sugiro focar as próximas iterações na adição de testes de unidade e testes de integração automatizados ao ponto em que você pode refatorar confortavelmente a base de código e refatorar em um único sprint.

Buhb
fonte
68

Minha sugestão:

  1. Crie uma filial
  2. Mesclar diariamente do tronco para o seu ramo e resolver conflitos.
  3. Trabalhe até terminar. Sua filial pode estar fora do núcleo de desenvolvimento para vários sprints.
  4. Volte ao tronco.

Não há como evitar o fato de que provavelmente ficará feio. Eu não te invejo. Na minha experiência, quando você muda drasticamente um projeto, é mais fácil mesclar o desenvolvimento contínuo ao novo paradigma do que, de alguma forma, mesclar o novo paradigma em um tronco agora alterado depois que tudo estiver concluído. Ainda assim, vai doer.

Março de Corbin
fonte
11
Discutimos o uso dessa abordagem e, se nenhuma outra idéia surgir antes de resolvê-la, é isso que planejamos fazer.
Charles Lambert
3
Receio que você tenha muita sobrecarga se mesclando entre o tronco e o galho, se desejar realizar uma refatoração tão completa.
Giorgio
Na maioria dos casos (espero), essas alterações mescladas não afetarão o código em questão aqui. Eu não me importaria de estender o cronograma para essa alteração se isso garantisse um resultado confiável.
Charles Lambert
11
Considerando a volatilidade que sua apresentação parece sugerir, talvez você deva considerar o Git , pois facilita esse tipo de ramificação e fusão especulativa.
John Tobler
11
@Giorgio: eu também, a mesclagem diária parece um pouco paranóica, mas depende muito do tamanho da equipe. Quanto mais pessoas, mais mudanças e mais frequentemente você deve mesclar. Diariamente, parece o limite inferior, se você quiser ter tempo para trabalhar.
Matthieu M.
40

Nem todas as tarefas podem ser realizadas em um sprint de 2 semanas (artificial), por isso é necessário bom senso. Se não puder mais ser decomposto e for necessário, basta seguir em frente e fazê-lo. O processo não é mais importante que o resultado final e deve ser visto como uma diretriz e não como uma lei que nunca será violada.

Chris Card
fonte
3
Sua resposta é uma informação muito boa sobre o assunto. Estou aqui para "seguir em frente", como você diz. Fiz a pergunta na esperança de obter algumas informações para que eu pudesse criar um processo para executar paralelamente ao processo existente ou modificar de alguma forma o processo atual para resolver minha situação atual. Preciso de algo para informar aos desenvolvedores para que eles tenham diretrizes para trabalhar, pois isso acontecerá pelo menos mais duas vezes.
Charles Lambert
+1 para "O processo não é mais importante que o resultado final e deve ser visto como uma diretriz e não como uma lei que nunca será violada". - As pessoas realmente parecem esquecer isso.
Bjarke Freund-Hansen
32

Basta fazer um sprint de 3, 4 ou 5 semanas. Quem se importa? Você está obviamente convencido de que nada pode ser feito em um prazo menor, então pare de lutar contra isso.

Só não conte aos seus colegas da Royal Society of Blind Agile Adherance.

JeffO
fonte
parece que, por razões organizacionais (hotfixes mensais), é muito difícil mudar os sprints de 2 semanas.
Steve Bennett
10

Eu recomendo começar com o livro Working efetivamente with Legacy Code , de Michael Feathers. Ele cobre uma variedade de técnicas para reduzir o escopo das mudanças no estilo da refatoração.

kdgregory
fonte
Um bom livro, com certeza, mas acho que não abrange a refatoração dividida em vários sprints.
Adam Lear
4
Vou dar um +1 a isso, porque provavelmente é o melhor livro para começar quando você começar a aprender, como o título diz, a trabalhar efetivamente com o código legado. É relevante para alguém que possa fazer essa pergunta e não entender o que está envolvido em dividir as coisas em etapas menores.
Charles Lambert
@ Anna - então você pode (re) ler o capítulo 25, que fala sobre técnicas para quebrar os tipos de acoplamentos que impedem pequenas alterações.
precisa saber é o seguinte
@kdgregory Fair o suficiente. :) Se importa de acrescentar isso à sua resposta para torná-la mais incrível?
Adam Lear
7

Em nossa loja, quando temos grandes tarefas de refatoração ou reescrita que não podem ser concluídas em uma janela de release, deixamos a funcionalidade como está no sistema. Mas, começamos com as novas funções de bloco lego refatoradas conforme o tempo permitir. Eventualmente, chegamos a um estado em que temos blocos de lego suficientes, que um sprint fornece tempo suficiente para conectar os blocos de lego ao aplicativo e ativá-lo para os usuários.

Mais concisamente, dividimos ou retrabalhamos grandes funções usando novos nomes. Então, no final, usamos nosso trabalho renomeado e refatorado em vez do código antigo desagradável.

Amy Anuszewski
fonte
Essa é uma boa ideia, mas exigiria um alto nível de comunicação para ser implementada. Por exemplo, quando estou codificando, se eu identificar um método que não está sendo usado em nenhum lugar e não for público, eu o removerei.
Charles Lambert
5

Dedique um sprint para descobrir como manter o código funcionando corretamente no meio da refatoração. Isso pode assumir a forma de métodos e classes descontinuados, wrappers, adaptadores e similares. Sua refatoração pode tornar o código mais sujo por um curto período de tempo para ficar mais limpo a longo prazo; isso está ok. No momento, você está dizendo que isso não pode ser feito. Eu não acho isso certo - pense em como seria o seu processo, se pudesse ser feito, pense em quais etapas você pode tomar para fazê-lo. Então mergulhe.

Carl Manaster
fonte
Já fizemos tudo isso. Essa foi a razão pela qual expressei claramente que não poderia ser quebrado.
Charles Lambert
Realmente? Você passou um sprint inteiro simplesmente planejando refatorar sem quebrar o sistema e não conseguiu nada? Acho difícil acreditar que um sprint de planejamento dedicado não tenha resultado; talvez você precise contratar um consultor (e não, eu não sou um, não estou tentando conseguir um show).
Carl Manaster
11
Eu não disse nada disso. Eu estava dizendo que passamos por um processo semelhante ao que você descreveu e saiu do outro lado com algum código que não pode ser refatorado em um único sprint.
Charles Lambert
Eu disse: "Dedique um sprint para descobrir como manter o código funcionando adequadamente no meio da refatoração". Você disse: "Já fizemos tudo isso". Você está dizendo agora o contrário? Me desculpe se isso parece controverso, mas eu não entendo.
Carl Manaster
5

+1 na resposta de Corbin March, é exatamente o que eu estava pensando. Parece que sua base de código é um pouco feia e vai demorar mais de um único ciclo de sprint para limpá-la.
Então, assim como Corbin disse,

  1. ramifique-o em um "projeto de refatoração"
  2. teste sua mudança de agência
  3. promova para o seu ambiente de teste o teste de controle de qualidade
  4. junte-o gradualmente de volta ao tronco até que a refatoração seja concluída.

Tenho certeza de que você não terá nenhum problema em vender isso para o gerente de desenvolvimento, se o seu gerente estiver tendo dificuldades para vê-lo, explique a eles que Roma não foi construída em um dia e limpou todo o lixo jogado no escritório de Roma ruas não vai ser feito em um dia também. A refatoração levará um tempo, mas no final valerá a pena em termos de manutenção mais fácil, lançamentos de aprimoramentos mais rápidos, menos tickets de produção e um SLA mais cumprido.

bkdraper
fonte
11
Eu tenho toda a munição que preciso para convencer todos. Eu só preciso de um plano oficial para executá-lo, quando o apresento. Das respostas aqui, não tenho dúvida de que vou encontrar uma solução repetível.
Charles Lambert
4

Embora o redesenho que você realmente deseja fazer seja uma tarefa grande, seria possível refatorar partes menores para quebrar / desacoplar dependências individuais? Você sabe - em caso de dúvida, adicione indiretamente. Cada uma dessas dissociações deve ser uma tarefa menor que a gigantesca que você não pode concluir.

Depois que as dependências forem removidas, você poderá dividir as tarefas de refatoração restantes para serem obtidas nos sprints.

Matthew Flynn
fonte
3

No projeto em que estou trabalhando no momento, estamos usando sprints de 4 semanas. E, às vezes, não podemos terminar uma história de usuário e apenas a reiniciamos durante o sprint a seguir.

No entanto, IMHO deve ser possível dividir uma refatoração em histórias menores que se encaixam em um sprint de 4 semanas. Se você não conseguir colocar o código em um estado consistente dentro de quatro semanas, sinto que você está reescrevendo seu aplicativo em vez de refatorá-lo.

Giorgio
fonte
um sprint de 4 semanas deve cobri-lo. No entanto, não podemos parar os sprints atuais de 2 semanas devido a outras correções de bugs, etc. Portanto, isso teria que se estender por mais de um sprint. Assim, o cerne do meu problema.
Charles Lambert
Como eu disse, estamos usando sprints de 4 semanas e, se uma história não terminar em 4 semanas, apenas agendamos para o próximo sprint. Você pode pelo menos ter o sistema em um estado consistente no final de um sprint de duas semanas (e continuar durante o sprint a seguir)?
Giorgio
Não é um estado consistente verificável .
Charles Lambert
Devo acrescentar minha onda ao esforço que outros fizeram para esperar que você encontre outra palavra para usar, em vez de "refatorar". A refatoração é bem definida e seu escopo é muito mais imediato e de curto prazo do que o reprojeto e a reprogramação maciça e demorada que você precisa fazer.
John Augler
2

Eu recomendo que, quando determinadas tarefas levarem mais tempo que o ciclo de sprint de duas semanas, a tarefa seja programada por outro tempo. Sua equipe identificou a necessidade de refatoração e isso é importante. Às vezes, não há outra opção ... e, sim, isso é péssimo.

Quando chegar a hora de começar a refatoração, você simplesmente suspenderá os sprints normais. Você não tem escolha. Use o controle de versão inteligente - ramificar, refatorar, testar, mesclar. Sempre há um momento em que a refatoração de alguns grandes projetos tem prioridade sobre os recursos. Se possível, eu também tentaria separar as preocupações para melhorar a flexibilidade.

IAbstract
fonte
Não podemos adiar para sempre, e sua resposta não aborda como executar a refatoração.
Charles Lambert
@ Charles: 'previsto para outra hora.' ;) Eu não disse cancelar o projeto.
iAbstract
2

Tendo recentemente enfrentado o mesmo problema com uma parte de nossa base de código (que também é um pouco maior), espero poder compartilhar algumas idéias com você. Na minha situação, a base de código havia sido desenvolvida por outra equipe; portanto, ninguém dos desenvolvedores originais estava envolvido nessa refatoração. Minha experiência com a base de código foi de aproximadamente 1 ano, e outro desenvolvedor encarregou-a de 2 anos.

Permitam-me duas pequenas notas sobre as outras respostas aqui:

  • A ramificação ajudará você a estabelecer um playground para si mesmo, mas nunca mescle suas alterações no tronco em um grande conjunto de alterações. Você terá sérios problemas com o resto da equipe.
  • Você precisa fazer isso de forma incremental, e isso pode ser feito. Sem desculpas. Leia Trabalhando com eficiência com o código herdado, capa a capa. Leia isso novamente.
  • Pensar que você pode fazer isso um grande passo é uma falácia. Embora pareça mais trabalho, fazê-lo de forma incremental é muito mais fácil de gerenciar.

Ficar aparentemente "fora da reserva" por duas semanas ou mais não passará despercebido. Você precisa garantir o apoio do gerenciamento de projetos e, ainda mais importante, da equipe. Se a equipe não estiver comprometida com essa refatoração (e isso significa, faça isso agora, não em um futuro distante), você terá problemas.

Não faça isso sozinho, use programação em pares. Isso não significa estritamente que você precisa ficar sentado na frente do mesmo teclado o tempo todo, mas pode lidar com tarefas pequenas e estreitas (por exemplo, testes de gravação que capturam o comportamento dessa classe) individualmente.

Faça uma refatoração de arranhões e trate-a como tal. (Uma espécie de refatoração de protótipo "descartável", o bit "descartável" é importante!) Honestamente, é improvável que você saiba todas as implicações que sua refatoração terá. Uma refatoração de rascunho o ajudará em alguns aspectos:

  • Você descobrirá partes do sistema que nunca soube que elas existiam.
  • Você terá uma visão muito melhor de como os módulos se interconectam
  • Você descobrirá uma nova maneira de agrupar seu sistema em módulos, provavelmente muito diferente do seu entendimento atual. Discuta idéias com seu parceiro. Tente destilar sua nova visão. Escreva um pequeno white paper de arquitetura (ou desenhe um diagrama) que diga onde as coisas estão atualmente e onde devem pertencer logicamente.

Quando você fizer sua refatoração de arranhões, espero que você descubra que não pode simplesmente mudar tudo. Você vai se sentir mal, é apenas uma grande bagunça e você não pode simplesmente apertar um botão e fazê-lo funcionar. Foi o que aconteceu comigo, pode ser diferente na sua situação.

No entanto, meu parceiro e eu entendemos muito melhor nosso sistema. Agora, conseguimos identificar refatorações / redesignes menores e menores (embora ainda grandes). Capturamos nossa visão do sistema em um diagrama e a compartilhamos com a equipe, juntamente com os itens de lista de pendências que criamos para implementar essa visão. Fortalecidos por um consenso comum, decidimos quais itens implementaríamos ao longo da próxima iteração.

Uma última coisa que nos ajudou foi usar um grande quadro branco. Há muitas coisas para manter em sua cabeça. É extremamente importante que você faça anotações. Escreva para si mesmo uma nota de resumo no final do dia, capturando o que você fez hoje e deseja fazer amanhã. Isso ajuda a relaxar os grandes momentos, e você precisa de um tempo descontraído para acompanhar a tarefa. Boa sorte!

Johannes Rudolph
fonte
1

Inicie uma janela de manutenção durante a qual nenhum desenvolvimento adicional é realizado. Execute o redesenho e depois retome os sprints de desenvolvimento.

Christopher Mahan
fonte
0

Temos dois tipos de trabalhos em mãos:

  1. Trabalhos de hora-homem
  2. Obras geniais

A refatoração geralmente consiste no primeiro tipo de trabalho, já que muitos métodos já são conhecidos por desenvolvedores como DRY , SRP , OCP , DI etc. Assim, quando um projeto leva dois meses para ser refatorado, leva apenas dois meses , existe de jeito nenhum. Assim, minha sugestão seria não refatorar o projeto original e deixá-lo trabalhar em sua situação atual. Pare de receber novas solicitações e requisitos das partes interessadas e do proprietário do produto . Em seguida, deixe a equipe trabalhar no projeto até que ele seja refatorado e pronto para começar.

Saeed Neamati
fonte
0

Uma sugestão que pode ajudar: Se você tiver um código não testado, de modo que não tenha tempo suficiente para refatorá-lo e testá-lo novamente dentro do sprint de duas semanas, considere primeiro fazer outras pequenas alterações não relacionadas ao código, para que você possa se concentrar em escrever testes para o primeiro sprint ou dois. Talvez você possa identificar vários clientes não testados do código que deseja refatorar; escolha um cliente e faça outras alterações de alguma utilidade para os negócios que forçarão você a escrever testes para esse cliente. Quando você estiver mais familiarizado com o código, trabalhando com ele, e tiver mais testes, e possivelmente tiver realizado algumas refatorações menores, estará em uma posição muito melhor para realizar a refatoração e o (agora mais fácil ) testando ambos em uma iteração.

Outra abordagem é fazer uma cópia do código incorreto, refatorá-lo e mover os clientes um de cada vez para o novo código. Este trabalho pode ser dividido em iterações.

E não desista: não aceite apenas que uma refatoração grande não pode ser dividida em etapas menores. A abordagem mais fácil / rápida / melhor pode levar mais tempo que uma iteração. Mas isso não significa que não há como executar blocos do tamanho de iteração.

Jeff Grigg
fonte