
Desde o início de 2018, sou o líder / chefe / desenvolvedor líder da equipe - chame como quiser, mas o ponto principal é que sou totalmente responsável por um dos módulos e por todos os desenvolvedores que trabalham nele. Essa posição me dá uma nova visão do processo de desenvolvimento, pois estou envolvido em mais projetos e participo mais ativamente da tomada de decisões. Recentemente, graças a essas duas circunstâncias, de repente percebi o quanto uma medida de entendimento afeta o código e o aplicativo.
O pensamento que quero expressar é que a qualidade do código (e o produto final) está intimamente relacionada ao quanto as pessoas que projetam e escrevem o código estão cientes do que estão fazendo.
Você pode estar pensando agora: “Obrigado, cap. Claro, seria bom entender o que você escreve. Caso contrário, com o mesmo sucesso, você pode contratar um grupo de macacos para usar teclas arbitrárias e se acalmar. " E você está absolutamente certo. Por conseguinte, tomo como certo: você percebe que é necessário ter uma idéia geral do que está fazendo. Isso pode ser chamado de nível zero de entendimento e não o analisaremos em detalhes. Analisaremos detalhadamente o que exatamente precisa ser entendido e como isso afeta as decisões que você toma todos os dias. Se eu soubesse essas coisas de antemão, isso me pouparia uma tonelada de tempo perdido e código duvidoso.
Embora você não veja uma única linha de código abaixo, ainda acho que tudo o que foi dito aqui é de grande importância para escrever código expressivo e de alta qualidade.
Primeiro nível de entendimento: Por que não funciona?
Os desenvolvedores geralmente chegam a esse nível nos estágios iniciais de sua carreira, às vezes até sem a ajuda de outras pessoas - pelo menos de acordo com minhas observações. Imagine que você recebeu um relatório de bug: alguma função do aplicativo não funciona, você precisa corrigi-lo. Como você vai agir?
O esquema padrão é assim:
- Encontre o trecho de código que causa o problema (como isso é feito é um tópico separado, eu o revelo em meu livro sobre código desatualizado)
- Faça alterações neste snippet
- Verifique se o bug foi corrigido e se não há erros regressivos
Agora vamos nos concentrar no segundo ponto - fazer alterações no código. Existem duas abordagens para esse processo. Primeiro: para investigar exatamente o que está acontecendo no código atual, identifique o erro e corrija-o. Segundo: vá para o toque - adicione, digamos, +1 a uma declaração ou loop condicional, veja se essa função funcionou no cenário certo e tente outra coisa e assim por diante ad infinitum.
A primeira abordagem está correta. Como Steve McConnell explica em seu livro Code Complete (a propósito, eu recomendo), toda vez que alterarmos algo no código, poderemos prever com segurança como isso afetará o aplicativo. Cito de memória, mas se a correção de bugs não funcionar como o esperado, você deve ser muito cauteloso, deve colocar em questão todo o seu plano de ação.
Resumindo o acima, para executar uma correção de bug sólida que não prejudica a qualidade do código, você precisa entender toda a estrutura do código e a origem de um problema específico.
Segundo nível de entendimento: Por que isso funciona?
Esse nível é compreendido muito menos intuitivamente que o anterior. Sendo um desenvolvedor iniciante, aprendi isso graças ao meu chefe e depois expliquei repetidamente a essência do assunto para iniciantes.
Desta vez, vamos imaginar que você recebeu dois relatórios de erros ao mesmo tempo: o primeiro é sobre o cenário A, o segundo é sobre o cenário B. Algo está errado nos dois cenários. Assim, você é levado primeiro para o primeiro bug. Guiados pelos princípios que introduzimos para o primeiro nível de entendimento, você aprofunda o código relevante para o problema, descobre por que ele força o aplicativo a se comportar exatamente como o do cenário A e faz ajustes razoáveis que fornecem exatamente o resultado que você deseja. esperado. Tudo está indo bem.
Então você vai para o cenário B. Você repete o script na tentativa de provocar um erro, mas - uma surpresa! - agora tudo funciona como deveria. Para confirmar sua suposição, você cancela as alterações feitas no processo de trabalho no erro A e o erro B retorna novamente. Sua correção de bug resolveu os dois problemas. Sorte!
Você não contou com isso. Você encontrou uma maneira de corrigir o erro no cenário A e não tem idéia do porquê funcionou no cenário B. Nesse estágio, há uma grande tentação de decidir que ambas as tarefas foram concluídas com êxito. Isso é bastante lógico: o objetivo era eliminar erros, não era? Mas o trabalho ainda não acabou: você ainda precisa descobrir por que suas ações corrigiram o erro no cenário B. Por que? Então, para que ele esteja trabalhando nos princípios errados, e você precisará procurar outro caminho. Aqui estão alguns exemplos desses casos:
- como a solução não pôde ser direcionada especificamente para o erro B, levando em consideração todos os fatores, você pode ter quebrado a função C. sem saber.
- é possível que em algum lugar o terceiro bug relacionado à mesma função também tenha se escondido, e sua correção de bug faça com que o sistema funcione corretamente no script B nele. Agora tudo parece bom, mas um belo dia esse terceiro bug será percebido e corrigido. Então, no cenário B, ocorre um erro novamente, e bem, se apenas lá.
Tudo isso introduz a aleatoriedade no código e um dia ele cairá na sua cabeça - provavelmente no momento mais inoportuno. Você terá que reunir sua vontade em um punho para se forçar a gastar tempo entendendo por que tudo parece funcionar, mas vale a pena.
Terceiro nível de entendimento: por que funciona?
Minha percepção recente está conectada precisamente a esse nível e provavelmente teria me proporcionado mais benefícios se eu tivesse chegado a essa ideia anteriormente.
Para tornar mais claro, vamos dar uma olhada em um exemplo: seu módulo deve ser compatível com a função X. Você não está particularmente familiarizado com a função X, mas foi informado que precisa usar a estrutura F. para compatibilidade com ela. Outros módulos que se integram ao X funcionam exatamente com ele.
Desde o primeiro dia de sua vida, seu código não entrou em contato com a estrutura F, portanto, não será tão fácil implementá-lo. Isso terá sérias conseqüências para alguns componentes do módulo. No entanto, você avança no desenvolvimento: escreva código por semanas, teste, implante versões piloto, obtenha feedback, corrija erros de regressão, encontre complicações imprevistas, não se enquadre no prazo originalmente acordado, escreva mais código, teste, opere conexão, corrigir erros de regressão - tudo isso para implementar a estrutura F.
E em algum momento você repentinamente percebe - ou talvez ouça alguém - que talvez a estrutura F não ofereça compatibilidade com a função X. Talvez todo esse tempo e esforço não tenham sido aplicados de todo para isso.
Algo semelhante aconteceu uma vez no decorrer do trabalho em um projeto pelo qual eu era responsável. Por que isso aconteceu? Porque eu mal entendi qual é a essência da função X e como ela se relaciona com a estrutura F. O que devo fazer? Peça à pessoa que define a tarefa de desenvolvimento que explique claramente como o plano de ação planejado leva ao resultado desejado, em vez de simplesmente repetir o que foi feito para outros módulos, ou que tome a palavra necessária para que a função X funcione.
A experiência deste projeto me ensinou a me recusar a iniciar o processo de desenvolvimento até termos um entendimento claro do motivo pelo qual somos solicitados a executar determinadas ações. Recusar texto sem formatação. Quando você recebe uma tarefa, o primeiro impulso é executá-la imediatamente, para não perder tempo em vão. Mas a política de “congelar o projeto até entrarmos em todos os detalhes” pode reduzir o tempo perdido em ordens de magnitude.
Mesmo que eles tentem pressioná-lo, forçá-lo a começar o trabalho, embora você não entenda como isso se justifica, resista. Primeiro, descubra o objetivo para o qual você está designado e decida se esse é o caminho certo para a meta. Tive que aprender tudo isso com uma experiência amarga - espero que, para quem lê isso, meu exemplo facilite a vida.
Quarto nível de entendimento: ???
Sempre há algo a aprender em programação, e suponho que apenas toquei nas camadas mais altas do tópico do entendimento. Quais outros níveis de entendimento você descobriu ao longo dos anos trabalhando com código? Que decisões foram tomadas que tiveram um bom efeito na qualidade do código e do aplicativo? Que decisões foram erradas e lhe ensinaram uma lição valiosa? Compartilhe suas experiências nos comentários.