Práticas recomendadas para entrega de código legado


66

Dentro de alguns meses, um colega estará migrando para um novo projeto e eu herdarei um de seus projetos. Para preparar, já encomendei o trabalho efetivamente de Michael Feathers com o código legado .

Mas esses livros, assim como a maioria das perguntas sobre o código herdado que encontrei até agora, preocupam-se com o caso de herdar o código como está. Mas, neste caso, eu realmente tenho acesso ao desenvolvedor original e temos tempo para uma entrega ordenada.

Alguns antecedentes do trecho de código que herdarei:

  • Está funcionando: não há bugs conhecidos, mas à medida que os requisitos de desempenho aumentam, algumas otimizações serão necessárias em um futuro não muito distante.
  • Não documentado: existe praticamente zero documentação no nível do método e da classe. O que o código deve fazer em um nível superior, no entanto, é bem compreendido, porque eu tenho escrito contra sua API (como uma caixa preta) há anos.
  • Somente testes de integração de nível superior: Existem apenas testes de integração que testam a interação adequada com outros componentes por meio da API (novamente, caixa preta).
  • Nível muito baixo, otimizado para velocidade: como esse código é central para todo um sistema de aplicativos, muitos deles foram otimizados várias vezes ao longo dos anos e são extremamente baixos (uma parte possui seu próprio gerenciador de memória para determinadas estruturas) / registros).
  • Concorrente e sem bloqueios: Embora eu esteja familiarizado com a programação simultânea e sem bloqueios e tenha contribuído com algumas partes para esse código, isso adiciona outra camada de complexidade.
  • Grande base de código: esse projeto em particular tem mais de dez mil linhas de código, então não há como eu ter tudo explicado para mim.
  • Escrito em Delphi: Eu vou colocar isso lá fora, embora eu não acredite que o idioma seja pertinente à questão, pois acredito que esse tipo de problema seja independente do idioma.

Fiquei me perguntando como seria o tempo até a partida dele. Aqui estão algumas idéias:

  • Obter tudo para compilar na minha máquina: mesmo que tudo deva ser verificado no controle do código-fonte, quem não se esqueceu de fazer o check-in de um arquivo de vez em quando, então essa provavelmente deve ser a primeira ordem de serviço.
  • Mais testes: Embora eu queira mais testes de unidade no nível de classe, para que, quando eu fizer alterações, quaisquer bugs que eu introduza possam ser detectados desde o início, o código atual não é testável (classes enormes, métodos longos, muitos dependências mútuas).
  • O que documentar: Eu acho que, para começar, seria melhor focar a documentação nas áreas do código que seriam difíceis de entender, por exemplo, devido à sua natureza de baixo nível / altamente otimizada. Receio que existam algumas coisas que possam parecer feias e que necessitem de refatoração / reescrita, mas na verdade são otimizações que estão por aí por uma boa razão de que eu possa sentir falta (cf. Joel Spolsky, Coisas que você deveria Nunca faça, parte I )
  • Como documentar: Eu acho que alguns diagramas de classe da arquitetura e de seqüência de funções críticas acompanhadas de uma prosa seriam os melhores.
  • Quem documentar: Eu queria saber o que seria melhor, que ele escrevesse a documentação ou que ele me explicasse, para que eu possa escrever a documentação. Receio que coisas que sejam óbvias para ele, mas não para mim, não sejam cobertas adequadamente.
  • Refatoração usando programação em pares: isso pode não ser possível devido a restrições de tempo, mas talvez eu possa refatorar parte de seu código para torná-lo mais sustentável enquanto ele ainda estava por perto para fornecer informações sobre por que as coisas são do jeito que são.

Por favor, comente e adicione a isso. Como não há tempo suficiente para fazer tudo isso, estou particularmente interessado em como você priorizaria.

Atualização: Com o término do projeto de transferência, expandi esta lista com minhas próprias experiências nesta resposta abaixo .


2
Concentre-se em documentar o porquê das funções otimizadas!

Espero que o código esteja sob controle de origem. Nesse caso, você se beneficiará dos comentários inseridos para cada alteração (se houver).
Bernard

Boa decisão sobre o uso eficaz de Michael Feathers com o código legado. Definitivamente, é necessário começar a escrever esses casos de teste nos módulos que você acha que provavelmente precisam de modificação. Se você começar agora, será mais fácil obter as expectativas corretas.
Bill Leeper

Há uma fase antes da refatoração, na qual tenho dúvidas para que a Internet pareça pobre em respostas: O que os principais programadores fazem para entender o código complicado e ilegível de outra pessoa?
Sergiol #

Respostas:


25

Como você tem acesso ao desenvolvedor que você codifica, pergunte: -

  • Quais módulos foram os mais difíceis de codificar / implementar. Quais foram os problemas e como eles foram superados.

  • Quais módulos geraram mais erros.

  • Quais módulos resultaram nos bugs mais difíceis de resolver.

  • De quais partes do código ele mais se orgulha.

  • Quais pedaços de código ele realmente gostaria de refatorar, mas ainda não teve tempo.

Essas perguntas fornecerão uma visão sobre o que causará mais problemas e, talvez mais importante, uma identificação dos processos de pensamento e das perspectivas do desenvolvedor original.


Eu gosto da ideia de escolher as partes que você mencionou. Intuitivamente, eu teria seguido de cima para baixo, mas dessa forma as partes mais desagradáveis ​​enterradas no código podem não ter surgido até muito tarde, talvez muito tarde no processo. Seu caminho faz mais sentido, eu acho. Você tem alguma sugestão para a parte "como documentar"? UML? Texto?
PersonalNexus

@PersonalNexus. Você também pode levar essa abordagem para a documentação. Pergunte quais documentos são mais úteis e quais não são confiáveis ​​ou desatualizados (acredite em mim 95% da documentação se enquadra na última categoria!).
James Anderson

17

Como o projeto de entrega está encerrado, acho que daria um tempo e escrevia minha própria resposta contendo as coisas que funcionaram melhor para mim.

  • Obtenha tudo sob controle de versão: Depois de me certificar de que tudo o que eu precisava construir estava sob controle de versão, também procurei no disco rígido do desenvolvedor antigo, procurando scripts ou utilitários adicionais que seriam úteis para implantar e / ou testar o aplicativo, mas não estavam. fez check-in.
  • De cima para baixo: eu começaria com uma análise de alto nível das principais turmas e uma visita guiada ao antigo desenvolvedor das principais áreas. Então eu me aprofundava no resto por conta própria, sinalizando coisas que não faziam sentido para mim com //TODOmarcadores.
  • Escreva toda a documentação: Enquanto o antigo desenvolvedor examinava minha redação para ter certeza de que estava certo, insisti em escrever tudo sozinha. Dessa forma, eu teria certeza de que a escrita fazia sentido para mim e não apenas para o antigo desenvolvedor.
  • Comentários em todos os lugares: adicionei resumos de documentação XML a todas as classes e métodos. Dessa maneira, assegurei-me de ter, pelo menos, analisado cada pedaço de código e ter entendimento suficiente para resumir o que ele fazia em uma frase. Também facilitou o entendimento dos métodos usando métodos / classes resumidos, pois o IntelliSense coleta essas informações. Também pude identificar facilmente áreas do código que ainda precisava examinar.
  • Documento próximo à fonte: para facilitar a conexão entre o código fonte e a documentação, coloquei a maior parte da minha documentação diretamente no código fonte. Para documentação de alto nível que descreve a interação entre vários subsistemas, usei um wiki, pois colocar essas informações em apenas um lugar no código não funcionava. Toda a documentação deve ser eletrônica e pesquisável em texto completo.
  • Diagramas: Para uma visão geral básica, usei diagramas de classes de várias granularidades para os diferentes subsistemas. Para as partes concorrentes, os diagramas de objeto e interação foram realmente úteis; veja também minha outra pergunta sobre o tópico .
  • Refatoração como um par: Enquanto eu fazia alguma refatoração com o desenvolvedor antigo para ter uma ideia do código e tornar as coisas mais fáceis de manter, esse foi um processo demorado e também arriscado, devido à falta de boas ferramentas de refatoração e a várias desagradáveis dependências entre as várias partes. O trabalho eficaz de Michael Feathers com o código legado é uma ajuda muito boa para isso, mesmo que a refatoração sem o suporte adequado da ferramenta ainda seja dolorosa. Enquanto refatorava, deixava que ele controlasse o mouse e o teclado, pois era mais divertido para ele (veja também meu último ponto) e eu estava livre para escrever o que estava aprendendo.
  • Check-ins separados para comentários e alterações: depois de introduzir um erro acidentalmente, escrevendo um comentário sobre um override, tomei o cuidado de fazer comentários e alterações em check-ins separados. Usei um pequeno utilitário para remover todos os comentários do código-fonte antes de fazer o check-in, para que um diff de um check-in somente para comentários mostrasse 0 diferenças. Todas as alterações (por exemplo, remoção de campos não utilizados) foram cuidadosamente revisadas por pares com o desenvolvedor antigo para garantir que eu não estivesse removendo as coisas que ainda eram necessárias.
  • Passo a passo linha por linha de passagens críticas: Para as passagens mais otimizadas / complexas, eu passaria o código linha por linha com o desenvolvedor antigo e, às vezes, até com um terceiro colega. Dessa maneira, eu compreendi completamente o código e, à medida que mais pessoas examinavam o código, identificamos alguns bugs e algumas coisas que poderiam ser otimizadas ainda mais.
  • Seja rápido e mantenha o desenvolvedor antigo motivado: notei que o desenvolvedor antigo estava cada vez menos interessado, pois seu último dia estava se aproximando (não surpreendentemente). Portanto, garantiria que as partes mais críticas fossem entregues primeiro, deixando o resto para eu descobrir por conta própria, se necessário. Eu também tentei deixar as coisas mais divertidas (por exemplo, controle do teclado ao programar em pares) para ele e fazer as coisas chatas, como documentação, escrevendo sozinho.
  • Identificar solicitações de recursos: achei útil solicitar ao desenvolvedor antigo uma lista de recursos solicitados pelas pessoas, mas que ainda não foram adicionados. Havia algumas coisas que para mim pareciam simples de adicionar, mas havia um bom motivo para não serem adicionadas, pois teriam quebrado outras coisas quando implementadas da maneira que eu pensava inicialmente.

14

Tendo estado em uma situação semelhante, acredito que também vale a pena considerar o seguinte:

  • Certifique-se de poder fazer e testar uma implantação: faça sua própria implantação do produto, a partir do zero - e verifique se isso é idêntico ao realizado pela pessoa que está saindo. Isso garantiria que todos os scripts e instruções sejam claros para você e capturaria omissões acidentais, como ingredientes que não foram registrados no sistema de controle de versão. (Não estou dizendo que isso iria acontecer, apenas que, se tiver acontecido, será muito mais fácil lidar com isso agora, antes que a pessoa saia)

    (Isso pode não ser relevante para você, por exemplo, se você já faz Integração Contínua ou Implantação Contínua, mas vale a pena mencionar, apenas no caso ...)

  • Escrevendo mais testes: Essa é uma maneira muito boa de testar sua compreensão de um sistema. Isso permitirá (ou forçará) você a examinar mais de perto as áreas do código e confirmará que o código está tão livre de erros quanto você suspeita, ou revelará áreas nas quais você pensou ter entendido a intenção, mas na verdade você precisa pedir esclarecimentos ao seu colega antes que ele saia

  • Escrita em pares da documentação: Esta é uma maneira eficaz de escrever visões gerais. Eu estou sugerindo que você começa o seu colega para descrever uma característica ou área, e, em seguida, você escrevê-la, na documentação, em suas próprias palavras. Descobrimos que isso era muito mais fácil quando feito por duas pessoas juntas.

Eu colocaria a escrita dos testes como uma prioridade mais alta do que a escrita da documentação, pessoalmente, pois os testes provavelmente lhe darão um entendimento mais firme.

Com relação à refatoração usando programação em pares , a única coisa que eu diria é que existe o perigo de que isso se torne um poço sem fundo, especialmente porque você disse que só tem testes de alto nível. Você pode achar que acaba gastando muito mais tempo disponível do que pretendia.


+1 mais testes. nunca há testes suficientes.
Sardathrion

10

+1 nas respostas que você já tem na sua pergunta!

Tour guiado
10k linhas de código é muito, mas acho que ainda não é impossível que o outro cara faça um 'tour guiado'. Você se senta junto à frente do código e ele o leva em uma viagem de cima para baixo, trabalhando as 'camadas'. Você precisaria fazê-lo em breves rajadas - tudo de uma só vez mataria vocês dois.

Ampliar, diminuir o zoom
A vantagem de fazer isso é que, enquanto ele está explicando para você, ele quase certamente terá alguns momentos "oh, sim, também existem" momentos que ele talvez não tivesse se estivesse apenas tentando documentá-lo por conta própria. E suas perguntas ajudarão a focar nos bits óbvios para ele, mas não para mais ninguém. Esse tipo de interação de zoom in / zoom-out é possível apenas um a um, tentando escrever ou ler algo assim é pesado.

Documentação
Acho que vocês dois devem documentar independentemente as coisas - ele deve começar de baixo (caso você não tenha tempo para chegar lá juntos), e você deve começar de cima, com base no que entendeu sua visita guiada e como se fosse para outra pessoa [em um trabalho anterior, herdei um monte de código 'legado', e só tive tempo de documentá-lo antes de me deixar :)].

Cadê o que?
O objetivo da maior parte disso é que você possa ter uma idéia de onde as coisas acontecem. Portanto, devido a um bug ou modificação específica, você pode encontrar rapidamente o local no código em que precisa se concentrar. Você pode testar a si mesmo pegando a lista de bugs antigos e ver se consegue prever com precisão onde estava o problema.

Deixe-o secar
Não importa se ele acaba te odiando (sorria), seu trabalho é obter o máximo de informações possível do cérebro desse cara no tempo disponível. Certifique-se de ter o gerenciamento do seu lado e que eles priorizem a transferência de conhecimento em vez de "apenas consertar os últimos bugs antes que ele saia" (a menos que você os conserte ...).


+1 para tentar corrigir alguns velhos erros me para testar o meu entendimento do código
PersonalNexus

11
"Não importa se ele acaba te odiando" - cuidado, "é um mundo pequeno";)
retracile 10/11/11

Além disso, abra um documento do Word e documente tudo, incluindo uma tonelada de capturas de tela. Isso me salvou muitas vezes quando você está em um estado de sobrecarga de informações!
Ben Power

7

Sugiro o seguinte (além do que já foi identificado) - Primeiro, peça ao seu gerente que lhe dê tempo para trabalhar com esse sujeito o máximo possível e tente sentar-se com ele sempre que ele tiver a tarefa de fazer uma alteração. Você não precisa saber tudo o que ele está fazendo, mas tente pegar o máximo que puder. O mais importante é ser amigo dele.

Trate a entrega como um projeto, coloque um plano em prática e envolva o gerenciamento.

0 - Verifique se você sabe como usar o sistema.

1 - Faça um inventário claro dos componentes da solução, a origem de cada um e onde está (em repositórios diferenciados)

2 - Obtenha e, se possível, gerencie as senhas dos diferentes servidores a partir de agora. Verifique se você tem todas as informações da conta de administrador

3 - Obtenha as licenças de cada componente externo, a menos que esteja fora do seu escopo (por exemplo, dlls especiais, banco de dados, etc.)

4 - Obtenha um relatório por escrito do desenvolvedor e de seus clientes sobre o status atual do sistema (se eles forem locais da sua empresa)

5 - Obtenha a documentação para as regras de negócios, fórmulas de cálculo, etc. Você pode fazer isso com ele. Peça a ele e-mails, informações sobre reuniões, documentos de requisitos do usuário, documentos de design e similares para serem fornecidos a você.

6 - Obtenha uma lista de eventos agendados (execuções mensais de trabalhos, execuções semanais de trabalhos) aos quais o software deve responder

7 - Aprenda os procedimentos de backup / restauração

8 - Entenda as estruturas usadas na criação do aplicativo

9 - Conheça as modificações solicitadas / esperadas / planejadas e o status de quaisquer solicitações de usuário pendentes. Comece tentando identificar como fazer isso sozinho.

10 - Verifique se seus ambientes de teste e desenvolvimento são muito semelhantes.

11 - Tente identificar as principais dependências (em outros sistemas ou entre componentes) que não podem ser facilmente identificadas.

12 - Identifique e documente as versões necessárias de cada uso de software e seu contato com o fornecedor (se necessário)

13 - Identifique as ferramentas especiais que ele estava usando e que você não possui, caso isso possa ajudá-lo.

14 - Obtenha um fluxo de sistema de alto nível. e comece a construir sua biblioteca de documentação

15 - Entenda como gerenciar a segurança do usuário para o aplicativo

16 - Obtenha o log de erros e tente entender as ações e como a ação afetou os dados mais antigos (se aplicável)

17 - Conheça os processos que demoram muito e o que você precisa observar (por exemplo, tamanhos incomuns de arquivos, ftp de arquivos duplicados etc.) onde aplicável.

18 - Verifique o relógio do servidor de produção

19 - Identifique onde estão as configurações e compare cada configuração do ambiente com a produção para saber quais parâmetros são diferentes e por que

20 - Obtenha as informações de contato desse cara

21 - Se o sistema for interno, agende uma reunião com os usuários do sistema (você precisa saber quem eles são e qual o papel de cada um) e seja apresentado a eles. Ouça o que eles têm a dizer sobre o sistema e sobre os problemas atuais, se houver. Certifique-se de ser incluído nos e-mails o mais cedo possível (após a aprovação do gerente)

22 - Avalie sua compreensão 1 semana antes de ele sair e relate qualquer problema que considere um risco

Como você mencionou que não possui um banco de dados, essa lista ficou mais curta.

Boa sorte.


@ SSamra: Obrigado pelo comentário de levantamento. Eu precisava disso. :)
NoChance

Muito exaustivo e incluindo alguns pontos importantes que eu poderia ter perdido de outra forma, por exemplo, envolvendo a gerência e nossos clientes (internos).
PessoalNexus

5

Eu consideraria as partes mais complicadas e otimizadas para desempenho primeiro. Eu faria com que ele primeiro documentasse essas partes e as explicasse uma por vez, depois tentaria escrever testes nessas partes (incluindo antes e depois dos testes de desempenho, para que você possa ver se uma nova otimização melhora ou piora as coisas ) e peça à outra pessoa que revise os testes. Dessa forma, ele documenta e explica, você usa a explicação para escrever testes (enquanto ele está documentando uma área diferente), e a revisão dele ajudará a garantir que você entenda o que deveria estar testando. Dessa forma, você também obtém uma média de teste adicional para algumas das partes mais críticas do aplicativo e da documentação das otimizações de desempenho especializadas.

Se houver tempo depois de abordá-las, eu passaria por um processo semelhante com as partes do aplicativo que mais frequentemente precisavam de mudanças ao longo dos anos, mas que não estão no primeiro grupo de coisas documentadas.

Em seguida, documente tudo o que resta.


5

Eu acho que a melhor maneira de obter algum código grande é a abordagem de cima para baixo. Tente entender o quadro geral primeiro e, em seguida, vá gradualmente mais fundo nos componentes, um por um.

Agora, em cada nível de escavação, peça a ele que priorize as partes que precisam de mais atenção. Peça que ele o explique o máximo possível, mas sempre documente você mesmo.

A melhor parte de documentar você mesmo é que, quando voltar mais tarde, não terá problemas em lembrar o mesmo estado cognitivo em que se encontrava, quando ele lhe explicou. Você pode entender muito mais facilmente o que escreveu do que outra pessoa. Na minha experiência, duas pessoas que documentam o mesmo pedaço de código não produzem partes de texto com aparência semelhante.

Acho que isso também resolve seus problemas de "o que e como documentar". Quando ele explica tudo, você pode decidir o que deseja que seja documentado quando retornar ao código - e documentar apenas essas partes.

A idéia é primeiro entender completamente o código (na presença dele) e, em seguida, escrever / fazer tudo o que permitirá que você o faça depois (na ausência dele).

Ao entender completamente o código, quero dizer que você precisa ter uma ideia geral - e como cada componente se relaciona com essa imagem geral. Eu achei particularmente útil acompanhar como cada peça soma o todo. Não tente compreender nada isolado - nunca perca a visão de seu contexto.

Por fim, depois de fazer o acima, assuma o controle proativamente. Decida-se para quais peças você precisa de cobertura de teste de unidade. que partes precisam ser (ou podem ser) otimizadas, como você pode refatorar algum componente, etc. Confie que, se você conhece o sistema, pode tomar todas as decisões depois que ele se for.


como você deve documentar isso? texto simples ? wiki? comentários no código fonte?
c69 8/11/11

Qualquer coisa que permita restaurar o mesmo entendimento do código que você tinha quando estava escrevendo os documentos.
treecoder

5

Sinto por você.

Algumas sugestões:

  1. Grave todas as conversas que tiver com o programador que está saindo!
  2. Peça a motivação por trás das "grandes" questões. É bom que você entenda a API, mas procure as decisões internas - por que o código foi particionado? quais são as responsabilidades.
  3. Faça um esforço para realmente estudar o código. Quando você assume tarefas de manutenção e suporte, às vezes há pressão para "estudar o código enquanto progride". Resista, se puder, e realmente estude o código.
  4. Procure por cenários. Você conhece a API - veja como o código se comporta. Um exemplo que vem à mente é o de um módulo de fax. Como usuário da API, você precisa preparar previamente uma imagem da página e enviar ao código um comando para transmitir a página. Peça ao programador de saída que rastreie com você o código para ver como esse cenário é realizado. Então, é claro, vá para o cenário "página de recebimento".
  5. 80/20 - tente cobrir os cenários mais comuns primeiro.
  6. Considere uma reescrita. Se o código for antigo e as interfaces estiverem bem definidas, talvez a tecnologia tenha mudado o suficiente para justificá-lo.
  7. Detesto dizer isso, mas considere procurar um novo emprego.

Eu gosto da ideia de gravar todas as conversas, para que eu possa voltar às suas palavras originais, depois que ele se for. Sugestão # 7, no entanto, não é uma opção ;-)
PersonalNexus

3

Se você quiser uma documentação decente e razoavelmente indolor, compre uma cópia do Pascal Analyzer (PAL) , usei isso em projetos Delphi e foi ótimo - eles agora podem ter dividido a funcionalidade da documentação em um produto com o qual não estou familiarizado (Pascal Browser) então você pode ter que comprar os dois (<300 USD), mas o PAL foi uma ótima ferramenta para entender onde as variáveis ​​estavam sendo usadas, onde as funções estavam sendo chamadas, etc.

Use o PAL para ter uma idéia de como o código está estruturado e, provavelmente, uma lista de cerca de 1000 melhorias sugeridas, se minha experiência for algo a continuar. Trabalhar com a lista melhorará a qualidade do código, simplificará bastante e facilitará sua vida no futuro. O próprio Delphi suporta refatoração em versões recentes (nos últimos 5 anos ou mais). Você precisava incluir tudo no arquivo dpr para que ele funcionasse corretamente quando eu estava fazendo isso, então lembre-se disso.

Se você quiser testes de unidade, faça o download do DUnit e comece a criar alguns testes com o codificador original - essa é provavelmente uma maneira construtiva de usar pelo menos parte do tempo.


2

Embora você não tenha mencionado um banco de dados back-end, mas supondo que exista um,

  1. Obtenha o modelo de dados documentado especialmente as colunas e PK-FK
  2. Configure um rastreio sql e registre todas as consultas acionadas durante o uso do aplicativo. A ordem de execução das consultas fornecerá uma boa idéia sobre o fluxo do aplicativo e também ajudará na depuração

Bom ponto em geral, mas não há banco de dados no meu caso em particular.
PersonalNexus

11
pode ser que irá ajudar alguém
NRS

2

Estou na mesma situação em que nosso arquiteto se mudou para a Austrália e deixou muito legado, como esteve na empresa nos últimos 8 anos. Ele próprio herdou coisas herdadas do arquiteto anterior, que era um contratado.

Você e outros já mencionaram bons pontos, mas aqui estão os problemas que enfrentamos depois que ele partiu, pode ser que você possa se preparar melhor ...

1) (Pessoa técnica) Detalhes de contato dos clientes com os quais ele está lidando.

2) Sua conta sob a qual ele comprou licenças de software, chaves que precisam ser renovadas a cada ano e processos / custos para renová-las.

3) Documento de configuração de bibliotecas / componentes e produtos de software de terceiros que se integram aos seus produtos. Lutamos por 4 dias para recuperar uma máquina que foi perdida devido à liberação de espaço da TI e a algumas instruções erradas que lhes foram passadas.

4) Documentos / etapas em que ele é usado para depositar o código-fonte em empresas de depósito de software, por exemplo, Custódia.

5) Ainda existe uma lista longa, mas pode não ser aplicável a você também. Nenhuma quantidade de documentação pode substituir uma pessoa real, portanto, mantenha seus detalhes à mão, mantenha-se em boas condições e boa sorte :)

Também não sei se é a primeira vez para você. Para mim, trabalhei com 5/6 empregadores e sempre herdei código com documentação ruim ou sem documentação. Então, junto com toda a documentação, fique positivo :)

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.