Eu aprendi uma quantidade significativa de codificação, no entanto, sempre esteve em um ambiente científico (não em ciência da computação), completamente autodidata, sem ninguém para me guiar na direção certa. Assim, minha jornada de codificação foi ... bagunçada. Percebi agora que, sempre que construo algum tipo de programa, no final, percebo como poderia ter feito isso de maneira muito mais elegante, muito mais eficiente e de uma maneira muito mais flexível e fácil de gerenciar no futuro. Em algumas circunstâncias, eu realmente voltei e reconstruí as coisas desde o início, mas geralmente isso não é praticamente possível. Embora a maioria dos meus programas até agora tenha sido relativamente pequena, parece bastante complicado reescrever completamente programas grandes toda vez que você cria algo.
Só estou pensando, isso é uma experiência normal? Caso contrário, como você evita que isso aconteça? Eu tentei planejar as coisas com antecedência, mas não consigo realmente prever tudo até começar a elaborar algum código.
Respostas:
Esse sentimento é completamente normal e esperado. Isso significa que você está aprendendo. Quase toda vez que inicio um novo projeto, começo em uma direção e acabo desenhando de maneira diferente no final.
É prática comum primeiro desenvolver um protótipo antes de iniciar a coisa real. Também é comum revisitar o código antigo e refatorá- lo. Isso é mais fácil se o seu design for modular - você pode redesenhar facilmente partes e peças de cada vez, sem precisar descartar totalmente o design antigo.
Para algumas pessoas, é melhor escrever primeiro o pseudo-código . Outros acham útil começar escrevendo comentários descrevendo o que o código fará, depois escreva o código assim que a estrutura geral estiver lá. Essas duas coisas ajudarão você a planejar melhor seu design e podem evitar a necessidade de uma reescrita.
Se você faz parte de uma equipe, ter um processo de revisão é crucial para o processo de design. Peça a alguém que revise seu código para aprender como melhorar seu design.
fonte
Esta é uma experiência muito comum
A maioria das pessoas com quem interajo e eu também me sinto assim. Pelo que posso dizer, uma razão para isso é que você aprende mais sobre o domínio e as ferramentas usadas ao escrever seu código, o que o leva a reconhecer muitas oportunidades de melhoria depois de escrever seu programa.
O outro motivo é que você pode ter uma idéia na cabeça sobre a solução ideal de código limpo e, em seguida, o mundo real e suas limitações complicadas atrapalham, forçando você a escrever soluções e hacks imperfeitos que podem deixá-lo insatisfeito.
"Todo mundo tem um plano até levar um soco na cara."
o que fazer sobre isso
Até certo ponto, você terá que aprender a aceitar que seu código nunca será perfeito. Uma coisa que me ajudou nisso é a mentalidade de "Se eu odeio o código que escrevi há um mês, significa que aprendi e me tornei um programador melhor".
Uma maneira de aliviar o problema é estar sempre atento a possíveis melhorias enquanto trabalha e refatora continuamente. Certifique-se de atingir um bom equilíbrio entre refatorar e adicionar novos recursos / corrigir bugs. Isso não ajudará em grandes problemas de design, mas geralmente o deixará com uma base de código mais polida da qual você pode se orgulhar.
fonte
Aprenda refatoração - a arte de melhorar gradualmente o código. Todos aprendemos o tempo todo, por isso é muito comum perceber que o código que você mesmo escreveu pode ser melhor.
Mas você deve poder transformar o código existente para aplicar essas melhorias sem precisar começar do zero.
fonte
Se você tem excelentes requisitos estáticos e os entende bem e tem tempo para análises detalhadas, você tem a chance de criar um bom design com o qual ainda ficará satisfeito quando terminar.
Mesmo nesse caso feliz, você pode aprender novos recursos de linguagem que teriam ajudado a criar um design melhor.
No entanto, geralmente, você não terá essa sorte: os requisitos serão menos que estelares e incompletos e, embora você tenha pensado que os entendeu, acontece que existem áreas sobre as quais você fez suposições inválidas.
Em seguida, os requisitos serão alterados à medida que os usuários analisarem suas entregas iniciais. Então, algo que os usuários não controlam mudará, por exemplo, a lei tributária.
Tudo o que você pode fazer é projetar, assumindo que as coisas vão mudar. Refatore quando puder, mas saiba que tempo e orçamento geralmente significam que sua entrega final não é tão elegante quanto teria sido se você soubesse no início o que sabe agora.
Com o tempo, você vai se aprofundando nos requisitos que recebe e obtém um nariz para o qual partes de seu projeto provavelmente precisam de flexibilidade para absorver as mudanças.
No final, aceite que a mudança é constante e ignore a pontada que diz "Eu poderia ter feito melhor". Seja orgulhoso e feliz por ter fornecido uma solução.
fonte
O que você pode fazer é criar um protótipo descartável, antes de começar a fazer o projeto "real". Rapido e sujo. Então, quando você obtém um protótipo para provar um conceito, conhece o sistema e como fazer as coisas corretamente.
Mas não se surpreenda, se depois de N anos você voltar a esse código e pensar "que bagunça".
fonte
Lembre-se deste mantra:
A solução perfeita nem sempre é a solução ideal . A solução ideal é aquela que atinge o status "bom o suficiente" com a menor quantidade de trabalho.
Se você responder sim a todas essas perguntas, seu software é "bom o suficiente" e não há boas razões para reescrevê-lo do zero. Aplique as lições de design que aprendeu no seu próximo projeto.
É perfeitamente normal que todo programador tenha alguns programas complicados no passado. Aconteceu várias vezes ao longo da minha carreira como desenvolvedor de software que eu olhei para algum código, me perguntei "Que idiota escreveu essa bagunça?", Verifiquei o histórico da versão e percebi que era eu de vários anos atrás.
fonte
É tentador pensar que o planejamento perfeito fornecerá a arquitetura / arquitetura de software perfeitas, no entanto, isso é categoricamente falso. Há dois grandes problemas com isso. Primeiro, "no papel" e "o código" raramente correspondem, e o motivo é que é fácil dizer como deve ser feito, em vez de realmente fazê-lo . Em segundo lugar, mudanças imprevistas nos requisitos tornam-se aparentes no final do processo de desenvolvimento que não poderiam ter sido pensadas desde o início.
Você já ouviu falar do movimento Agile? É uma maneira de pensar em que valorizamos "reagir à mudança" em vez de "seguir um plano" (entre outras coisas). Aqui está o manifesto (é uma leitura rápida). Você também pode ler sobre o Big Design Up Front (BDUF) e quais são as armadilhas.
Infelizmente, a versão corporativa do "Agile" é um monte de falsos (mestres de scrum certificados, processo pesado em nome de "Agile", forçando o scrum, forçando 100% de cobertura de código etc.) e geralmente resulta em mudanças de processo asininas porque os gerentes pense que o Agile é um processo e uma bala de prata (do qual não é nem um). Leia o manifesto ágil, ouça pessoas que iniciaram esse movimento, como tio Bob e Martin Fowler, e não se deixe levar pela versão sem sentido de "corporate Agile".
Em particular, você geralmente pode se dar bem apenas com o TDD (Test Driven Development) em código científico , e há uma boa chance de que seu projeto de software seja muito bom. Isso ocorre porque o código científico de sucesso tem principalmente interfaces ultra-utilizáveis, com desempenho como uma preocupação secundária (e às vezes concorrente), e assim você pode se dar bem com um design mais "ganancioso". O tipo TDD força seu software a ser ultrautilizável , porque você escreve como deseja que as coisas sejam chamadas (idealmente) antes de implementá-las. Também força pequenas funções com pequenas interfaces que podem ser chamadas rapidamente de uma maneira simples, "entrada" / "saída", e coloca você em uma boa posição para refatorar caso os requisitos mudem.
Acho que todos podemos concordar que
numpy
é um software de computação científica bem-sucedido. Suas interfaces são pequenas, super utilizáveis e tudo funciona bem juntas. Observe quenumpy
o guia de referência recomenda explicitamente o TDD: https://docs.scipy.org/doc/numpy-1.15.1/reference/testing.html . Eu usei o TDD no passado para o software de imagem SAR (Synthetic Aperature Radar): e também posso afirmar que funciona extremamente bem para esse domínio em particular.Advertência: A parte de design do TDD funciona menos bem em sistemas onde uma refatoração fundamental (como decidir que você precisa que seu software seja altamente simultâneo) seria difícil, como em um sistema distribuído. Por exemplo, se você tivesse que projetar algo como o Facebook, onde você tem milhões de usuários simultâneos, fazer TDD (para orientar seu design) seria um erro (ainda aceitável para usar depois de um design preliminar e apenas "testar o primeiro desenvolvimento" "). É importante pensar nos recursos e na estrutura do seu aplicativo antes de entrar no código. O TDD nunca o levará a um sistema distribuído e altamente disponível.
Dado o exposto, deve ser um pouco evidente que um design perfeito é realmente impossível de alcançar; portanto, perseguir um design perfeito é um jogo de tolos. Você realmente pode apenas chegar perto. Mesmo se você acha que pode redesenhar do zero, provavelmente ainda existem requisitos ocultos que não se mostraram. Além disso, as reescritas levam pelo menos o tempo necessário para desenvolver o código original. Quase certamente não será mais curto, pois é provável que o novo design tenha problemas próprios imprevistos, além de você ter que reimplementar todos os recursos do sistema antigo.
Outra coisa a considerar é que seu design realmente importa quando os requisitos mudam .Não importa o quão ruim é o design, se nada mudar (supondo que seja totalmente funcional para os casos de uso atuais). Eu trabalhei em uma linha de base que possuía uma instrução de troca de 22.000 linhas (a função era ainda mais longa). Foi um design terrível? Caramba, sim, foi horrível. Nós consertamos isso? Não. Funcionou muito bem do jeito que estava e essa parte do sistema nunca realmente causou falhas ou bugs. Ele só foi tocado uma vez nos dois anos em que estive no projeto e alguém, você adivinhou, inseriu outro caso no comutador. Mas não vale a pena arrumar tempo para consertar algo que é tocado com pouca frequência, simplesmente não é. Deixe o design imperfeito como ele é e, se não estiver quebrado (ou constantemente quebrado), não o conserte. Então talvez você possa fazer melhor ... mas valeria a pena reescrever? O que você vai ganhar?
HTH.
fonte
Concordo plenamente com a resposta fornecida por Andreas Kammerloher, mas estou surpreso que ninguém tenha sugerido aprender e aplicar algumas práticas recomendadas de codificação. É claro que isso não é uma bala de prata, mas usar uma abordagem de orientação aberta, padrões de design, entender quando seu código cheira e assim por diante fará de você um programador melhor. Investigue qual é o melhor uso de bibliotecas, estruturas etc. Há muito mais com certeza, estou apenas arranhando a superfície.
Isso não significa que você não verá seu código antigo como um lixo total (na verdade, você verá os programas mais antigos ainda mais lixo do que sem esse conhecimento), mas com cada novo software que você escrever verá você melhora. Observe também que o número de práticas recomendadas de codificação aumenta com o tempo; algumas simplesmente mudam para que você nunca chegue à perfeição. Aceite este ou bastante o caminho.
Mais uma coisa boa é ter uma revisão de código. Quando você trabalha sozinho, é fácil cortar custos. Se você tiver uma segunda pessoa revisando seu código, eles poderão indicar onde você não segue essas práticas recomendadas. Dessa forma, você produzirá um código melhor e aprenderá algo.
fonte
Para adicionar outras excelentes respostas aqui, uma coisa que acho útil é saber para onde você quer chegar .
É raro receber a aprovação de uma grande parte da refatoração por conta própria. Mas muitas vezes você pode fazer pequenos refatoramentos à medida que avança, 'sob o radar', enquanto trabalha em cada área da base de código. E se você tem um objetivo em mente, pode aproveitar essas oportunidades para avançar, passo a passo, na direção certa.
Pode levar muito tempo, mas a maioria das etapas melhorará o código e o resultado final valerá a pena.
Além disso, sentir que você poderia fazer melhor é um bom sinal ! Isso mostra que você se preocupa com a qualidade do seu trabalho e está avaliando-o criticamente; então você provavelmente está aprendendo e melhorando. Não deixe que essas coisas o preocupem - mas não pare de fazê-las!
fonte
Você inadvertidamente tropeçou em um dos maiores desafios da humanidade (aventuras), a ponte entre homem e máquina. A ponte entre o homem e a estrutura física, engenharia civil, por exemplo, está em andamento há cerca de 200 anos ou mais.
Como o desenvolvimento de software realmente só se tornou popular nos anos 90, ele tem aproximadamente 30 anos. Aprendemos que não é tanto uma disciplina de engenharia quanto uma ciência social, e apenas começamos.
Sim, você experimentará TDD, Refatoração, Programação Funcional, Padrão de Repositório, Fonte de Eventos, MV alguma coisa, Script Java (<- Faça isso, é loucura), Vinculação de Modelo, Sem Sql, Containers, Agile, SQL (<- faça isso é poderoso).
Não há uma solução. Até os especialistas ainda estão entendendo os canudos.
Bem-vindo, e esteja avisado, é um lugar solitário; mas absolutamente fascinante.
fonte
Eu vou ir um pouco contra a corrente. Isso é incrivelmente comum , mas não é aceitável . O que isso indica é que você não está reconhecendo boas maneiras de organizar seu código enquanto o escreve. A sensação vem do seu código não ser direto .
Sua experiência foi minha por um longo tempo também, mas recentemente (nos últimos dois anos), venho produzindo mais códigos que não me fazem sentir que preciso jogar tudo fora. Aqui está aproximadamente o que eu fiz:
Meu código agora é mais "processual", com o que quero dizer que está organizado por quais ações são executadas e não por quais estruturas de dados ele usa. Eu uso objetos em linguagens em que funções independentes não podem ser substituídas em tempo real (C # e Java não podem substituir funções em andamento, o Python pode). Eu tenho a tendência de criar mais funções utilitárias agora, que apenas afastam alguns clichês irritantes do caminho para que eu possa realmente ler a lógica do meu código. (Por exemplo, quando eu precisava processar todas as combinações de itens em uma lista, empurrei o índice em loop para um método de extensão que retorna
Tuple
s, para que a função original não seja confusa com esses detalhes de implementação.) Agora passo muito mais coisas como parâmetros para funções, em vez de ter uma função alcançando algum outro objeto para buscá-la. (O chamador busca ou o cria e o passa e o passa.) Agora deixo mais comentários que explicam coisas que não são óbvias apenas olhando o código , o que facilita o acompanhamento da lógica de um método. Só escrevo testes em casos limitados em que me preocupo com a lógica de algo que acabei de criar e evito usar zombarias. (Faço mais testes de entrada / saída em partes isoladas da lógica.) O resultado é um código que não é perfeito , mas que realmente parece bom, mesmo 2 ou 3 anos depois. É um código que responde razoavelmente bem à mudança; pequenas coisas podem ser adicionadas ou removidas ou alteradas sem que todo o sistema desmorone.Até certo ponto, você precisa passar por um período em que as coisas estão uma bagunça, para que você possa ter alguma experiência. Mas se as coisas ainda estão tão confusas que você quer jogar tudo fora e começar de novo, algo está errado; você não está aprendendo.
fonte
Lembrando que seu tempo é limitado. E seu tempo futuro também é limitado. Seja para trabalho, escola ou projetos pessoais, quando se trata de código de trabalho , você deve se perguntar "está reescrevendo esse o melhor uso do meu tempo limitado e valioso?". Ou talvez "esse é o uso mais responsável do meu tempo limitado"?
Às vezes a resposta será inequivocamente positiva . Geralmente não. Às vezes, estará em cima do muro e você terá que usar sua discrição. Às vezes, é um bom uso do seu tempo simplesmente por causa das coisas que você aprenderá fazendo isso.
Eu tenho muitos projetos, profissionais e pessoais, que se beneficiariam de uma porta / reescrita. Eu também tenho outras coisas para fazer.
fonte
É uma parte completamente normal da aprendizagem. Você percebe erros à medida que avança.
É assim que você melhora e não é algo que você deva evitar.
fonte
Você pode se dar a experiência de saber que o desejo sedutor de reescrever é geralmente improdutivo. Encontre algum projeto de código aberto antigo, cabeludo e deselegante, de complexidade moderada. Tente reescrevê-lo do zero e veja como você o faz.
Eventualmente, seu instinto mudará de pensar "eu poderia reescrever esse sistema muito melhor" para pensar "a fragilidade desse sistema pode ser indicativa de alguma complexidade que não é imediatamente aparente".
fonte