Explorando a IA generativa


TDD com copiloto do GitHub

por Paul Sobocinski

O advento dos assistentes de codificação de IA, como o GitHub Copilot, significa que não precisaremos de testes? O TDD ficará obsoleto? Para responder a isso, vamos examinar duas maneiras pelas quais o TDD ajuda o desenvolvimento de software program: fornecer um bom suggestions e um meio de “dividir e conquistar” ao resolver problemas.

TDD para um bom suggestions

Um bom suggestions é rápido e preciso. Nos dois anos, nada bate com um teste de unidade bem escrito. Não testes manuais, não documentação, não revisão de código, e sim, nem mesmo a IA generativa. De fato, os LLMs fornecem informações irrelevantes e até alucinar. O TDD é especialmente necessário ao usar assistentes de codificação de IA. Pelas mesmas razões que precisamos de suggestions rápido e preciso sobre o código que escrevemos, precisamos de suggestions rápido e preciso sobre o código que nosso Assistente de Codificação de IA escreve.

TDD para dividir problemas

A solução de problemas by way of divisão e conquista significa que problemas menores podem ser resolvidos mais cedo que os maiores. Isso permite integração contínua, desenvolvimento baseado em tronco e entrega contínua. Mas realmente precisamos de tudo isso se os assistentes de IA fizeram a codificação por nós?

Sim. Os LLMs raramente fornecem a funcionalidade exata de que precisamos após um único immediate. Portanto, o desenvolvimento iterativo ainda não está desaparecendo. Além disso, os LLMs parecem “provocar raciocínio” (ver estudo vinculado) quando resolvem problemas de forma incremental by way of Cadeia de pensamento solicitando. Os assistentes de codificação de AI baseados em LLM têm melhor desempenho quando dividem problemas e conquistas, e o TDD é como fazemos isso para o desenvolvimento de software program.

Dicas de TDD para copiloto do GitHub

Na ThoughtWorks, usamos o Github Copilot com TDD desde o início do ano. Nosso objetivo foi experimentar, avaliar e evoluir uma série de práticas eficazes em torno do uso da ferramenta.

0. Introdução

Explorando a IA generativa

Começar com um arquivo de teste em branco não significa começar com um contexto em branco. Muitas vezes começamos com uma história do usuário com algumas notas difíceis. Também conversamos em um ponto de partida com nosso parceiro de emparelhamento.

Esse é tudo o contexto que o copiloto não vê até colocá -lo em um arquivo aberto (por exemplo, na parte superior do nosso arquivo de teste). O copilot pode trabalhar com erros de digitação, formato de ponto e gramática ruim-você escolhe. Mas não pode funcionar com um arquivo em branco.

Alguns exemplos de contexto inicial que funcionaram para nós:

  • ASCII Artwork Mockup
  • Critérios de aceitação
  • Orientação de suposições como:
    • “Não precisava da GUI”
    • “Use programação orientada a objetos” (vs. programação funcional)

A Copilot usa arquivos abertos para contexto, portanto, manter o arquivo de teste e o arquivo de implementação aberto (por exemplo, lado a lado) melhora bastante a capacidade de conclusão do código da Copilot.

1. Vermelho

TDD representado como uma roda de três partes com a parte 'vermelha' destacada no terceiro esquerdo superior

Começamos escrevendo um nome de exemplo de teste descritivo. Quanto mais descritivo o nome, melhor o desempenho da conclusão do código da Copilot.

Nós achamos que um Dado que depois A estrutura ajuda de três maneiras. Primeiro, isso nos lembra de fornecer contexto de negócios. Segundo, permite que a Copilot forneça recomendações de nomeação rica e expressiva para exemplos de testes. Terceiro, revela o “entendimento” do Copilot do problema do contexto de primeira linha (descrito na seção anterior).

Por exemplo, se estivermos trabalhando no código de back-end, e o copilot está concluindo o código do nosso nome de exemplo, “Dado o usuário … Clique no botão Comprarisso nos diz que devemos atualizar o contexto de primeira linha para especificar, “Assuma que não GUI” ou, “Esta suíte de teste interfina com os pontos de extremidade da API de um aplicativo de Flask Python”.

Mais “pegadinhos” para prestar atenção:

  • O Copilot pode preencher o código múltiplos testes por vez. Esses testes são frequentemente inúteis (nós os excluímos).
  • À medida que adicionamos mais testes, o Copilot completará várias linhas em vez de uma linha em um tempo. Geralmente, ele inferirá os passos corretos “organizar” e “ato” dos nomes dos testes.
    • Aqui está o Gotcha: Ele infere o passo “afirme” correto com menos frequência, por isso somos especialmente cuidadosos aqui que o novo teste é falha corretamente Antes de passar para o passo “verde”.

2. Verde

TDD representado como uma roda de três partes com a parte 'verde' destacada no terço superior direito

Agora estamos prontos para a Copilot ajudar na implementação. Um conjunto de testes já existente, expressivo e legível maximiza o potencial da Copilot nesta etapa.

Dito isto, o copiloto geralmente falha em dar “passos do bebê”. Por exemplo, ao adicionar um novo método, o “Child Step” significa retornar um valor codificado que passa no teste. Até o momento, não conseguimos convencer a Copilot a adotar essa abordagem.

Testes de aterro

Em vez de dar os “passos do bebê”, o copilot salta à frente e fornece funcionalidade que, embora muitas vezes relevante, ainda não foi testado. Como solução alternativa, “preenchemos” os testes ausentes. Enquanto isso diverge do fluxo padrão do TDD, ainda precisamos ver nenhum problema sério com nossa solução alternativa.

Excluir e regenerar

Para o código de implementação que precisa ser atualizado, a maneira mais eficaz de envolver o copiloto é excluir a implementação e regenerar o código do zero. Se isso falhar, excluir o conteúdo do método e escrever a abordagem passo a passo usando comentários de código pode ajudar. Falhando nisso, o melhor caminho a seguir pode ser simplesmente desligar o copilot momentaneamente e codificar a solução manualmente.

3. Refactor

TDD representado como uma roda de três partes com a parte 'Refactor' destacada no terço inferior

A refatoração no TDD significa fazer alterações incrementais que melhoram a manutenção e a extensibilidade da base de código, todas realizadas enquanto preservam o comportamento (e uma base de código de trabalho).

Para isso, achamos a habilidade da Copilot limitada. Considere dois cenários:

  1. “Eu sei o movimento do refattor que quero experimentar”: Os atalhos e recursos do IDE Refactor, como o Multi-Cursor Choose, pegue-nos onde queremos ir mais rápido que o Copilot.
  2. “Não sei qual refator se transfer”: A conclusão do código do copiloto não pode nos guiar por meio de um refator. No entanto, o copilot bate -papo pode fazer sugestões de melhoria de código diretamente no IDE. Começamos a explorar esse recurso e vemos a promessa de fazer sugestões úteis em um escopo pequeno e localizado. Mas ainda não tivemos muito sucesso em sugestões de refatoração em maior escala (ou seja, além de um único método/função).

Às vezes, conhecemos o movimento do refactor, mas não sabemos a sintaxe necessária para realizá -la. Por exemplo, criando uma simulação de teste que nos permitiria injetar uma dependência. Para essas situações, o Copilot pode ajudar a fornecer uma resposta em linha quando solicitado por meio de um comentário de código. Isso nos salva da troca de contexto à documentação ou pesquisa na net.

Conclusão

O ditado comum: “Lixo, lixo” se aplica à engenharia de dados e à IA e LLMS generativos. Declarado de maneira diferente: entradas de maior qualidade permitem que a capacidade do LLMS seja melhor alavancada. No nosso caso, o TDD mantém um alto nível de qualidade de código. Essa entrada de alta qualidade leva a um melhor desempenho de copilot do que o possível.

Portanto, recomendamos o uso do copilot com o TDD, e esperamos que você encontre as dicas acima úteis para fazê -lo.

Graças à equipe “Conjunto com Copilot” começou no Thoughtworks Canada; Eles são a principal fonte dos achados abordados neste memorando: Om, Vivian, Nenad, Rishi, Zack, Eren, Janice, Yada, Geet e Matthew.


Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *