Como você faz a transição de um programa do desenvolvimento para o release?

67

Em algum momento, um programa está em desenvolvimento. Recursos estão sendo adicionados, removidos ou alterados o tempo todo. Toda versão é nada além de um protótipo. Então eu não perco muito tempo escrevendo código super limpo nesse ponto, porque eu nunca sei quanto tempo algo dura. É claro que tento manter a qualidade do código em certos padrões, mas o tempo é sempre um problema.

Em seguida, chega o ponto em que o programa termina e o (s) tomador (es) de decisão diz "é isso". Eu tenho um protótipo de trabalho neste momento, mas o código dentro é um pouco confuso de todo o lado e para trás durante a fase de desenvolvimento. Espero que eu comece a testar / depuração final, mas meu instinto diz que eu deveria agora de alguma forma limpar e reescrever coisas para dar uma arquitetura adequada que facilite a manutenção.

Uma vez que o material tenha sido testado e aprovado, não faz sentido reescrevê-lo. Em uma base regular eu estou lá com um protótipo 'acabado' em funcionamento e recebo um bug durante o teste e vejo que é um resultado de codificação não inteligente que é um resultado de todo o processo de desenvolvimento. Eu estou no meio do teste e o bugfix seria uma reescrita ... é uma bagunça!

Existem maneiras melhores / de livros didáticos, tenho certeza. Mas eu tenho que trabalhar em um ambiente de trabalho real, onde nem tudo é um livro didático.

Então, como eu faço a transição do meu protótipo de trabalho para uma versão de lançamento com uma base de código estável? Talvez eu não deva considerar o desenvolvimento terminado assim que o vejo e realmente o vejo como a fase de limpeza ... Não sei, preciso de ajuda aqui.

EDITAR

Eu quero esclarecer algumas coisas.

  • Eu estou 100% do lado certo antes e depois, código limpo e legível. Mas eu também tenho que fazer as coisas e não posso sonhar com a beleza do código tudo limpo e brilhante. Eu tenho que encontrar um compromisso.

  • geralmente, um novo recurso é realmente algo que queremos testar e ver se faz sentido implementar algo assim. (especialmente em aplicativos móveis, para obter uma aparência real em um dispositivo real) Então é algo pequeno que (imho) não justifica muito trabalho em uma primeira iteração "vamos ver". No entanto, por vezes, surge a pergunta QUANDO eu pago este tech.debt? É disso que trata essa questão.

Se eu souber que metade dos recursos serão descartados um dia depois (experiência suficiente em nossa empresa até agora), realmente acho difícil acreditar que a melhor maneira de abordar o meu problema é investir tempo extra para escrever tudo. limpar mesmo que a maior parte seja descartada logo após. Parece-me que vou economizar tempo se fizer uma grande limpeza quando a coisa estiver sólida, daí a minha pergunta.

    
por NikkyD 09.03.2016 / 13:55
fonte

7 respostas

98

So I don't waste much time on writing super clean code at that point because I never know how long something lasts.

Não saber quanto tempo dura alguma coisa nunca deve ser uma desculpa para desleixo - muito pelo contrário. O código mais limpo é IMHO o que não entra em seu caminho quando você tem que mudar alguma coisa. Portanto, minha recomendação é: sempre tente escrever o código mais limpo possível - especialmente quando estiver codificando um protótipo. Porque será muito mais fácil adaptá-lo quando algo tiver que ser mudado (o que certamente irá acontecer).

Não me entenda mal - minha compreensão do "código mais limpo" não tem nada a ver com tornar o código bonito por causa da beleza. Isso é realmente algo que pode atrasar você. No meu ponto de vista, código limpo é o código que é mais auto-explicativo (não é necessário gravar tantos documentos - acelera), fácil de entender (menos erros, menos depuração necessária - aumento de velocidade, menos tempo necessário para encontrar o correto lugar para alterar - acelerar), resolve o problema dado com a menor quantidade de código necessário (menos código para depurar - speedup óbvio), é DRY (apenas um lugar para mudar quando algo tem que ser mudado - aceleração - e menor risco de introduzir novos bugs esquecendo de mudar um segundo lugar), segue padrões de codificação (coisas menos complicadas para se pensar - speedup), usa blocos de construção pequenos e reutilizáveis (que podem ser reutilizados para muitos recursos ou até mesmo protótipos) e assim por diante.

I am expected to start testing/final debugging but my gut says I should now somehow clean up and or rewrite stuff to give it proper architecture that makes maintenance etc easier

Fazer "limpeza" depois nunca funciona. Considere que você limpa antes de implementar um novo recurso, ou quando começar a implementá-lo, mas não depois. Por exemplo, sempre que você começar a tocar em um método para um recurso e perceber que ele ultrapassa 10 linhas, considere refatorá-lo em métodos menores - imediatamente , antes de concluir o recurso. Sempre que você detectar uma variável ou um nome de função existente, você não sabe exatamente o que isso significa, descubra para que serve e renomeie a coisa antes de fazer qualquer outra coisa. Se você fizer isso regularmente, mantenha seu código pelo menos em um estado "limpo o suficiente". E você começa a economizar tempo - porque você precisa de muito menos tempo para depurar.

I am in the middle of testing and the bug fix would be a rewrite

... que é a prova real para o que eu escrevi acima: ser assombrações "sujas" imediatamente de volta quando você começar a depurar seu código e irá torná-lo mais lento.

Você pode evitar isso quase completamente se fizer a limpeza imediatamente. Em seguida, correções de bugs significam principalmente pequenas alterações no código, mas nunca uma alteração arquitetural importante. Se você realmente detectar evidências de melhorias na arquitetura durante o teste, adie-as, coloque-as no sistema de rastreamento de problemas e implemente-as na próxima vez que você precisar implementar um recurso que se beneficie dessa alteração ( antes você começar com esse recurso).

Isso requer alguma disciplina e alguma experiência em codificação, é claro. É uma ideia semelhante à idéia por trás do "desenvolvimento orientado a testes", fazendo essas coisas de antemão em vez de executá-las posteriormente (o TDD também pode ajudar, mas o que escrevi funciona mesmo quando você não usa o TDD). Quando você fizer isso consequentemente, você não precisará de nenhuma "fase de limpeza" especial antes de liberar.

    
por 09.03.2016 / 14:32
fonte
22

Você tem dois problemas separados, ambos com o mesmo sintoma (código malfeito):

Problema # 1: controle de requisitos insuficiente Não quero dizer que seus stakeholders alterem seus requisitos com muita frequência, quero dizer que você está permitindo alterações nos requisitos durante um ciclo de correções / testes. Mesmo as metodologias ágeis não suportam isso; você constrói, testa, entrega, injeta novos requisitos.

Problema # 2: Você acredita que o material que você está escrevendo é "só por enquanto" No desenvolvimento de software "apenas por enquanto" o código é realmente extremamente raro. Você percebeu que uma vez satisfeito o requisito do usuário, os rigores da oferta e da demanda tornam muito difícil justificar a volta e a reimplementação de um recurso "concluído". Então o que fazer sobre isso? Sempre escreva o código de produção. Funcionalmente para você, isso significa que suas estimativas para as partes interessadas precisam ser substancialmente maiores, para que você tenha algum tempo para fazer isso da maneira certa.

Além disso, entenda que você está trabalhando na posição mais difícil como desenvolvedor: Leia o artigo de Joel Spolsky assuma a vida de um desenvolvedor interno . Então, você precisa ser extremamente vigilante se quiser entrar com sua sanidade intacta.

    
por 09.03.2016 / 18:23
fonte
21

É um problema comum - especialmente ao criar o que é essencialmente um balão de avaliação por assim dizer.

Existem várias abordagens que podem ajudar. Em primeiro lugar, a abordagem TDD pode ajudar a reduzir a base de código àquela que é estritamente necessária. Se seus testes forem compatíveis com seu código, você poderá pelo menos ter alguma confiança de que seu código se comporta como deveria.

Reserve um tempo para refatorar a medida que você for. Uma vez que você tenha um protótipo e o cliente esteja ansioso para colocar as mãos nele, é difícil dizer que você precisa de tempo para polir o que (para eles) está completo. Eu gosto de fazer check-in em uma base diária seguida de um check-in de refatoração, mas YMMV.

Desenvolvedores que escrevem código rapidamente são frequentemente requisitados - nós tivemos um desenvolvedor como esse no meu último departamento. Todos os times o queriam porque ele trabalhava super rápido. Quando chegou a hora de testar e liberar seu código, as rodas rapidamente saíram. Coisas codificadas, hacks e atalhos em todos os lugares. Seu estoque logo caiu - massivamente.

O corte do código de produção desde o início pode parecer um empecilho, mas dependendo do ambiente, existem muitas ferramentas que podem tirar o trabalho de desenvolvimento, como Ghostdoc e Stylecop .

Vale a pena entrar na mentalidade de desenvolvimento certa desde o início. Você ficaria surpreso com a quantidade de sistemas back-of-a-fag-packet que deveriam ser apenas soluções stop-gap se tornarem aplicações básicas.

    
por 09.03.2016 / 14:29
fonte
11

Continuamente

Velocidade de desenvolvimento é o principal motivo para escrever código limpo, legível e testável; não é feito por beleza, nem por outros valores abstratos. Por que eu negaria isso a mim mesmo e só o faria depois por algum futuro programador?

Claro que pode haver mudanças que são principalmente cosméticas e, portanto, não essenciais; Eu diria que é muito mais útil ter um código moderadamente bom agora, durante o desenvolvimento, do que ter uma bagunça agora e esperar torná-lo perfeito mais tarde (o que, sejamos francos, isso nunca vai acontecer, mesmo se você tivesse o tempo).

    
por 10.03.2016 / 11:14
fonte
4

Você faz isso diferenciando o código "Estou apenas tentando isso para ver como funciona" e "isso está indo para o código do produto". Existem várias maneiras de fazer isso.

Um é a ramificação ou qualquer que seja a palavra no seu sistema de controle de origem. Você cria uma ramificação para o novo relatório ou o novo layout de importação ou o que for. Se as pessoas gostarem, a tarefa de colocá-lo de volta no ramo principal é um trabalho separado e rastreável. Pode ser atribuído a alguém e relatado e não é esperado que apenas magicamente aconteça a gestão do dia (ou vendas) concorda que o recurso pertence ao produto.

Outro é picos. Você não faz essa mudança no produto. Você sai em algum aplicativo separado, super simples, que existe apenas para você ter um lugar para colocar código. Você pode ser tão confuso quanto quiser porque está apenas explorando a nova API ou qualquer outra coisa. E, novamente, se você voltar e relatar "sim, podemos fazer isso, descobri como" há uma tarefa rastreável, reportável e atribuível de escrever código pronto para o produto no produto para fazer o que você deseja.

Em ambos os casos, o produto pronto significa legível, puro, seguindo os padrões de nomenclatura, com testes e aderindo ao seu estilo de código e metas de desempenho. Em ambos os casos, você torna esse trabalho visível. Eu concordo que você não quer fazer todo esse trabalho toda vez que alguém está propenso a tirar o recurso do produto. Mas você não quer deixar esse trabalho ficar invisível também. Trabalhar em cópias separadas do produto ou em um produto não relacionado que é pouco mais que um equipamento de teste permite que você expõe o trabalho para criar um código pronto para o produto assim que alguém decidir que deseja algo.

A desvantagem é que eles não podem decidir que querem algo e enviá-lo (ou seja, a meia-meia-boca, confuso, não testado, não documentado, possivelmente meia-versão lenta que você implementou como prova de conceito) amanhã. Na primeira vez que você receber um pushback nessa frente, simplesmente pergunte se você deve fazer o caminho mais longo (mais caro) toda vez, apenas no caso, diminuindo o caminho para os recursos rejeitados. Se você perguntar corretamente, você receberá um "não".

    
por 10.03.2016 / 23:00
fonte
1

Realmente, acho que você já entendeu o problema. O problema é que seu estilo de codificação está exigindo que você faça muito retrabalho. A razão pela qual está precisando de muito retrabalho é porque (a) é colocada junto com previsão e planejamento insuficientes e (b) os incrementos de curto prazo regularmente colocados durante o desenvolvimento combinatoriamente aumentam a complexidade de qualquer retrabalho necessário.

A resposta, portanto, é para

(a) desloque seu estilo de desenvolvimento um pouco mais para a cascata e um pouco menos ágil. Não vá até o fim, porque a cachoeira clássica tem suas próprias armadilhas. Há um equilíbrio saudável a ser tido. Eu sei que pode ser apenas pensar em coisas por alguns dias, às vezes, como nenhum desenvolvimento está sendo feito, mas você tem que confiar no processo. Na engenharia, você não pode simplesmente unir as coisas e, em seguida, pregar as coisas no topo e esperar sair com uma solução elegante. Se não há ninguém fazendo arquitetura e design técnico de nível superior, isso significa que é o seu trabalho. Você está pagando o preço de negligenciar esse trabalho.

(b) tente evitar remendar as coisas. Não pense a longo prazo apenas quando chega a hora de fazer o controle de qualidade. Realmente você deveria testar cada pequena parte que você constrói, o tempo todo, e cobrindo todos os casos de entrada, aqueles que não estão no caminho feliz também. Um patch / hack é quase por definição uma correção de curto prazo, que pode ter um custo de longo prazo, atingindo o custo total de propriedade do cliente no sistema. Mais uma vez, a pressão está ligada para obter o código, então tem que haver equilíbrio. Mas tente não colocar correções de curto prazo no lugar, esp. aqueles que juntam componentes que realmente devem ser fracamente acoplados. Haverá retrabalho, por isso, faça-o com antecedência para facilitar as coisas, para evitar os hacks e os patches que se acumularão com o tempo e se tornem incontroláveis.

    
por 09.03.2016 / 16:35
fonte
0

Você escreve:

Every version is nothing but a prototype. So I don't waste much time on writing super clean code at that point because I never know how long something lasts. ...

Then comes the point where the program is finished and the decision maker(s) say "that's it". I do have a working prototype at this point, but the code inside is a bit messy from all the back and forth during the development phase.

Uma versão com check-in pode ser um "protótipo" na medida em que perde recursos ou alguns recursos não são revelados, mas todo o código registrado deve ser um código de qualidade de produção que não precise de limpeza.

Acho que você está adiando a "limpeza" para muita coisa.

Minha regra é:

  • Comece com o (sub) recurso
  • sinta-se à vontade para escrever coisas incompletas e incompletas, talvez alguns detalhes sobre o que estou implementando ou se eu tiver que riscar a (s) última (s) hora (s) da codificação (observe que isso pode andam de mãos dadas com o TDD / testes, é que tudo está um pouco enfraquecido para obter um feedback rápido do espaço de implementação que estou explorando)
  • O sub-recurso "funciona" suficientemente bom por enquanto
  • Agora faça a limpeza: antes de um commit do SCC .
    • Examine o código para ver o que é óbvio
    • Faça um diff vs last commit para revisar as alterações e talvez pegar alguns problemas
    • Corrija as coisas que anotei no meu bloco de anotações
  • Agora eu faço o commit - essa qualidade de código está pronta para ser enviada

Neste ponto, o código confirmado ainda pode conter algumas soluções alternativas ou "dívida técnica" que seria bom limpar, e talvez eu o limpe quando for natural fazer o seguinte sub-recurso , mas tudo ficará bem se o código for lançado como está.

    
por 10.03.2016 / 01:25
fonte