Desenvolvimento

5 fev, 2018

Jogada perfeita: construindo Uber Eats no Android

Publicidade

O envio de um aplicativo provavelmente não é a primeira coisa que vem à mente quando você pensa em esportes. Quando você ferve isso, no entanto, um lançamento bem sucedido é moldado pelas mesmas forças que contribuem para um jogo perfeito: o alinhamento final da visão, determinação, direção e trabalho em equipe.

Da esquerda para a direita: Os companheiros de equipe Padmini Pyapali, Jesus Medrano, Paulina Ramos e Hilary Karls no primeiro lançamento do Uber Eats do Android em Toronto. Eles celebraram seu lançamento bebendo batidas pedidas da loja de suco favorita de Paulina através do aplicativo.

De muitas maneiras, o aplicativo Android Uber Eats foi a jogada perfeita da nossa equipe. Em agosto de 2015, estávamos envolvendo a construção de uma nova casa para Instant Uber Eats (nossa primeira iteração da plataforma Uber Eats) no aplicativo do passageiro da Uber.

Especificamente, estávamos testando a entrega de alimentos, adicionando uma alternância no cabeçalho do aplicativo que permitiu que os passageiros passassem de solicitar uma corrida para ver restaurantes dos quais pudessem fazer pedidos.

Através destes testes, descobrimos que os usuários preferiam uma maior variedade de menus completos do que uma variedade muito maior de restaurantes – para entrega imediata. Enquanto eles queriam sua comida rapidamente, um tempo de entrega de 10 minutos não era tão mágico com opções limitadas.

Durante um teste precoce de Instant Eats no aplicativo do passageiro da Uber, adicionamos a capacidade de os usuários trocarem as funcionalidades do passageiro e do Instant Eats tocando ícones na barra superior.

Para criar um produto que satisfizesse melhor as preferências dos usuários famintos do Android, decidimos criar um novo aplicativo – Uber Eats. O desafio inicial: passar seis semanas construindo uma versão viável de um aplicativo que fosse fácil de navegar, útil e, o mais importante, que tornasse a experiência de entrega de alimentos tão conveniente e agradável quanto possível.

Ambicioso? Claro, mas isso deu o tom. Como o designer da nossa equipe pontuou, a primeira iteração de Uber Eats para Android foi “a versão cupcake” – funcional e reduzida, mas ainda deliciosa.

O aquecimento: construir a base

O primeiro rascunho de nossos projetos estava pronto no final de agosto. No início de setembro, a equipe de engenharia mais ampla havia montado um plano e um esboço detalhado do que precisava existir para alimentar nosso aplicativo, tanto no iOS quanto no Android.

Durante o restante do mês, saímos de outras tarefas e começamos a planejar e executar com seriedade. Depois de analisar o escopo do projeto, aqueles de nós que já estiveram na indústria por algum tempo sabiam que tudo isso exigiria total atenção e dedicação até o final de dezembro.

Além do envio rápido, estávamos determinados a desenvolver para o crescimento futuro. Tomamos emprestado liberalmente as melhores práticas de outros lugares da Engenharia da Uber, desenvolvendo sobre bibliotecas internas e externas. Utilizamos o framework do MVC a partir do nosso aplicativo do motorista e do RxJava integrado, da mesma forma que fizemos para o nosso aplicativo do passageiro.

Para construir uma base sólida a partir da qual trabalhar, buscamos por recursos sobre essas tecnologias; que este aplicativo fosse codificado para que pudéssemos viver nele por muito tempo. Nós alavancamos o framework de rede da equipe da Plataforma da Uber para Android, que foi construída em cima de OkHttp, Retrofit, Dagger e nosso próprio framework de experimentação.

Nós nos desafiamos durante as revisões de código, avaliando se o nosso código fundamental era simples ou bem documentado o suficiente para que nossos futuros seres humanos pudessem entendê-lo.

Trabalhando com produtos, projeto e outras equipes, desenvolvemos histórias de usuários para entender melhor as funcionalidades que precisávamos construir. Essas especificações variaram de considerações tão básicas quanto “um usuário deve ser capaz de fazer o login” até “um usuário deve ser capaz de fazer um pedido” com um restaurante. Com estas diretrizes em mente, trabalhamos com nossas equipes back-end e iOS para definir as APIs do Uber Eats o mais claramente possível.

Mesmo sabendo que nossas API se ajustariam, começamos a implementar. Ter uma compreensão compartilhada entre as equipes nos permitiu desacoplar nossa execução. Além disso, concordar em como modelamos objetos em nosso sistema tornou mais fácil para nós construir versões sustentáveis ​​e uniformes do aplicativo em ambos os sistemas operacionais móveis. Alinhados aos nossos planos e estratégias, começamos a construir o caminho feliz.

A primeira metade: o caminho feliz em teoria

Em meados de outubro, atingimos nossa passada larga depois que um dos membros da nossa equipe sugeriu que dividíssemos o trabalho em postos de controle de duas semanas, uma prática que adotamos prontamente. Nós atribuímos proprietários para cada grupo de recursos e começamos a embalá-los, agilizando o trabalho mais perigoso e crítico primeiro.

Para que o aplicativo funcionasse perfeitamente, precisamos do nosso caminho feliz para verificar várias caixas. Primeiro, ele precisava ser fácil para que os usuários se inscrevessem e adicionassem suas informações de pagamento. Em seguida, um usuário teria que ser capaz de inserir sua entrada de endereço. Então, uma vez que uma pessoa entrasse em seu local de entrega, o aplicativo precisava trazer à tona todos os restaurantes em uma área específica e permitir que os usuários vissem seus menus.

Uma vez lá, os usuários precisavam visualizar páginas de pratos e adicionar pratos aos seus carrinhos de compra. E, finalmente, precisava ser fácil de fazer check-out e acompanhar os pedidos desde o momento em que os usuários pressionassem o botão “Pedir” até a entrega. Para garantir que nosso caminho feliz fosse tão “feliz”, tanto em teoria como na prática, todos nós aconselhamos a revisão de código, testar novas funcionalidades e corrigir erros.

Nós corremos duro todos os dias, confiamos uns aos outros para fazer um bom trabalho, demos feedback construtivo e assumimos a responsabilidade pelas nossas contribuições respectivas.

Em algum momento, no final de novembro, eu estava sentada em uma reunião de equipe olhando para todos. Uma imagem de um campo de futebol, jogadores correndo e passando, torcendo um para o outro – jogando o jogo perfeito – entrou na minha cabeça, e percebi como nós fluíamos perfeitamente juntos.

E mesmo que o jogo tenha ficado cada vez mais difícil, nossa paciência desgastada, as emoções correndo alto, e nenhum de nós estava no nosso melhor todo o tempo, confiamos um no outro para obter o aplicativo na linha de chegada.

A segunda metade: o caminho feliz no mundo real

No início de dezembro, as equipes do iOS e do back-end enfrentavam nosso maior inferno de integração. Era hora de ver quão “compartilhado” estava nosso entendimento compartilhado e o que realmente funcionaria na prática. Como muitas vezes acontece, esse processo levou alguma iteração. Depois de resolver problemas persistentes, as duas equipes voaram para Toronto para iniciar o Uber Eats no iOS em 9 de dezembro de 2015.

Enquanto isso, nossa equipe do Android estava envolvendo os últimos recursos em nossa versão do aplicativo. Ao mesmo tempo, tivemos que manter um olho para qualquer mudança que surgisse da integração do iOS e back-end. Pouco tempo depois, conseguimos colocar nossos primeiros pedidos através do aplicativo e, na verdade, conseguir alimentos entregues (embora ainda não tivéssemos construído o rastreamento de entrega, então, esperando que nosso pedido fosse um pouco mais estressante do que é agora).

Meu item favorito para pedir era sempre o biscoito de chocolate do Mr. Holmes Bakehouse – eu realmente  poderia comer meus cookies de teste!

Analisando os dados em torno do nosso lançamento do iOS em Toronto, podemos ver que alguns de nossos pressupostos simplificadores produziram menos experiências otimizadas de usuário. Por exemplo, esperávamos que todos os restaurantes iriam on-line basicamente ao mesmo tempo.

Em vez disso, eram alguns aqui e ali, então muitos, e então muitos mais, e dado que nossa lista fazia pedidos de restaurantes abertos acima dos restaurantes fechados, a lista de opções disponíveis mudou tremendamente a cada poucos segundos. Parecia que o aplicativo era equivalente a um terremoto e sabíamos que devíamos corrigi-lo antes do lançamento do Android.

No lançamento, a página inicial do aplicativo Uber Eats do Android incorporou seções através das quais os usuários podiam pedir com facilidade tanto do Instante Eats como dos menus completos do restaurante.

Para abordar isso, adicionamos código para detectar mudanças no número de restaurantes abertos e fechados e atualizamos on-line se houvesse apenas algumas mudanças, solicitando ao usuário antes de aplicar atualizações se estivesse em um determinado limite.

Nós também percebemos que havia muitos restaurantes para navegar em uma única lista sem incorporar uma funcionalidade de pesquisa. Então, construímos a primeira versão de busca do lado do cliente em 48 horas, inclusive incorporando verificação ortográfica e sugestões usando os cálculos de distância Levenshtein.

Um acabamento fino

Nós ainda estávamos correndo até o nosso código congelar no final de dezembro. Enquanto as equipes do iOS e de back-end estavam saindo comemorando o sucesso do seu lançamento, ficamos para trás, pedimos pizza e solucionamos problemas persistentes, revisamos o código e pousamos todos os erros restantes. Energizados por nossa camaradagem, alcançamos a linha de chegada irradiando orgulho e entusiasmo, amplificamos muito mais por exaustão. Nós colocamos tudo no campo, afastando do nosso trabalho com abraços e comemorações.

No lançamento, nossas telas de rastreamento de pedidos e checkout foram as versões mais simples possíveis.

Uma vez que era um pouco arriscado enviar um aplicativo durante o feriado (enquanto a maioria dos engenheiros estava preocupada com o apoio ao tráfego da Noite de Ano Novo), decidimos voar para Toronto após o Ano Novo para o nosso lançamento.

Durante o feriado, aproveitei a vantagem da oportunidade de liderar um projeto de trabalho em Roatan, Honduras. Eu sabia que ficaria feliz tomando banho de sol, mergulhando e implementando a acessibilidade TalkBack no aplicativo. Então, eu acabei trabalhando com meu colega Erik na praia em Honduras com Jesus apoiando nossas revisões de código da Área da Baía. E aí, dissemos adeus a 2015, tornando Uber Eats mais acessível para usuários de Android, nadando com tubarões na véspera de Ano Novo e ficando extremamente queimados, no tempo certo para o nosso lançamento em 6 de janeiro de 2016 na fria Toronto.

Dois anos e 200 cidades depois

Dois anos depois, o aplicativo Uber Eats do Android foi expandido para mais de 200 cidades em todo o mundo, com mais de 80 mil parceiros de restaurantes. Nosso trabalho duro valeu a pena: em 2016, o aplicativo ganhou um Prêmio de Escolha do Editor da Google Play Store e foi baixado por milhões de usuários em todo o mundo.

Embora tenhamos lentamente reescrito partes do nosso aplicativo à medida que lançamos novos recursos, alguns de nossos códigos originais ainda estão em uso hoje.

Ao longo do tempo, adicionamos a capacidade de “favoritar” restaurantes e ver grupos de restaurantes no feed em carrosséis no aplicativo Uber Eats. Também melhoramos as capacidades de busca e pesquisa do aplicativo.
Também investimos significativamente na otimização da experiência de checkout e entrega da Uber Eats.

Enquanto Jesus e eu ainda estamos na equipe de Uber Eats, Paulina e Padmini levaram seu espírito empreendedor para Uber Freight. Jogar o jogo perfeito com eles me ensinou várias lições sobre o que é preciso para criar e lançar um novo aplicativo com sucesso:

Parceria com suas equipes de operações para oferecer crescimento

Nenhum dos crescimentos que vimos com a Uber Eats teria sido possível sem as nossas equipes de operações. Seus primeiros testes em Los Angeles e os mercados que experimentaram com Instant Uber Eats provaram que o negócio ficaria firme para que pudéssemos expandir com confiança. Além disso, a equipe de Toronto trabalhou em estreita colaboração conosco e seus parceiros locais para lançar a primeira versão do aplicativo completo e do marketplace e investiu sua energia para fazê-lo funcionar.

Prática: experimente cedo e muitas vezes

Tivemos vários experimentos antes de nos empenharmos em criar um aplicativo separado. A visão que obtivemos ao realizar experimentos de investimento relativamente baixos no início nos deu a confiança para construir um novo aplicativo, e saber que encontraríamos um caminho para algo útil.

Alavancar frameworks

Construir em cima de frameworks e bibliotecas da Uber, Square, Google e a comunidade de engenharia mais ampla nos salvou muito tempo e esforço. Não reinventar a roda, a menos que você tenha que começar do zero.

Priorize os recursos chave/de risco primeiro

É uma boa prática dividir os recursos nas categorias “fundamental” (P0), “importante” (P1), “bom ter” (P2), etc. Para essa implantação, estivemos quase que exclusivamente focados nas P0s. E mesmo entre as P0s, é importante ter uma ideia de quais recursos são os mais arriscados – os mais prováveis de exigir mais tempo do que o esperado.

Se aqueles podem ser derrubados para P1, faça isso. Caso contrário, encaixe-os mais cedo no cronograma de desenvolvimento. Caso os horários mudem, a flexibilidade tornará mais fácil o envio, seja mudando o escopo do resto do projeto ou concordando em uma nova data de lançamento com seus stakeholders.

Deixe tempo para integração

Mesmo com o melhor planejamento, os momentos finais de qualquer projeto podem revelar inconsistências na compreensão ou premissas que não eram bastante precisas. Orçar um pouco de tempo para integração, testes e correções de erros dá-lhe uma chance de resolver quaisquer problemas com menos estresse.

Corra na mesma direção: alinhamento e valores importam

Embora isso seja amplamente conhecido, o alinhamento com o que precisa ser feito é essencial para a execução. Confusão em torno do que está sendo construído, por quem, e quando desperdiçar um tempo valioso. Nessa linha, também é importante ter alinhamento sobre como você e sua equipe escolhem construir. Estávamos todos alinhados em querer construir um aplicativo em que possamos viver por pelo menos um ano sem ter que reescrever assim que lançamos. Se alguns membros valorizaram profundamente a qualidade do código e alguns envios valorizados o mais rápido possível e limpando tudo mais tarde, a tensão inevitável teria nos retardado enormemente.

Cuidem-se uns dos outros

Nossa equipe trabalhou bem junta porque confiamos uns aos outros tanto para executar e ajudar cada um se alguém ficasse preso. A equipe de engenharia mais ampla da Uber Eats, também valoriza esse mesmo senso de confiança e suporte. Sabemos que, se precisamos de ajuda com qualquer coisa – desde revisões de código até corrigir erros para colaborar em recursos – nos protegemos uns aos outros, capacitando-nos a produzir algo muito maior do que podemos sozinhos.

Se servir de algo delicioso no Android lhe interessa, você deve considerar se candidatar a um cargo em nossa equipe!

***

Este artigo é do Uber Engineering. Ele foi escrito por Hilary Karls. A tradução foi feita pela Redação iMasters com autorização. Você pode conferir o original em: https://eng.uber.com/android-eats/