Implementando a interface do usuário no iOS: melhor, mais rápido e escalável



Há alguns meses, me deparei com uma série de documentários muito interessante na Netflix chamada Abstract , que basicamente exploram a produção de designers profissionais de diferentes setores, como arquitetura, design gráfico, moda, ... em seus locais de trabalho.

Foi fácil identificar algumas semelhanças no trabalho de designers de outros campos com o de um desenvolvedor iOS que implementa interfaces de usuário. Por exemplo, quando um designer está criando algo grande o suficiente para ser dividido em partes menores, usar uma estratégia como ' Dividir e Conquistar' é a chave para poder se concentrar em peças menores que serão montadas em estágios posteriores do processo .

Dividir um projeto inteiro em subunidades menores nos permite pensar sobre cada problema isoladamente, removendo quaisquer dependências entre os componentes. Mas a imagem completa também precisa estar presente durante todo o processo; caso contrário, poderá haver problemas quando chegar a hora de ajustar tudo novamente.

Por outro lado, enquanto assistia à Abstract , notei que no processo de design de objetos como sapatos, faixas ou prédios, o design final permanece fixo durante a vida útil do produto. O design de um tênis Nike não será alterado após o lançamento e não haverá atualizações quando estiver na prateleira da loja. Às vezes, um design permanece inalterado mesmo 20 anos depois, e o produto ainda é sólido.


Nike Air Max '97 - Empire State Building (Nova York)

Muitos desenvolvedores de iOS passam muito tempo criando interfaces, definindo interações e aprimorando os detalhes da interface do usuário como parte do processo de criação de aplicativos grandes e complicados. É necessário ter em mente a visão geral do aplicativo como um todo, é claro, mas é igualmente importante pensar em como manter todos os componentes menores separados e distintos - pois esses componentes pequenos podem ser reutilizados mais tarde ao criar outros elementos do aplicativo.


Na equipe do iOS no Badoo, temos lançamentos semanais, todos os quais incluem muitos novos recursos, melhorias e outras alterações que afetam a interface do usuário. É sempre nosso objetivo avançar rapidamente e liberar recursos da mais alta qualidade possível, mas há um ano identificamos alguns problemas em nosso processo de desenvolvimento da interface do usuário e criamos um plano para corrigi-lo.

Descrição do problema


Vou tentar definir o problema em apenas uma frase:
A equipe do iOS não tinha um processo claro de desenvolvimento de interface do usuário.
O que isso significava na prática? Isso significava que o desenvolvimento de qualquer novo recurso com alterações na interface do usuário no aplicativo iOS poderia levar a todos os tipos de problemas. Aqui estão os problemas mais comuns que enfrentamos diariamente:

  • A comunicação com os designers não era clara nem eficaz. Havia pouca transparência com os designers em relação aos componentes existentes da interface do usuário que implementamos nos aplicativos. Isso os forçou a criar novos componentes muito parecidos com os existentes.
  • Não havia padrões geralmente aceitos para a implementação dos componentes da interface do usuário. Cada desenvolvedor estava implementando componentes de maneiras diferentes e muitos deles não estavam se encaixando bem.
  • A duplicação de código estava causando problemas significativos na arquitetura, adicionando complexidade ciclomática, entre outros problemas.
  • Sempre foi muito difícil aplicar modificações em todo o aplicativo para o mesmo componente.
  • Havia um risco maior de introduzir regressão nos componentes existentes, a menos que suas modificações não fossem cobertas pelos testes.

Não haveria varinha mágica para resolver esses problemas porque se trata de processo. Alterar a maneira como as coisas são feitas requer alinhamento entre equipes diferentes e convencer as pessoas afetadas pelo processo sobre os benefícios de uma nova maneira de fazer as coisas.

'Dividir e conquistar' pode ser uma abordagem útil aqui, começando com pequenos problemas, isolando cada problema e começando a construir uma solução global passo a passo. Neste artigo, explicarei como conseguimos isso!

Estruturas de interface do usuário


Abordamos o problema partindo da fundação. O primeiro problema a ser resolvido foi a duplicação de código. Precisávamos unificar nossos componentes e reuni-los em um só lugar.

Nossa solução foi criar algumas estruturas, que chamamos de BadooUIKit. A idéia era que isso contivesse todos os componentes da interface do usuário, semelhante ao que a Apple faz com o UIKit. Ele contém classes que representam as interfaces de usuário de um aplicativo específico (existem outros aplicativos em nossa empresa, mas esse UIKit específico contém apenas componentes da interface do usuário específicos do aplicativo Badoo).

Cada aplicativo possui uma paleta de cores, fontes, margens, etc ... diferentes, portanto, ajuda a ter uma estrutura específica do aplicativo para adicionar folhas de estilo para o aplicativo dentro da estrutura.



O que acontece com os componentes da interface do usuário que podem ser compartilhados e reutilizados em diferentes aplicativos?

Para isso, criamos outra estrutura chamada Platform_UIKit. Essa estrutura possui todos os componentes genéricos da interface do usuário que podem ser usados ​​em diferentes aplicativos.

Nós migramos toda a interface do usuário para a nova estrutura imediatamente?

Não, isso teria sido uma tarefa enorme. Em vez disso, decidimos construir todas as novas UIs dentro da nova estrutura e apenas tentamos mover os componentes existentes quando isso afetava nossa tarefa atual. Em alguns casos, um componente pode ter muitas dependências e, portanto, seria difícil passar do aplicativo principal para o framework. Nesses casos, geralmente optamos por executar a tarefa de migração separadamente. Como parte do plano inicial, priorizamos elementos básicos como fontes, cores, botões, etc.

Posteriormente, uma vez criada a base, migramos toda a interface do usuário do nosso bate-papo para uma estrutura de interface do usuário. Fizemos isso algum tempo depois de termos implantado a infraestrutura e ajudou a ter um processo de migração mais suave.

Nota lateral:
Se você está curioso sobre o processo de criação de um desses componentes, dê uma olhada neste excelente artigo do meu colega Valerii Chevtaev

Um requisito muito importante para essas estruturas é que elas não devem depender de outras estruturas ou classes que não sejam estritamente o código da interface do usuário. Por exemplo, nunca importamos modelos do aplicativo principal, classes relacionadas à camada de rede, repórteres de estatísticas, etc.

Ao isolar a interface do usuário de outras dependências, tornamos os componentes o mais reutilizáveis ​​possível:



Não há problema em o BadooUIKit importar do Platform_UIKit, mas não o contrário, por um simples motivo, se o Platform_UIKit depender do BadooUIKit, ele não será mais independente do aplicativo.



No Badoo, adicionar essas estruturas ao nosso projeto não foi muito difícil e não exige muita manutenção. Todo projeto lá fora é diferente e nem sempre é fácil encontrar a maneira apropriada de construir uma estrutura, mas é benéfico a curto e a longo prazo.

Aqui estão alguns dos benefícios do uso do UIKit:

  • Ter os componentes da interface do usuário em um único local facilita a localização e mantém o projeto melhor organizado, em vez de espalhá-los por toda a estrutura do projeto.
  • Liberar classes de dependências internas ajuda a diminuir o tempo de compilação em todo o projeto.
  • A remoção de dependências não relacionadas ao código da interface do usuário facilita a reutilização dos componentes e reduz o tempo de compilação.
  • Atualizando um componente no Badoo Se o aplicativo depende de componentes do BadooUIKit, é muito fácil aplicar alterações em todo o aplicativo.
  • Componentes isolados são muito mais fáceis de testar.
  • Ter uma estrutura separada torna reutilizável em outros aplicativos, se necessário. Por exemplo, criando um aplicativo que lista e apresenta todos os componentes nesta estrutura.

O aplicativo da galeria




O BadooUIKit resolveu muitos de nossos problemas, mas sabíamos que ainda podíamos ir além, houve algumas melhorias que podem ser feitas no processo.

Como ver todos os componentes da interface do usuário isoladamente? Poderíamos criar uma maneira de encontrar componentes da interface do usuário e ver como eles ficariam com diferentes cores de código? Poderíamos torná-los facilmente testáveis? Havia alguma maneira de os designers terem um catálogo de todos os componentes de interface do usuário existentes que já estávamos implementando no iOS?

Como já tínhamos o BadooUIKit como uma estrutura de interface do usuário isolada, decidimos criar um aplicativo autônomo simples para uso interno. Apresentamos a Galeria Badoo.

O objetivo da Galeria Badoo é servir como uma ferramenta para desenvolvedores, designers e até equipes de produtos apresentarem os componentes da interface do usuário de maneira amigável. Nesta aplicação, implementamos muitos recursos diferentes que facilitam a interação com os componentes da interface do usuário.

Como esse aplicativo é uma ferramenta interna e não está prevista para lançamento na App Store, é possível adicionar qualquer recurso ou ferramenta que considerarmos necessário. No nosso caso, identificamos os seguintes recursos como sendo particularmente úteis:

  • Pesquisa de componentes
  • Classificação do nome do componente
  • Marcar como favorito
  • Comutador de vários estilos - para ver como nosso componente ficaria com diferentes folhas de estilo
  • Flex
  • Um visualizador de quadros por segundo



Cada componente pode ter muitos estados diferentes, dependendo da entrada do usuário ou da lógica intrínseca do aplicativo. Por exemplo, um UIButton simples define vários estados: padrão, destacado, focado, selecionado e desativado.

Curioso? Verifique aqui para mais informações.

Também queríamos apresentar todas as combinações em nossa galeria. Fazemos isso dentro de cada tela específica para qualquer componente. Obviamente, nossas próprias versões do botão podem ter estados diferentes do botão UIKit da Apple.



Este é um resumo dos principais benefícios da Galeria Badoo:

  • Lista todos os componentes da interface do usuário que implementamos no iOS
  • Pesquisa e localização fáceis de componentes da interface do usuário. Agora, todos na nossa equipe ou equipe de produtos podem ver todas as opções possíveis de um componente de interface do usuário e encontrar novos usos possíveis para eles
  • Ser capaz de encontrar facilmente componentes que já existem torna muito mais fácil convencer um designer a reutilizá-los
  • O tempo de compilação de um projeto muito pequeno como esta galeria é muito curto. A velocidade de desenvolvimento de todo o recurso pode ser reduzida com a implementação da interface do usuário neste aplicativo leve
  • O recurso de favoritos nos ajuda a encontrar os componentes que estamos implementando no momento
  • Adicionar ferramentas externas como FPS, multimarcas e flex ajuda a entender, melhorar e medir a qualidade dos componentes da interface do usuário que temos no catálogo
  • Todos esses componentes agora estão em uma estrutura separada e apresentados isoladamente. Isso os torna facilmente testáveis!

Sobre o teste


A maioria dos problemas iniciais listados no artigo foi resolvida com a introdução do novo conjunto de ferramentas:



Mas ainda havia alguns problemas que poderiam ser aprimorados, outras que precisavam ser respondidas: Ao fazer alterações, como podemos garantir que a interface do usuário tenha a aparência esperada após algumas alterações? Como podemos evitar que outras partes do aplicativo ou outros componentes sejam afetados adversamente quando "subcomponentes" são modificados?

Uma boa maneira de encontrar respostas para todas essas perguntas é adicionando testes aos componentes da interface do usuário. Já existe muita documentação sobre como implementar o teste de interface do usuário no iOS. Também existem muitas ferramentas diferentes disponíveis para testar diferentes aspectos da interface do usuário de um aplicativo.

No Badoo, decidimos começar a adicionar testes de instantâneo usando uma das "ferramentas" mais populares no momento para o teste de instantâneo: iOSSnapshotTestCase (anteriormente conhecido como FBSnapshotTestCase porque foi inicialmente criado e lançado como código aberto pelo Facebook).

Encontre mais informações sobre o teste de captura instantânea e essa estrutura específica nos seguintes links:



Precisávamos encontrar uma maneira de testar os componentes que já tínhamos no BadooUIKit, a fim de evitar possíveis regressões enquanto modificávamos os componentes usados ​​pelo restante do aplicativo.

Também queríamos automatizar o processo de adição de um novo teste de captura instantânea para um componente, tanto quanto possível.

Conforme explicado anteriormente neste artigo, também temos um aplicativo de galeria que lista todos os componentes e todos os diferentes estados que um único componente pode ter. É muito conveniente, pois permite que os testes de instantâneo sejam adicionados usando o Badoo Gallery como o aplicativo host.

Todos os componentes da interface do usuário implementados no BadooUIKit são armazenados em uma classe (padrão de repositório ou armazenamento) que fornece acesso a todos os componentes. Esse armazenamento pode ser instanciado para apresentar a lista de componentes na galeria e para acessá-los nas classes de teste de captura instantânea. Isso significa que não é necessário duplicar o trabalho de instanciar e preparar os diferentes estados de cada componente no nível de teste, porque isso já foi feito ao introduzir o componente na interface do aplicativo da galeria.

Estas são algumas perguntas que podem surgir em relação ao teste de captura instantânea. Permita-me fornecer algumas respostas:

Onde as imagens de instantâneo são armazenadas?

Nós os armazenamos diretamente no repositório git. Inicialmente, pensamos que ele poderia aumentar demais o tamanho do repositório, mas provou não ser tão ruim. Na maioria dos casos, não estamos testando telas inteiras, mas pequenos componentes e, portanto, as capturas de tela são muito leves. Atualmente, nossa pasta de capturas de tela tem cerca de 11 Mb, o que consideramos aceitáveis.

Todas as resoluções possíveis em todos os simuladores possíveis são testadas?

Não, o benefício não seria enorme e poderia causar inúmeros problemas, incluindo testes inadequados, uma pasta de instantâneos mais pesada e mais dificuldades em manter o conjunto de testes. Preferimos ser pragmáticos e testar apenas o dispositivo mais popular entre nossos usuários. Nosso sistema de integração contínua também é configurado para usar um simulador do mesmo modelo de dispositivo usado para fazer as capturas instantâneas.

Os testes de captura instantânea são suficientes para cobrir toda a interface do usuário?

Eu acho que não. No Badoo, também temos diferentes tipos de testes em diferentes níveis do aplicativo, como, por exemplo, testes funcionais (usamos as estruturas Calabash e KIF) e alguns testes de integração. Na minha experiência, é importante encontrar um bom equilíbrio entre o tipo de testes e a quantidade de testes necessários para atender aos requisitos de qualquer aplicativo.

Lições aprendidas


Obviamente, durante o processo de criação dessa nova plataforma, nossa empresa aprendeu muitas coisas e ainda estamos aprendendo a cada iteração. Todas as ferramentas e processos acima foram introduzidos em um período de 12 meses e ainda estão evoluindo. Até agora, todas as etapas se mostraram positivas, tanto para os desenvolvedores quanto para a empresa, e desde o início começamos a ver resultados positivos. Aqui estão algumas das lições que aprendemos durante esse processo:

  • Mover todos os componentes existentes de uma só vez é uma tarefa muito grande, mas criar o sistema de design e incentivar a equipe a usá-lo como parte do fluxo de desenvolvimento aumenta o número de componentes da interface do usuário passo a passo. Mover alguns componentes em todas as tarefas implementadas por alguns desenvolvedores não apenas aumenta automaticamente o número de elementos da interface do usuário em seu sistema, mas também desbloqueia e libera algumas dependências entre os elementos existentes. Isso facilita a tarefa de mover mais e mais componentes posteriormente.
  • Aprendemos que os designers estão felizes em reutilizar componentes existentes, mas é mais fácil convencê-los se pudermos demonstrar que já temos um componente totalmente funcional que se comporta de maneira muito semelhante ao que eles precisam.
  • A necessidade de economizar tempo a médio prazo é uma realidade. Todos sabemos que, no momento, os tempos de compilação nos projetos Swift + Objective-C não são os melhores. O aplicativo Galeria Badoo é muito leve e compila muito rápido. Aprendemos que é muito melhor implementar os componentes da interface do usuário diretamente usando o aplicativo da galeria como playground e depois usá-los no aplicativo principal, onde os tempos de compilação não são tão rápidos.
  • A existência de componentes em um UIKit específico e em um aplicativo de galeria, onde podemos testar facilmente os componentes, impulsiona todo o processo de teste e nos permite escrever testes com mais facilidade.


Indo além - Cosmos


No Badoo, nos preocupamos com todos os nossos recursos e queremos que eles tenham uma interface de usuário unificada e visualmente atraente para oferecer a nossos usuários a melhor experiência de qualidade ao usar todas as nossas plataformas. É por isso que estamos fazendo mudanças globais - com a ajuda das equipes de design e produto - em toda a empresa e implementando um sistema de design chamado Cosmos.



Cristiano Rastelli escreveu vários artigos interessantes, onde explica em detalhes como o Cosmos ganhou vida. Não perca!

Agradecimentos


Este projeto não era um trabalho individual: toda a equipe do iOS, incluindo gerentes, desenvolvedores e QAs, participou de uma maneira ou de outra. Eu tenho que agradecer a todos eles, porque posso dizer que todos estavam a bordo desde o início.

Graças à incrível equipe de design do Badoo, que está sempre disposta a ir além para melhorar os processos de design em toda a empresa.

Agradecimentos especiais a Alexander Zimin por várias melhorias e por sua participação em tantas reuniões sobre esse processo, bem como por me apoiar pessoalmente nessa aventura na interface do usuário. Também a Alyssa Ordillano por seus excelentes gráficos que melhoraram bastante a acessibilidade deste artigo.

Source: https://habr.com/ru/post/pt440920/


All Articles