Categorias

Como a Trivago trocou todo seu tech stack de uma vez

Trivago é uma empresa alemã que oferece um serviço que funciona como um mecanismo de busca customizado, que pesquisa os melhores preços de hotéis para quem está viajando. Isso é possível porque sua aplicação consulta a impressionante base de 5 milhões de hotéis e alojamentos em quase 200 países, incluindo processos de reserva e lotação. Isso exige uma capacidade excepcional de manipulação de um grande volume de dados. Com cerca de 4 milhões de usuários ao mês, a plataforma também precisa lidar com um tráfego agressivo.

Todas essas necessidades exigem soluções tecnológicas robustas. Fundada em 2005, ao longo desses dezessete anos, a Trivago passou por transições e reestruturações em seu backend. A mudança mais recente foi completada no final de 2021, depois de dezoito meses de trabalho. Nesse processo, a Trivago abriu mão de uma combinação de PHP com seu próprio framework javascript para uma aplicação em Next.js, escrita com TypeScript. Essa migração afetou o domínio principal e mais de 50 domínios pertencentes à empresa, envolveu o trabalho de 30 desenvolvedores e resultou em 200.000 linhas de código .ts (em 2600 arquivos) e 115 mil linhas de código .tsx (em 1500 arquivos).

Toda essa transferência de base tecnológica foi documentada em duas postagens em seu blog técnico oficial, que iremos resumir agora.

O problema

Anos antes, a Trivago havia desenvolvido o Melody, um framework de JavaScript criado especificamente para atender às necessidades da empresa. O Melody tinha a vantagem de ser leve e rápido, justamente por ser feito sob medida para suas funções, o que garantia à empresa um aplicativo capaz de rodar nos dispositivos Android mais fracos. O Melody havia surgido justamente pela grande quantidade de JavaScript embarcado anteriormente, que saturava o aplicativo.

Porém, a Trivago percebeu que o Melody era um beco sem saída para a própria empresa, com pouquíssimos desenvolvedores cuidando de sua manutenção. Era um risco. Não havia recursos para evoluir ou mesmo manter o framework, sua documentação era incompleta e novos desenvolvedores tinham dificuldades para se adaptar ou buscar soluções novas dentro do seu ecossistema. Tudo isso gerava uma camada de atrito, que acabava reduzindo a velocidade da produção de novas funcionalidades ou mesmo da correção de problemas. Além disso, novos profissionais sentiam que não estavam construindo uma expertise que pudesse ser útil fora da Trivago.

Decidiu-se então que o Melody e o PHP deveriam ser substituídos por soluções mais comuns no mercado, com uma vasta base de conhecimento, estudos de caso e documentação, algo que permitisse a contratação de novos desenvolvedores já especializados. Optou-se pela combinação de Next.js com TypeScript para reformular todo o tech stack da empresa.

Os obstáculos

Como todo processo de migração, a jornada da equipe de TI da Trivago não foi imune a percalços. Foi preciso vencer desafios nessa transição, tanto na parte administrativa quanto na parte técnica.

Tomada de decisões:

A mobilização de uma equipe gigante para cuidar da tarefa exigiu um fluxograma de tomada de decisões que não afetasse a produtividade. Principalmente porque algumas decisões teriam que ser tomadas não de forma prévia mas ao longo do surgimento de impasses técnicos. Ao mesmo tempo, era importante que todas as vozes fossem ouvidas ao longo do processo.

A Trivago adotou então uma estratégia de três pontos:

  • Um documento de decisão onde todos os fatos e pontos de vista relevantes foram coletados e organizados.
  • Um proprietário de decisão que fez a curadoria do documento de decisão, preparou a reunião de decisão e foi responsável para que uma decisão fosse alcançada.
  • Uma reunião de decisão, onde os pontos de vista foram trocados e discutidos, e uma decisão foi tomada no final.

Colaboração remota:

O projeto foi iniciado no primeiro trimestre de 2020 e encarou de imediato um impasse que ninguém estava esperando: uma pandemia mundial. Todo o processo de migração precisou ser realizado com a equipe trabalhando de forma remota, um esquema nunca experimentado antes dentro da Trivago. De acordo com a empresa, “isso representou um desafio para um projeto inédito com toneladas de discussões a serem feitas, decisões a serem tomadas e ideias a serem desenvolvidas. A largura de banda da videoconferência é menor do que a verdadeira interação pessoal e, às vezes, é mais difícil garantir que todos expressem realmente sua opinião”. A forma que a equipe encontrou para superar essa dificuldade foi através do bom humor e da descontração nas conferências online.

Gerenciar o tamanho do time:

A Trivago admite que houve uma falha de avaliação em relação ao número de profissionais necessários. Era necessário manter a equipe reduzida até que todo o código estivesse estável e crescer o time logo em seguida para ganhar velocidade na entrega da migração. Entretanto, esse equilíbrio exato não foi alcançado: o time aumentou rápido demais no início, com decisões pendentes que provocaram “uma falta de clareza”. Segundo a empresa, essa foi a lição mais importante aprendida na migração.

Mudança de paradigma com TypeScript:

Evidentemente, alguns engenheiros da Trivago mostraram resistência ao TypeScript. Não apenas porque tinham se acostumado com o Melody, mas também por estarem vindo de um estilo funcional de se escrever JavaScript, adeptos de diversos atalhos no desenvolvimento.

No entanto, quando esse processo de adaptação for concluído, descobrimos que o TypeScript oferece muita confiança em seu código. Ao escrever um novo código, isso já é uma vantagem. No entanto, é inestimável quando você altera o código existente, especialmente se você não o escreveu. Mesmo que você não entenda cada pequeno detalhe sobre o código, contanto que você acerte os tipos, é provável que seu código esteja funcionando corretamente.

Tom Bartel, engenheiro de software da Trivago

A migração

Os desenvolvedores da Trivago foram obrigados a pensar em tipos de fluxos de dados de forma rigorosa, mas esse cuidado adicional na aplicação teve suas compensações. Segundo o relatório técnico final, essa necessidade afiou o raciocínio lógico e aumentou a disciplina da equipe. A adoção de uma linguagem baseada em tipos também ajuda na hora de modificar ou refatorar código já existente.

Alguns atalhos e gambiarras foram embora, mas a migração conseguiu se beneficiar de alguns recursos:

Reaproveitando o poder do GraphQL

A base de código anterior da Trivago estava escorada de forma pesada na arquitetura GraphQL. Com o TypeScript, foi possível reutilizar o esquema e gerar automaticamente definições de tipo a partir dele. Os desenvolvedora usaram um comando simples apollo client:codegen para contatar o servidor GraphQL e atualizar os tipos do lado do cliente:

apollo client:codegen packages/graphql-types/generated \
--no-addTypename \
--target=typescript \
--outputFlat \
--globalTypesFile=./packages/graphql-types/globalTypes.ts

Para evitar conflitos, optou-se por escrever o código auto-generado em um pacote isolado de tipos, para não acontecerem problemas com o código escrito à mão pelos desenvolvedores.

Usando tipos “conectados”

Outra boa prática utilizada na migração foi conectar o sistema de tipos da aplicação ao esquema de tipos gerado automaticamente.

Inicialmente, estabeleceu-se um problema: tipos entidades chave criados pelos desenvolvedores que se tornaram parte do schema, mas que eram semelhantes a tipos gerados de forma automaticamente. Para complicar eles estavam sendo digitados um por cima do outro, gerando confusão. Eles citam o exemplo da entidade chave Accomodation (“acomodações”, em Português, um elemento fundamental para o serviço prestado pela Trivago):

return accommodations as Accommodation[]; // NÃO FAÇA ISSO!

Por causa dessa abordagem, objetos recuperados do GraphQL estavam sendo tratados como tipos locais. Como explica o engenheiro Tom Bartel, “além disso, como o tipo Accomodation possui campos de outros tipos escritos à mão, também fizemos um cast de tipo implícito nesses campos”:

export interface Accommodation {
  // ...
  accommodationDetails: AccommodationDetails; // hand-written
  coordinates: Coordinates; // hand-written
  closestPoi: Nullable<ConceptWithDistance>; // hand-written
  advertiserInfo: Nullable<AdvertiserInfo[]>; // hand-written
  deals: Deals; // hand-written
  // ...
}

Naturalmente, os tipos escritos manualmente eram similares ao gerados automaticamente e isso foi uma vantagem no começo. Entretanto, o time aprendeu a não confiar nessa tática, uma vez que ela se provou uma receita para o desastre, confundindo os desenvolvedores e impedindo o TypeScript de detectar bugs.

Segundo Bartel, resultados inesperados foram aparecendo: “o TypeScript diz que um determinado campo está lá, mas na realidade é indefinido ou nulo. É improvável que testes automatizados detectem esses erros, porque eles também teriam uma segurança de tipo burlada (….) Se você tiver sorte, você pegará o bug durante o teste manual. Se não, ele vai te atingir na produção”.

Vantagens da mudança

Aos trancos e barrancos, mas também com muito aprendizado ao longo do caminho, a migração foi um sucesso. O novo tech stack reduziu o peso da página inicial da Trivago de 2.1 MB para 1.7 MB. Na página de resultados, a mudança foi ainda mais impressionante, reduzindo de 4.1 MB para 2.6 MB. Uma das estratégias adotadas foi quebrar o modelo de aplicação de página unificada em múltiplas páginas, através do recurso de partição de código automática oferecido pelo Next.js. Isso significa uma redução do tempo de carga do lado do usuário, respostas mais rápidas e economia de dados.

Os desenvolvedores também se beneficiaram da recriação do código, que passou a ser mais limpo e melhor documentado do que era antes, o que permite mais agilidade na criação de novas funcionalidades. Além disso, todo o processo de migração sintonizou a equipe como um todo e desenvolveu um sentimento de pertencimento que não havia anteriormente. A vontade de preservar esse trabalho tem estimulado os profissionais a manterem a documentação atualizada, assim como explicar as decisões de design tomadas para seus colegas.

Acho que é seguro dizer que todas as pessoas que trabalharam no projeto aprenderam muito – algumas sobre gerenciamento de projetos, outras sobre comunicação, outras sobre tópicos técnicos. É uma grande sensação quando você vê muitas pessoas aprendendo e crescendo juntas.

Tom Bartel, engenheiro de software da Trivago

Saindo de um framework interno e adotando uma solução praticada popularmente no mercado, isso permite que novos desenvolvedores se acomodem em seus postos de forma mais fluida. A Trivago adotou uma configuração que é mais ou menos padronizada, baseada em tecnologias conhecidas. Desta forma, novos desenvolvedores podem começar a acrescentar e produzir desde o primeiro dia, sem uma curva de aprendizado abrupta.

A equipe de TI da Trivago agora segue confiante de que faz parte de uma comunidade muito maior. Qualquer dificuldade que possa surgir em alguma implementação já foi solucionada antes e documentada em algum lugar, com múltiplas soluções disponíveis como bibliotecas de código aberto que podem dinamizar o processo dentro da empresa.