Voltar para Notícias para desenvolvedores

Desvendando o desconhecido

16 de maio de 2023PorAndrew Reedy

A Meta possui um ecossistema de produtos que são usados diariamente por bilhões de usuários, seja para criar conexões sociais ou para gerar engajamento comercial. Esses bilhões de usuários também nos pedem para fornecer continuamente – em um ritmo acelerado – novas funcionalidades e melhorias para os nossos produtos. Devido à nossa grande base de usuários, realizamos milhares de alterações de código todos os dias para atender a essas expectativas.

O lançamento contínuo de um número tão grande de melhorias pode gerar regressões na integridade do aplicativo e causar a degradação da experiência do usuário. Na Meta, temos ferramentas avançadas de prevenção para evitar a inclusão de alterações problemáticas nos produtos. Com elas, é possível monitorar vários sinais nos produtos e detectar regressões antes de lançar os apps. Esses sinais estão relacionados a três áreas: desempenho, confiabilidade (funcional e sistêmica) e eficiência. Eles são denominados em conjunto como o "PRE" (pelas iniciais em inglês) dos produtos. A prevenção começa com uma série de rastreamentos analíticos e de observabilidade coletados durante o processo de criação do código. Além disso, os sistemas de monitoramento e observabilidade reúnem dados de uso interno dos produtos em ambientes de pré-produção. As ferramentas de garantia de qualidade, tanto manuais quanto automatizadas, testam os produtos nesses ambientes também.

Mesmo com o uso desses mecanismos criados para avaliar a qualidade das alterações de código antes que elas cheguem à produção (e, assim, evitar o impacto para o usuário), pode acontecer que as mudanças que afetam o usuário cheguem à produção e precisem ser corrigidas e implementadas outra vez. Para reduzir a possibilidade de o problema afetar um grande número de usuários, usamos vários mecanismos para liberar gradualmente as alterações para o público.

Quando a funcionalidade não atende às expectativas de um usuário, definimos isso como uma regressão. Usamos a palavra sinal para indicar que os usuários estão nos informando que algo não funciona conforme o esperado. Coletamos sinais de regressão o quanto antes de forma sistêmica por meio de insights de dados e código instrumentado. Depois, implantamos correções para reduzir o impacto ao usuário. Quando não recebemos sinais consistentes das nossas ferramentas, contamos com os relatos dos usuários para saber se ocorreu uma regressão. Esses relatos são encaminhados por vários mecanismos, como quando os usuários agitam os telefones para relatar um problema no aplicativo, indicando o contexto e o momento em que ele ocorre.

Para que possamos atender às necessidades dos nossos clientes o mais rápido possível – às vezes no mesmo dia –, a Meta investiu em vários programas e sistemas de confiabilidade para permitir uma capacidade de resposta significativa em grande escala.

Os sinais podem vir de usuários internos ou públicos (indivíduos, empresas, grupos, entre outros). Examinamos cuidadosamente os sinais dos usuários internos para ajudar a evitar que mudanças indesejadas cheguem à produção. Vale ressaltar que os sinais são agregados; por exemplo, incluem o número de bugs por milhão de usuários. Os sinais também podem ser encaminhados a partir de ferramentas e cenários de teste automatizados, mecanismos de desenvolvimento (alertamos os desenvolvedores sobre alterações que podem causar problemas no tempo de execução), registros do sistema e muitas outras fontes. Além disso, temos ferramentas que aproveitam esses sinais para identificar rapidamente as causas e as correções apropriadas.

Depois que uma regressão é identificada, buscamos os engenheiros responsáveis para aplicar as correções. Dependendo da complexidade da regressão, usamos vários métodos para acionar os engenheiros certos e recorremos ao conhecimento da Meta sobre aprendizado de máquina. Devido à forma como o aprendizado de máquina funciona, seguimos esse processo de modo contínuo à medida que lançamos novos recursos e ajustamos o treinamento dos nossos modelos para acompanhar as mudanças constantes.

Há um ganho em tudo isso: passamos da simples detecção para a mitigação, a prevenção e a contenção das regressões de forma sustentável. No processo, maximizamos a capacidade de resposta, o retorno sobre o investimento e a eficiência.

Na próxima seção, abordaremos em mais detalhes como identificamos a ocorrência de uma regressão e como respondemos a isso.

Traduzindo e quantificando problemas desconhecidos

Quando falamos em um problema "desconhecido", nos referimos a um bug sinalizado por um usuário ou sistema. A informação sobre a ocorrência de um bug pode vir de várias fontes diferentes.

  • Testes sintéticos sobre o funcionamento adequado dos nossos aplicativos e produtos específicos neles.
  • Usuários internos que participam de testes para encontrar bugs. Isso pode incluir as nossas equipes de teste dedicadas ou a base de usuários mais ampla na Meta.
  • Usuários externos que estão enfrentando problemas ao usar o diálogo de relato de bugs nos nossos apps.

Esses bugs são desconhecidos até que sejam realmente sinalizados como incidentes que afetam os usuários. Quando o número desses relatos de bug atinge um determinado limite, entendemos que a ocorrência é verdadeira e que ela representa um evento de regressão: uma alteração de código criou um novo bug e temos que agir rapidamente para mitigá-lo. Existem dois tipos principais de relatos:

  • "Problema identificado" – Quando o código instrumentado detecta e relata a regressão (e temos várias ferramentas que ajudam a produzir esse sinal)
  • "Problema desconhecido" – Quando a regressão não é identificada internamente e contamos com o relato do usuário

Além disso, as regressões se enquadram em várias categorias, como bugs de código, conteúdo parecido com spam ou alguma outra violação da política de conteúdo. Mantemos o foco na primeira área para resolver problemas de experiência do usuário relacionados ao código. Mas o que fazer quando há usuários relatando milhares de problemas?

Gerando sinais e insights

Para gerenciar o grande volume de relatos, geramos sinais específicos para alertar as nossas equipes sobre problemas. O primeiro tipo de sinal é aquele que, com limites devidamente ajustados, nos informa que ocorreu de fato um incidente ou uma regressão. Vale lembrar que vários eventos podem ter ocorrido dependendo do tipo de regressão. Por exemplo, uma regressão pode afetar diversos produtos que têm uma base de código comum. Procuramos essas semelhanças e as abordamos como um único incidente para otimizar o uso dos recursos. O gráfico abaixo é um exemplo de como podemos identificar visualmente o afastamento da linha de tendência, o que indica uma regressão.

Depois, coletamos outros sinais, que podem indicar o tipo de regressão que estamos enfrentando. Esses sinais fornecem informações sobre os sintomas associados à regressão e são gerados por algoritmos de aprendizado de máquina ajustados para produtos específicos da Meta. Os algoritmos analisam os relatos dos usuários para determinar o que causou a regressão. Dessa forma, é possível escolher a equipe de engenharia certa para resolver o problema implantando uma correção de código ou outra medida.

Muitos outros sinais também são gerados com base nos dados de registro coletados. Esses registros de diagnóstico podem vir do lado do cliente ou do servidor que são coletados (com o consentimento do usuário) para ajudar a determinar a causa. Os aplicativos incorporam fluxos de consentimento adequados para determinar se esse tipo de dado pode ser coletado com base nas permissões do usuário. Também consideramos a longevidade dos dados para cumprir os regulamentos aplicáveis.

A combinação de sinais nos permite explorar melhor a regressão e atribuí-la à equipe de produto correta para mitigar rapidamente o problema e restaurar a experiência esperada pelo usuário.

Os insights também são derivados de resultados agregados. Analisamos os dados para encontrar as causas comuns e determinar se é necessário fazer alterações para evitar que as regressões ocorram novamente. Isso é fundamental para manter uma abordagem robusta que permite lidar com problemas de experiência do usuário, já que nos ajuda a minimizar a superfície de regressão ao longo do tempo.

Nossos aplicativos para dispositivos móveis não apenas incluem caminhos de navegação que possibilitam ao usuário relatar um problema, mas também fornecem a capacidade de sinalizar um bug agitando o dispositivo. Dessa forma, é possível coletar a telemetria no contexto. Essa telemetria se torna ainda mais detalhada por meio de sinais da caixa preta provenientes do app. A caixa preta é como um gravador de voo que captura automaticamente determinados registros (com base no consentimento fornecido pelo usuário) sobre o que estava acontecendo com o aplicativo no momento em que o bug foi relatado, para que possamos diagnosticar melhor o problema.

Essa telemetria é apresentada em um conjunto de visualizações da linha do tempo para ajudar as equipes de engenharia a determinar o que causou o problema. Devido ao ritmo acelerado de lançamento dos nossos apps, bem como das alterações nos componentes do aplicativo do lado do servidor, sem esse recurso seria difícil identificar o problema. Ter essa telemetria ao longo do tempo também nos ajuda a detectar padrões nas regressões para evitá-los no futuro.

Dimensionamento para superfícies de produtos menores

Ao tornar os nossos sinais mais precisos, podemos trabalhar melhor em partes específicas da superfície de regressão que antes talvez passassem despercebidas. Uma superfície representa uma oferta específica dentro de um produto, como o Feed de Notícias ou o Reels. Isso é desafiador porque os produtos possuem muitos recursos detalhados. Além disso, novas funcionalidades são lançadas regularmente. Ou seja, a superfície de regressão é grande e ainda cresce com o tempo. Por isso, as nossas estratégias defensivas e ofensivas precisam se adaptar continuamente.

Para poder dimensionar o nosso trabalho, há várias condições que precisam ser atendidas:

  1. Ter cobertura precisa e classificação adequada das superfícies de produtos atuais
  2. Reduzir a superfície de regressão para produtos atuais (ou seja, prevenção)
  3. Aumentar o alcance dos nossos algoritmos para novas superfícies de produtos

O não cumprimento das condições acima pode resultar em um sistema sobrecarregado que não pode ser gerenciado devido ao tamanho, à complexidade e à imprecisão. Portanto, as nossas iniciativas servem para manter esse equilíbrio e, ao mesmo tempo, executar com eficiência as nossas operações diárias.

Indo além dos bugs

Conforme reduzimos a superfície de regressão (sem baixar a guarda), aumentamos o nosso foco em outras áreas importantes: prevenção e usabilidade.

A prevenção inclui o seguinte:

  1. Como aprendemos com as regressões anteriores?
  2. Que defesas implementamos para que essas regressões não ocorram novamente?
  3. Como podemos, ao longo do tempo, garantir que a superfície de regressão continue diminuindo?

Como foi mencionado, agregamos dados de regressões anteriores para aprender com eles. O que aprendemos que é preciso fazer:

  1. Colocar marcadores no nosso código ainda em um ambiente de pré-produção para impedir que uma alteração indesejável avance para a produção
  2. Aumentar a cobertura de teste em vários níveis para detectar tais regressões
  3. Alterar o produto para resolver esses problemas

A prevenção nos ajuda evitar o avanço das regressões no ciclo de vida do desenvolvimento e, assim, continuar reduzindo os custos. Fazemos isso obtendo sinais detalhados no início do processo de desenvolvimento, começando com a autoria do código e os ciclos de lançamento de pré-produção. Isso não apenas melhora a experiência do usuário, mas também reduz os custos de desenvolvimento e nos ajuda a direcionar recursos para a criação de novos produtos.

Melhorar a nossa capacidade de lidar com regressões nos permite focar na experiência do usuário ou nos problemas de usabilidade. Essas são preocupações importantes porque priorizam a melhoria em vez da correção dos produtos. Com o tempo, a proporção de problemas de usabilidade em relação a regressões deve aumentar, e o número total de problemas de usabilidade e regressões deve diminuir.

Por fim, isso resulta em uma melhoria contínua da experiência do usuário quando se trata de funcionalidade e usabilidade.

Este artigo foi escrito em colaboração com Bijan Marjan, gerente do Programa Técnico da Meta.