Trabalhando no código de outra pessoa [fechado]


60

Eu tenho quase um ano de experiência em codificação. Depois de começar a trabalhar, na maioria das vezes eu trabalhava no código de outra pessoa, adicionando novos recursos aos existentes ou modificando os existentes. O cara que escreveu o código real não funciona mais na minha empresa. Estou tendo dificuldade para entender o código dele e fazer minhas tarefas. Sempre que tentei modificar o código, de alguma forma eu mexi com os recursos de trabalho. O que devo ter em mente enquanto trabalha com o código de outra pessoa?


103
Bem-vindo ao mundo real, onde o código vive para sempre e os programadores vêm e vão.

65
Não é o código de outra pessoa. É o seu código agora.
Buhb

6
@gnat novamente, isso pode ser apenas devido à inexperiência e falta de conhecimento dos OPs. se eu fui em função de um colega, apagado uma linha de código essencial, coloque referido código ao vivo e partiu-o, isso é até a minha negligência, não o código estruturalmente instável
rickyduck

19
@Buhb: Mas, de 6 meses a partir de agora, quando você voltar a ele, será código de outra pessoa, mesmo as partes que você escreveu ;-)
Jörg W Mittag

6
Seja feliz. Você está desenvolvendo uma habilidade crítica que o diferencia de pessoas com menos experiência ou apenas com experiência acadêmica. É suposto ser difícil. É por isso que é valioso.
Scott C Wilson

Respostas:


59

O código possui testes de unidade? Caso contrário, sugiro fortemente que você comece a adicioná-los. Dessa forma, você pode escrever novos recursos / correções de erros como testes com falha e modificar o código que o teste passa. Quanto mais você criar, mais confiança terá que seu código adicionado não quebrou mais nada.

Escrever testes de unidade para códigos que você não entende completamente o ajudará a entender o código. Obviamente, testes funcionais devem ser adicionados se ainda não existirem. Minha impressão foi de que eles já existiam na questão do OP. Se eu estiver errado nesse ponto, esses testes funcionais devem ser seu primeiro passo.

Eagle76dk faz um ótimo argumento sobre a contratação de seu gerente para fazer este trabalho - mais detalhes na postagem de Eagle76dk.

Além disso, à medida que você escreve esses testes, encorajo você a tentar escrever os testes para que eles verifiquem o comportamento comercial que o método pode ter tentado realizar, e não o comportamento do código. Além disso, não assuma que os comportamentos de negócios que você vê no código são os corretos - se você tem alguém que pode lhe dizer o que o aplicativo deve fazer, isso é, em muitos casos, mais valioso do que o que o código pode lhe dizer.


12
Escrevendo testes de unidade pode ser mais fácil dizer do que fazer, porém, dependendo do código e suas dependências ...
Svish

1
@ Smish: Bom ponto. Eu nunca impliquei que seria fácil, mas vale a pena fazer isso, mesmo que seja necessária alguma refatoração para tornar o código mais adequado para testes de unidade.
Sardathrion

46
Escrever testes de unidade no código existente é uma tarefa muito desafiadora e demorada, se o código não foi projetado para ele. Fazer isso em código que você não entende, para um iniciante, pode ser um trabalho muito pesado que nunca terminará. Seria uma maneira de começar a aprender o código, mas eu não diria que é a maneira óbvia de começar a aprender o código.
jake_hetfield

3
Os testes de unidade são melhor escritos durante o desenvolvimento. Caso você precise corrigir um erro e não entenda o design ou não tenha especificações, você poderá adicionar testes de unidade que aprovam os erros existentes. Às vezes, erros são características incorretas. Por isso, proponho estabelecer testes funcionais em vez de testes de unidade neste caso primeiro. Isso significa encontrar exemplos de usos que geram os resultados que o usuário aprova. Faça casos de teste escrevendo essas situações, ações e resultados detalhadamente. Se seus testes funcionais abrangerem todas as histórias de usuários e funcionarem após seus patches, você estará bem sem testes de unidade.
Alfe

2
Escrever testes de unidade é a abordagem de baixo para cima e levará uma quantidade imensa de tempo e, portanto, muitas vezes não é pragmático em grandes projetos. Escrever a coisa toda novamente pode ser mais rápido neste caso. Você pode encontrar (e precisar de tempo para corrigir) erros de unidade que não são importantes porque o caso nunca ocorre em um contexto funcional.
Alfe 23/05

46

Além de uma outra resposta que mencionou testes de unidade, sugiro que você verifique se tudo está no controle de versão para poder reverter suas alterações facilmente. E fazendo pequenas alterações para tornar o código mais sustentável.


11
Bom ponto, mas na verdade eu assumi meio que qualquer um hoje em dia usam (leia-se: deve usar) de controle de versão ...
Sardathrion

6
Você ficaria surpreso. Eu trabalhei como contratado em várias empresas em que apenas o corte final do código foi confirmado. Honestamente.
5arx

4
Para o argumento da 5arx: Se a cultura da empresa é apenas enviar código perfeito, é possível manter seu próprio repositório pessoal Git ou Mercurial. Isso é especialmente fácil se o controle de versão "real" da empresa for SVN.
Dustin Rasener

2
+1 e +1 ao comentário de 5arx. Eu fiz um trabalho de integração em REALMENTE grandes empresas, onde o sistema de controle de versão consiste em escrever a data, seu nome e um comentário no arquivo. Depois de ser usado no trabalho com o git, isso parece assustadoramente ineficiente e propenso a erros.
Leo

1
@Sardathrion Você sabe o que acontece quando você "ass u me" ...
WernerCD

32

Na minha opinião, a maneira mais rápida de aprender o código de outra pessoa (especialmente quando as mudanças desencadeiam um comportamento inesperado conforme você descreve) é percorrer o código usando um depurador .

Comece percorrendo o que parece ser o loop principal / métodos principais do programa. Use as funções de entrada e saída para ver o que os diferentes métodos fazem. Isso ensinará a estrutura geral do código.

Depois disso, divida e conquiste avançando e aprendendo as diferentes partes do programa em um nível mais profundo. Na maioria dos depuradores, você pode estudar variáveis e seus valores atuais . Estude como eles mudam e quando.

Defina pontos de interrupção nos métodos que acionam comportamentos que lhe dizem respeito. Por exemplo, se você estiver tentando alterar um texto no programa, e o texto voltar a mudar para o valor original, defina pontos de interrupção em todos os locais onde o texto foi alterado ou tente mover todas essas alterações para um único método. Use a pilha de chamadas para ver de onde esse método é chamado, etc.

Se alterar uma linha de código causar alterações inesperadas em outros lugares, coloque um ponto de interrupção nessa linha e veja o que acontece lá, por exemplo, verificando os valores das variáveis ​​atuais no escopo, usando step into ou a pilha de chamadas para ver de onde a ligação chegou.

Ao fazer isso muito, você começará a aprender a estrutura do código surpreendentemente rápido. Comecei como você fez nos meus primeiros trabalhos de programação, com muitos códigos que foram escritos há muitos anos e que foram alterados por muitas pessoas por muitos anos. O código não era meu apenas porque havia outras pessoas trabalhando nele ao mesmo tempo. Não pude reescrever tudo naquele momento. Escrever testes para todo esse código levaria meses ou anos. O depurador realmente me salvou, não sei como eu teria aprendido o código sem ele ...


3
Eu acho que essa é a única resposta realista, escrevendo testes de unidade para um aplicativo grande sem eles sua não prática
CommonSenseCode

Gostaria de poder votar mais de uma vez.
user949300

30

A primeira coisa a ter em mente é que é gasto mais tempo lendo código do que escrevendo código. Gaste tempo para entender como o outro cara trabalhava - seu estilo e abordagem para os problemas.

Tente adotar o estilo existente o máximo possível - caso contrário, o sujeito depois de você terá o dobro de ajustes para fazer.

Lidar com o código de outra pessoa é a norma, não a exceção. Você precisa descobrir como o outro indivíduo teria resolvido um problema ou implementado um recurso. Depois de fazer isso, você achará mais fácil lidar com o código dele.


21

Não seja rápido demais para assumir que o código do outro cara é ruim.

Mas sempre desconfie.

Mas sim, leva tempo para entender o código de outro desenvolvedor. Quanto mais uma função ou objeto é usado por várias partes do sistema, mais cuidado você precisa ter. Se você puder resolver o problema mais próximo do sintoma, isso às vezes pode ser útil. Por exemplo, normalize os dados recebidos de outro objeto no lado do objeto-problema após a entrega dos dados, mas antes que algo aconteça.

É um mau sinal quando mudar uma coisa quebra outra inesperadamente. Se você tiver outros desenvolvedores mais experientes nos quais possa contar com ajuda, recomendo que eles analisem as coisas que estão causando problemas. No mínimo, você pode pegar algumas coisas assistindo a depuração.


9
+1. Resista à tentação de reescrever blocos que você não entende - você quase certamente introduzirá novos bugs fazendo isso. Em vez disso, mova-se devagar e metodicamente pelo código, apenas fazendo alterações quando novas funcionalidades (ou correções de bugs) forem realmente necessárias.
C # # # # C Scott Scott Wilson

1
Eu diria várias vezes por ano que julgo mal. Acabei de fazer isso hoje e percebi que todos os 5 itens que eu achava problemáticos estavam lá por um motivo. Ele / eles poderia ter deixado eles mais claramente marcados, mas eu poderia ter perdido menos tempo assumindo que ele / eles não foram lá por um bom motivo.
precisa

14

Em um mundo ideal, todo o código escrito por um determinado desenvolvedor será bem documentado, bem estruturado e testado de maneira abrangente, tanto com ferramentas automáticas como testes de unidade quanto scripts de casos de uso que um usuário executa para verificar se você obtém o resultado esperado.

No entanto, a primeira coisa que você aprenderá é que não vivemos em um mundo ideal!

Muitos desenvolvedores não documentam seu código adequadamente, se é que misturam lógica de negócios com código não relacionado, e o único teste que eles fazem é uma rápida execução do que eles esperam ser o caso de uso normal.

Ao trabalhar com código como este, a primeira coisa que você precisa fazer é estabelecer o que ele deve fazer. Se houver comentários, eles podem fornecer pistas, mas não conte com isso. É minha experiência que muitos programadores não são bons em se explicar e, mesmo que deixem comentários, podem não ter sentido. No entanto, a menos que você seja o único codificador da empresa, alguém certamente deve ter pelo menos uma idéia básica de para que serve o código e o que ele deve fazer. Pergunte por aí!

Se você tiver testes de unidade, eles tornarão sua vida muito mais fácil. Caso contrário, parte do aprendizado da base de código pode envolver a escrita de testes de unidade para códigos que já existem. Normalmente, isso não é considerado uma boa prática, porque se você escrever testes de unidade para ajustar-se ao código existente, você terminará com testes de unidade que pensam que o código funciona como está (eles serão escritos para assumir que o comportamento que é realmente um bug é correto), mas pelo menos fornece uma linha de base. Se você descobrir mais tarde que algum comportamento que você achou correto está de fato errado, poderá alterar o teste de unidade para testar qual é o resultado esperado e não o resultado que o código fornece agora. Depois de fazer um teste de unidade, você pode fazer alterações e avaliar quais efeitos colaterais têm as alterações.

Finalmente, o melhor recurso que você tem ao lidar com um trecho de código não documentado é perguntar aos usuários finais. Eles podem não saber nada sobre código, mas sabem o que desejam que o aplicativo faça. A coleta de requisitos é o primeiro estágio de qualquer projeto, e conversar com os possíveis usuários do sistema a ser desenvolvido é sempre uma parte importante disso. Pense nisso como realizar o estágio de captura de requisitos para um novo projeto que, por acaso, já foi construído.

Lembre-se de que mesmo código bem escrito e bem documentado pode ser difícil para um estranho entender. Código é essencialmente uma expressão de como a pessoa que o escreveu estava pensando na época, e todo mundo tem seu próprio processo de pensamento. Você terá que aprender a ser um pouco paciente e a ser um detetive. Ser capaz de entrar no processo de pensamento de outra pessoa é difícil, mas é uma habilidade essencial para um programador que faz manutenção no código existente. Como a maioria das codificações (cerca de 70%) está relacionada à manutenção do código existente, é uma habilidade importante a aprender.

Ah, e agora que você viu a dor que um código mal documentado, não testado e confuso pode causar, você não fará isso com o próximo desenvolvedor ruim, certo? :) Aprenda com os erros do seu antecessor, comente bem seu código, verifique se todos os módulos têm uma responsabilidade claramente definida e se assegura de ter um conjunto abrangente de testes de unidade que você escreve primeiro (para metodologias TDD) ou pelo menos ao lado do código que está sendo desenvolvido.


13

Lembre-se de que a capacidade de ler código que você não escreveu é uma habilidade muito valiosa, provavelmente mais valiosa do que escrever código. Infelizmente, isso é amplamente subestimado e pouco ensinado nas escolas.

O que estou tentando dizer é que é normal que você nem sempre entenda o código ao lê-lo pela primeira vez (assim como é normal que você não escreva o código perfeito na primeira vez). Se você aceitar que leva algum tempo para obter um código estrangeiro, não se importará de fazer um esforço extra. Um pequeno resumo:

  • Os testes de unidade seriam ideais, mas nem sempre realistas; especialmente se você trabalha em uma grande organização com muita burocracia.

  • Aprenda a usar seu sistema de controle de versão corretamente; você nunca quebrará o existente ( nunca realmente , mas é uma boa rede de segurança).

  • Não assuma que é ruim simplesmente porque você não entende instantaneamente. Não assuma que é bom simplesmente porque funciona. O importante é que você entenda o estilo de código do mantenedor anterior e adapte suas linhas adicionadas ao estilo dele. O mantenedor que vem após você agradecerá por isso.

  • Infelizmente, em algumas empresas, a dificuldade de ler o código pode ser subestimada. Isso é comum em grandes corporações com processos rígidos. Eles geralmente (implicitamente) preferem que você insira códigos que funcionem rapidamente, em vez de levar algum tempo para escrever algo limpo. Deixarei que você decida onde sua equipe está nesse ponto.

  • Finalmente, nunca esqueça que ler código é uma habilidade . Quanto mais você fizer, melhor será. Outra maneira de dizer isso é que a única maneira de melhorar é praticar várias vezes. Como mencionado acima, a leitura do código é e será uma parte muito maior do seu trabalho do que a escrita.


11

A julgar pelos seus problemas com a quebra inadvertida de coisas, vou assumir que o código não é coberto por testes automatizados. O passo 0 seria encomendar e ler imediatamente Trabalhando efetivamente com o código herdado de Michael Feathers. É simplesmente inestimável.

Os passos básicos que eu sugeriria:

  • Cubra o código com testes que cobrem a funcionalidade atual.
  • Refatorar até que seja compreensível.
  • Escreva um teste para a funcionalidade nova ou modificada.
  • Implemente a nova funcionalidade.
  • Refatorar até a satisfação.

Eu deliberadamente deixo de fora a especificação do sabor dos testes (unidade, integração, ...) - apenas obtenha algum tipo de cobertura de teste automatizada.

(e, sim, siga o estilo de codificação em termos de layout e nomeação)


10

Como mencionado anteriormente: bem-vindo ao mundo real. Só posso concordar com respostas anteriores. Desejarei apenas estender a resposta com minha experiência de trabalho sobre estimativas de tempo.

Uma boa sugestão para deixar seu chefe claro: levará tempo para aprender como os outros desenvolvedores pensam. Geralmente, você perceberá que a solução atual geralmente depende da idade e da experiência do desenvolvedor.

Se você tiver sorte, a tarefa em questão deverá ser analisada e a compreensão da documentação o ajudará muito (mas esse geralmente não é o caso).

Minha experiência é que, ao modificar o código de outras pessoas, tente não alterar o código que não envolve sua tarefa atual. Você pode conhecer uma solução melhor ou ela pode ser escrita de uma maneira mais intuitiva, mas alterá-la geralmente leva a problemas como:

  • A tarefa levará mais tempo e seu chefe não a entenderá.
  • O código que você altera deve ser testado e custa. A solução atual foi testada e aprovada.
  • Será difícil ver quais mudanças solucionam a tarefa atual e quais são as correções "justas".

Mas não hesite em dizer ao seu chefe, se você vir algo que acha que deveria ser diferente (apenas mostra que você pode pensar).

Por fim, verifique se você tem tempo suficiente para fazer a solução. Uma solução mais rápida vem com a experiência. Porém, raramente existe uma solução rápida, pois esse é o primeiro / principal motivo de erros e código não sustentável.


5

Pense nisso como executar uma operação em uma pessoa.

Você examina o problema que precisa corrigir e percebe que a maioria das artérias etc. não está configurada da maneira que faria - então você as corta e corta até parecer certo para você e depois corrige o problema.

Surpreendentemente, seu paciente morre quase imediatamente.

Aplicativos herdados são os mesmos. Eles já têm uma maneira de trabalhar - você precisa entender os vários componentes do software e como eles se relacionam e, em seguida, fazer as alterações para que funcionem da mesma maneira. Não é empolgante deixar sua criatividade ir solta, mas você pode fazer isso em projetos pessoais.

Eu pediria a um engenheiro sênior que se sentasse com você por mais ou menos uma hora toda segunda-feira e explicasse um aspecto diferente do sistema. Faça anotações do que ele diz e envie-as por e-mail para ele e seu gerente para ver se ele tem algo a acrescentar. Você deve acelerar muito rapidamente dessa maneira.

Quanto a como não quebrar as coisas, primeiro certifique-se de entender o que o sistema faz. Teste antes - faça sua alteração - teste depois. Não há fórmulas mágicas; À medida que você ganha experiência, melhora - ou demitido, eu acho!


3

Uma coisa que eu realmente não vi tocada aqui - não trabalhe em uma ilha.

A menos que você seja o único programador em sua equipe, é provável que haja alguém que tenha mais experiência que você e, possivelmente, muitas pessoas nas quais você possa se apoiar.

Pergunte. Muitos deles.

Não se preocupe em "incomodar" alguém (dentro do razoável) - prefiro que alguém me interrompa por uma ou duas perguntas durante um ciclo de desenvolvimento normal, do que ter que apagar um incêndio em um ambiente de produção mais tarde.

Quando estiver pronto para fazer o check-in, revise-o com seu (s) mentor (es). Eles devem ser capazes de dizer não apenas se algo irá quebrar outra coisa, mas, mais importante, por quê. A revisão do código também tornará o mentor um programador melhor, dando-lhe uma visão do sistema que, de outra forma, eles não poderiam ver com tanta frequência.

Lembre-se: você não está apenas aprendendo o sistema como qualquer novo funcionário precisaria, mas também aprendendo a se tornar um programador.

E, cinco anos depois, incentive o próximo novato a usá-lo como mentor.


2

Quando se trata de código de depuração, lembre-se: sempre há uma razão . Quando você tenta encontrar e corrigir o mesmo bug estúpido há alguns dias e não está fazendo nenhum progresso, é tentador começar a pensar em um ou mais dos seguintes itens:

  • Eu apenas não sou inteligente o suficiente para descobrir como esse código funciona

  • O cara que escreveu esse código não tinha ideia do que estava fazendo

  • A magia está envolvida: magia muito negra

Essas são todas as formas de desistir. O antídoto é lembrar sempre que os computadores são determinísticos: sempre há uma razão para o que eles fazem. O código pode cheirar a maré baixa em uma fábrica de conservas de peixes e se assemelhar a uma tigela gigante de linguine, mas , sendo implacavelmente racional e mantendo a mente aberta, você descobrirá .


1

Se você escreve testes de unidade sempre que possível ou escreve pequenos aplicativos que envolvem o código que está sendo modificado, será necessário examinar, entender e documentar a lógica.

Se o código funcionar principalmente - parece que funciona -, eu preservaria o estilo da formatação do código para esse módulo, seja seu estilo ou não. Mantém as coisas uniformes. No entanto, bons comentários nunca saem de moda.

Aconselho um sistema de teste e plataforma de teste, onde você pode modificar e testar esse código, sem interromper a produção.

Se você pode remover elementos do código em uma biblioteca, eu o faria, a menos que você esteja trabalhando em uma biblioteca.

Com o tempo, depois de entender a lógica, você pode reescrever e testar.

Esse conselho é orientado pelo idioma que você está usando, pela capacidade de conseguir uma cama de teste e por outras restrições que você possui.


"bons comentários nunca saem de moda" ... a menos que o código seja alterado. Embora os comentários às vezes sejam úteis, sempre leve-os com um balde de sal - você precisará verificar se o código realmente faz o que o comentário diz. Com frequência, alguém altera uma linha de código, mas deixa um comentário existente - e agora irrelevante -.
dj18

1
@ dj18 Concordou, e limpar os comentários antigos faz parte da escrita do código. Estou dizendo para manter o formato - se possível - de uniformidade, mas comentar não é uma coisa ruim.
Octopusgrabbus 23/05

1

Tente usar algumas ferramentas do analisador de código para encontrar o código não utilizado que pode ser excluído - para que você não precise se preocupar com esse código.


1

Foi observado acima que você precisa entender a finalidade do sistema, não apenas os detalhes do código. Um programador com experiência suficiente para escrever um sistema de entrada de pedidos geralmente fica à vontade com a parte 'avançando', que envolve a seleção de produtos, a formatação de uma fatura e o processamento do pagamento. Eles ficam presos quando o usuário decide 'não se importe' e começa a fazer o backup das transações, ou quando comete um erro no processamento do pagamento e pressiona o botão 'voltar'. Nesse ponto, muitos programadores ficam confusos, porque veem o código 'aparecendo do nada' e não conseguem descobrir por que estão lá.

Em resumo, você precisa entender não apenas o 'fluxo normal', mas todo o retorno necessário se alguém cometer um erro ou mudar de idéia. Isso fica ainda pior com as substituições do supervisor, em que algum código pode ser executado apenas com certos privilégios de conta.

Se alguém escreve 10.000 linhas de código por ano e um aplicativo tem uma vida útil de dez anos, um programador responsável por pegar o trabalho de outra pessoa pode precisar entender 100.000 linhas de código. Divida isso por 50 linhas por página e 2000 páginas. Se o programa for gravado em um padrão de design, o programador descobrirá que o entendimento de um 'bloco' leva a pelo menos um entendimento geral da maior parte do restante. Caso contrário, é necessário ler toda a última linha.

Alguns programadores "apenas fazem o que lhes dizem" e escrevem espaguete. Eles nunca entendem o "quadro geral" - eles simplesmente corrigem quando os usuários reclamam. Em tal circunstância, é uma boa ideia começar a migrar o que puder para um padrão apropriado. Eventualmente, isso pode significar recodificar coisas que não estão "quebradas". Não se preocupe, verifique se o projeto é progressivamente mais sustentável.


0

Há algumas respostas muito legais aqui. Mas acho que também vale a pena mencionar o quanto a familiaridade com bons padrões de design pode ajudar, a ler (bem escrito) código existente e a escrever código legível.

É claro que pode ser muito confuso quando você encontra um SomethingFactorycódigo existente, que não segue o padrão de fábrica . Mas, tanto quanto sua equipe e sua estrutura permitem, pode ser benéfico manter esses casos no mínimo.

Os padrões de design a seguir (onde as necessidades da empresa permitirem) também podem reduzir significativamente a duplicação de código, o que, por sua vez, reduz os bugs em futuras modificações.

Algumas boas fontes de padrões de design são

http://sourcemaking.com/design_patterns

http://www.oodesign.com/

e, claro, o livro

http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612


0

Rastrear o fluxo de controle entre métodos é muito importante no desenvolvimento de um mapa mental da lógica de negócios.

Nossa solução é baseada no reconhecimento de que uma das poucas informações confiáveis ​​disponíveis ao abordar um sistema legado é o próprio sistema em execução. Nossa abordagem reifica os rastreamentos de execução e usa a programação lógica para expressar testes neles.

Gerar um modelo de dados de fluxo de trabalho é a melhor maneira de analisar todos os caminhos de código:

Na prática, a revisão de código se torna pesada nos fluxos de trabalho científicos herdados. A origem de tais fluxos de trabalho significa que as práticas de engenharia de software podem não ter sido aplicadas durante o desenvolvimento, levando a uma base de código que é efetivamente ofuscada. Embora a análise estática tenha desenvolvido técnicas para análise de fluxo de dados, elas não suportam o comportamento nos fluxos de trabalho do mundo real. Por exemplo, quando um arquivo de configuração deve ser carregado para determinar como os dados devem ser processados ​​ou quando a avaliação dinâmica de código é usada.

E visualizar o fluxo de trabalho é ideal:

Um motivo comum, que se presta ao desenvolvimento visual, é a apresentação de um fluxo de trabalho como um gráfico. Isso protege o usuário da complexidade subjacente de recursos e execução

Referências


-1

Verifique se você está usando um programa que ajuda a encontrar informações no arquivo atual. Nada é pior do que saber o que você está procurando no arquivo atual, mas você rola e rola e não consegue encontrá-lo. Uma exibição de estrutura de tópicos na ferramenta usada para editar o código realmente ajuda com esse problema.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.