ti-enxame.com

Como evitar sempre a sensação de que, se eu reconstruísse completamente meu programa do zero, faria muito melhor?

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 que ninguém me guiasse 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? Tentei planejar as coisas com antecedência, mas não consigo realmente prever tudo até começar a elaborar algum código.

92
Ashish

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 refatorar. Isso é mais fácil se o seu design for modular - você pode redesenhar facilmente os bits e as peças de uma vez, sem precisar descartar totalmente o design antigo.

Para algumas pessoas, ajuda escrever pseudo-código primeiro. 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.

4
asrjarratt

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 que usa 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 foi 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 refinada da qual você pode se orgulhar.

100
Andreas Kammerloher

Aprenda refatoração - a arte do código melhorando gradualmente. 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.

45
JacquesB

Se você possui 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 há áreas sobre as quais você fez suposições inválidas.

Em seguida, os requisitos serão alterados à medida que os usuários analisarem seus resultados iniciais. Então, algo que os usuários não controlam será alterado, por exemplo. lei de imposto.

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 seria 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 as partes do 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.

9
Wildbill

Como evitar sempre a sensação de que, se eu reconstruísse completamente meu programa do zero, faria muito melhor?

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".

3
BЈовић

Lembre-se deste mantra:

O perfeito é o inimigo do bem .

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.

  • Ele atende a todos os requisitos de funcionalidade e desempenho?
  • Está livre de erros críticos que você não pode corrigir na arquitetura atual?
  • Estime quanto trabalho você investirá para manter esse aplicativo no futuro. O esforço de reescrever seria maior do que o esforço de longo prazo que economizaria?
  • Existe a possibilidade de seu novo design realmente piorar as coisas?

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.

3
Philipp

Tentei planejar as coisas com antecedência, mas não consigo realmente prever tudo até começar a elaborar algum código.

É tentador pensar que o planejamento perfeito oferecerá um design/arquitetura de software perfeito, no entanto, isso é categoricamente falso. Há dois grandes problemas com isso . Em primeiro lugar, "no papel" e "o código" raramente correspondem, e o motivo é que é fácil digamos como deve ser feito, em oposição a 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 outros 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 acho que o Agile é um processo e uma bala de prata (do qual não é nem um). Leia o manifesto ágil, ouça as pessoas que começaram esse movimento como o tio Bob e Martin Fowler, e não seja sugado pela versão sem sentido do "corporate Agile".

Em particular, você geralmente pode se dar bem com o TDD (Desenvolvimento Orientado a Testes) em código científico , e há uma boa chance de que seu projeto de software acabe muito bem. 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 o seu software a ser ultra-utilizável , porque você escreve como deseja coisas a serem chamadas ( idealmente) antes de implementá-los. Também força pequenas funções com interfaces pequenas que podem ser chamadas rapidamente em 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 que o guia de referência de numpy recomenda explicitamente o TDD: https://docs.scipy.org/doc/numpy- 1.15.1/reference/testing.html . Eu usei 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 é bom usar depois você tem um = preliminar projetar e apenas "testar o primeiro desenvolvimento"). É importante pensar nos recursos e na estrutura do seu aplicativo antes saltando para o código. O TDD nunca o levará a um sistema distribuído e altamente disponível.

Como evitar sempre a sensação de que, se eu reconstruísse completamente meu programa do zero, faria muito melhor?

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ê pode realmente só chegue perto. Mesmo que você pense possa redesenhar do zero, provavelmente existem ainda requisitos ocultos que não se mostraram. Além disso, as reescritas demoram pelo menos enquanto quanto foi necessário para desenvolver o código original. Quase certamente não será mais curto, pois é provável que o projeto novo 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 (assumindo que seja totalmente funcional para os casos de uso atuais). Trabalhei em uma linha de base que possuía uma instrução de 22.000 comutadores de linha (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 reservar um 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ê pudesse se sair melhor ... mas valeria a pena reescrever? O que você ganhará?

HTH.

3
Matt Messersmith

Concordo plenamente com a resposta fornecida por Andreas Kammerloher, mas estou surpreso que ninguém ainda 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 (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.

2
Ister

Para adicionar as outras excelentes respostas aqui, uma coisa que acho útil é saber onde você deseja 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!

1
gidds

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, Java Script (<- Faça isso, é loucura), Vinculação de Modelo, Sem Sql, Recipientes , 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.

1
Marius

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. O sentimento vem do seu código não sendo direto.

Sua experiência foi minha por um longo tempo também, mas recentemente (nos últimos dois anos), tenho produzido mais código que não me faz sinto que preciso jogar tudo fora. Aqui está aproximadamente o que eu fiz:

  1. Seja claro sobre as suposições que qualquer bloco de código específico está fazendo. Lance erros se eles não forem cumpridos. Pense nisso isoladamente , sem depender de detalhes sobre o que o restante do software está fazendo. (O que o restante do software está fazendo influencia as suposições que você aplica e quais casos de uso são suportados, mas não influencia se você gera um erro quando uma suposição é violada.)
  2. Pare de acreditar que seguir regras, padrões e práticas produzirá um bom código. Jogue fora mentalidades e práticas que não são óbvias e diretas. Este era enorme. OO e TDD geralmente são ensinados de uma maneira que não se baseia em considerações práticas, como um conjunto de princípios abstratos que você deve seguir ao escrever código. Mas isso é totalmente inútil para o desenvolvimento de um bom código) Se você usar OO ou TDD), ele deverá ser usado como solução para os problemas que você entende que possui . Em outras palavras, eles devem ser usados ​​apenas quando você olha para um problema e pensa: "Ok, isso faz todo o sentido e é extremamente óbvio como uma boa solução". Não antes.
  3. Ao escrever código, concentre-se em duas perguntas:
    • Estou usando recursos e bibliotecas da maneira como foram projetados para serem usados ​​? Isso inclui usá-lo para os tipos de problemas que se destinava a resolver, ou pelo menos muito semelhantes.
    • É simples ? Meus colegas de trabalho e eu seremos capazes de seguir a lógica facilmente mais tarde? Existem coisas que não são imediatamente óbvias no código?

Meu código agora é mais "processual", com o que quero dizer que está organizado por quais ações são executadas em vez de quais estruturas de dados são usadas. Eu uso objetos em linguagens em que funções independentes não podem ser substituídas em tempo real (C # e Java não pode substituir funções em andamento, Python pode)). Eu tenho uma tendência para 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 Tuples para que a função original não fosse confusa com esses detalhes de implementação. ) Passo agora muito mais coisas como parâmetros para funções, em vez de ter uma função que se estende a algum outro objeto para buscá-la (o chamador busca ou cria em seu lugar e o passa.) Agora deixo mais comentários explicando as coisas. que não são óbvios apenas olhando para o código , o que torna mais fácil seguir a lógica de um método. Só escrevo testes em casos limitados em que ' estou preocupado 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 ok , 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ê tem para passar por um período em que as coisas estão uma bagunça, para que você tenha alguma experiência para aproveitar. 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.

1
jpmc26

Lembrando que seu tempo é limitado. E seu tempo futuro também é limitado. Seja no trabalho, na escola ou em projetos pessoais, quando se trata de código trabalhando, você deve se perguntar "está reescrevendo esse o melhor uso do meu tempo limitado e valioso?". Ou talvez "este é o uso mais responsável do meu tempo limitado"?

Às vezes a resposta será inequivocamente sim. 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.

0
Jared Smith

É uma parte completamente normal da aprendizagem. Você percebe erros à medida que avança.

É assim que você melhora e não é algo que você deve evitar.

0
mathreadler

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.

  • Seu design do zero acabou tão elegante quanto você esperava?
  • Sua solução é realmente exatamente o mesmo problema? Quais recursos você deixou de fora? Quais casos do Edge você perdeu?
  • Que lições suadas no projeto original você apagou na busca pela elegância?
  • Depois de adicionar novamente as peças que faltam ao seu design, é tão limpo quanto era sem elas?

Eventualmente, seu instinto mudará de pensar "Eu poderia reescrever esse sistema muito melhor" para pensar "a fragilidade desse sistema pode ser um indicativo de alguma complexidade que não é imediatamente aparente".

0
Maxpm