Criando um Design System para uma empresa que duplica o número de funcionários
Em 2017 crescemos 60%, mas o visual do produto não acompanhou esse crescimento
Esse post é o primeiro de uma série sobre como estamos criando e utilizando o nosso design system aqui na Involves.
Se quiser ir direto para a parte “técnica”, vá para a seção: “Nosso Cenário”.
A Involves cresce em um ritmo muito acelerado e dinâmico, sempre temos novos projetos, desafios e involvidos talentosos chegando. Passamos de uma sala empresarial para um prédio de 3 andares em menos de 2 anos, e nossa equipe de desenvolvimento saiu de uma sala de reuniões para ocupar um auditório. Hoje são 40 desenvolvedores espalhados em 7 equipes que trabalham em nosso produto Agile Promoter.
Quando foi noticiado que o Flash (tecnologia que rodava toda nossa aplicação) não teria mais suporte para os navegadores de nossos clientes, tivemos um grande desafio: Ao mesmo tempo em que nossa equipe escalava, precisávamos migrar o nosso sistema do Flex para o AngularJS em um prazo curtíssimo.
Esta mudança rápida conciliada com uma forma de trabalho individual, causaram um grande débito técnico. Por isso foram criados testes, bugs críticos foram corrigidos, e assim naturalmente o produto evoluiu, principalmente devido a criação de uma equipe para cuidar dele. A contratação de novos QA’s, Designers, Desenvolvedores, e a melhoria contínua trabalhada em cada involvido, contribuíram para o período de maior estabilidade que vivemos hoje.
Mas ainda sim, nos deparamos regularmente com as seguintes situações:
- Como eu crio a base dessa tela?
- Quais os componentes que já existem no nosso produto?
- Essa parte está quebrada!
- Já temos um botão pra isso, por que duplicaram?
- Essa função é tão diferente, parece outro produto!
- Onde é o lugar certo pra eu criar isso?
A grama do vizinho é sempre mais verde
Ao mesmo tempo em que a migração rápida para uma nova tecnologia manteve nosso produto, ficamos sem documentação técnica sólida e sem muitos alinhamentos entre os desenvolvedores, dificultando a criação e padronização de novos componentes e módulos.
Quando somamos os desafios de criação junto aos desafios clássicos de qualquer produto (performance, qualidade, organização, débito técnico, código legado…) é fácil uma ideia que parece bastante simples invadir nossa cabeça: mudança de tecnologia.
Dizemos que nossos problemas são causados pelas nossas ferramentas atuais por dois motivos:
- Não somos especializados na tecnologia usada no produto
- Não sabemos o que queremos resolver.
Por isso, pensamos em mudar, dizendo:
Tecnologia X performa muito bem e faz A, B e C. Logo, se mudarmos, resolveremos nosso cenário
Isso ocorre porque esquecemos de pensar no que é realmente importante, que é trazer as lições aprendidas no passado, alinhar com o que a empresa quer no futuro e traçar um plano baseado no cenário atual, para então, tomarmos a melhor decisão.
Para isso acontecer devemos levar em consideração: O produto, para entregar o melhor resultado para nossos clientes; A empresa, sustentando seu crescimento; E a equipe de desenvolvedores, que precisa estar feliz. Não é preciosismo, trata-se de focar nas nossas necessidades e não na tentativa de implementar soluções que funcionaram em gigantes como Facebook e Google.
Cada empresa e projeto possuem problemas diferentes, e cada decisão não importa o tamanho, terá um impacto diferente a longo prazo. Por isso precisamos pensar muito bem, sendo sim abertos a mudanças, mas somente as que resolvem as nossas necessidades.
Nosso cenário
Temos vários desafios para atacar dentre as 7 equipes. A minha é a responsável por cuidar da evolução do front e, como um dos nossos objetivos é a melhoria do nosso cenário atual, decidimos começar pelo básico: os nossos componentes (documentação, aparência e performance).
Migrar de ferramenta nesse momento estaria fora de cogitação, iríamos adicionar complexidade desnecessária, piorando nossa base e nossa tecnologia atual (AngularJS), que apesar de ter perdido popularidade continua com sua base suportada, ainda possibilitando evolução e melhoria para nossos usuários.
Começamos idealizando alguns dos componentes em conjunto com a equipe de UI/UX (na época em formação) e, acabamos criando um repositório separado para os componentes serem desenvolvidos completamente desacoplados da nossa aplicação, permitindo a criação de testes para eles.
Os problemas que encontramos nesta abordagem:
- Não sabíamos exatamente que problema resolver, não tínhamos nenhum estudo aprofundado;
- Com pouco alinhamento, optamos por iniciar a criação dos componentes básicos;
- Como a equipe de designers e produto ainda estava em formação e trabalhando com a concepção do produto, não tínhamos uma base confiável de como os nossos componentes deveriam se comportar e como priorizar o desenvolvimento;
- Acabamos criando um gargalo para a nossa equipe pois precisávamos utilizar recursos da equipe de designers que ainda não estavam dedicados a isto, assim como cuidar das nossas tarefas do dia a dia;
- Para este repositório ser útil no nosso caso, nós precisaríamos de uma certa quantidade de componentes, que iriam demandar um bom tempo de todos, e não estávamos conseguindo dar foco para isso.
Então surge…
Enquanto desenvolvíamos esse projeto, as equipes de Produto e UI/UX ganharam maturidade e forma devido a novas contratações e especializações de cada membro. Assim, cada designer estaria destinado a pelo menos uma equipe de desenvolvimento, alinhando os objetivos de UI/UX ao contexto dos setores.
O novo contexto da organização permitiu que atacássemos um projeto mais ambicioso: Criar um Design System para toda a empresa, conhecendo o desafio e passando por todas as etapas necessárias de planejamento ANTES de começar a desenvolver.
No entanto, pelas tarefas do cotidiano e tendo gargalos na nossa equipe o desenvolvimento do repositório acabou ficando lento, então decidimos parar o projeto por hora.
Planejamento
A partir de um rico trabalho de investigação, envolvendo clientes e diversas áreas da empresa, a equipe de design levantou atributos do nosso produto, que resultaram em valores que queremos transmitir em todos os pontos de contato, como impactos no comportamento do sistema, design, textos, tom de voz… em praticamente TUDO! Desse modo, afim de garantir que esses atributos sejam aplicados, foi criado um grupo para discutir e alinhar a nossa marca (EBL).
Esse não foi o único alinhamento na empresa. A criação de um roadmap do produto e aprofundamento na metodologia de OKR’s trouxe mais clareza para todo o trabalho, desde a estratégia até a execução.
Beleza, temos todos estes dados, mas e agora?
O desafio de criar um Design System para todas as áreas abriu novos horizontes, pois agora os componentes teriam que ser utilizados em novos contextos e também deveriam ser fáceis de adaptar independente de escolhas tecnológicas futuras.
Optamos por utilizar a solução mais purista possível, criar um novo projeto no qual os componentes iriam ser feitos apenas com HTML e CSS, sem bibliotecas, frameworks, pré-processadores e etc.
Após isso, conseguimos inserir este desafio como um objetivo geral da empresa em forma de OKR graças ao roadmap, e assim foram escolhidos os primeiros componentes a serem desenvolvidos.
Para esta escolha, buscamos os componentes mais visíveis X com as interações mais simples e mapeamos todos os lugares onde eles eram utilizados.
Foi então alinhado entre os designers e desenvolvedores como iríamos abordar a criação dos componentes, definindo questões como:
- Nomenclatura dos componentes e de qualquer outra propriedade (cores, sombras, etc.);
- Organização das camadas, as layers, seguiriam quase que a mesma estrutura da implementação real;
- A forma como o designer iria entregar a documentação com o dev;
- Que convenções iríamos utilizar.
Optamos também por seguir a metodologia de design atômico, assim, todos iriam utilizar a mesma linguagem na hora de conversar.
Foi criada toda a base comum para os elementos: cores, tipografia, espaçamentos, sombras, bordas e elevações. E, para cada conjunto de componentes, usando essa base, foi criado “um pequeno monstro”, indicando a forma mais complexa possível para aquele tipo de componente. A cada nova etapa na concepção, a base dos componentes era revisitada e melhorada!
Fazendo isso, conseguimos ter uma noção do pior cenário possível para este componente, também conseguimos ver o que era possível fazer com ele e, consequentemente, eliminar componentes desnecessários no nosso produto atual.
Apenas desenvolvendo o componente de seleção monstro, eliminamos em torno de 7 componentes individuais no nosso produto!
Simplificar abre oportunidade de escalar
Diante do nosso cenário isso é perfeito, pois conseguimos eliminar componentes que não fazem sentido, identificamos um padrão a ser utilizado no sistema inteiro, o que melhora experiência do usuário e da equipe. Além disso, o desenvolvimento do componente ficaria inteiramente responsabilidade da nossa equipe de desenvolvimento, possibilitando a remoção de bibliotecas externas, atendendo as nossas necessidades.
Depois disso, pudemos finalmente quebrar este componente monstro de acordo com o uso, criar todas as alterações de estado possível e, finalmente, finalizar a documentação de tudo.
Porque optamos por utilizar uma abordagem purista
- A utilização de um pré-processador css pode deixar o código enxuto. Temos a possibilidade de criar funções, variáveis e laços de repetição;
- Utilizar Web Components também é uma proposta atraente, já que estaríamos utilizando a própria plataforma para o desenvolvimento de componentes independentes de tecnologia;
- Poderíamos ir para uma abordagem progressiva como o Vue.js, ou qualquer outra tecnologia que nos permita evoluir aos poucos o que temos. Afinal é simples… basta criar os componentes, injetar a ferramenta X na nossa aplicação e começar as substituições.
Mas como já foi mencionado, não queremos introduzir uma outra tecnologia neste momento e muito menos voltar a ter os mesmos problemas de antes. Também queremos dar a liberdade para qualquer um fazer a implementação do nosso Design System da forma como bem entenderem.
Quanto ao pré-processador, temos alguns benefícios ao utilizá-los, mas…
Algumas vantagens de utilizar apenas CSS
- Teremos mais controle do que será escrito;
- O próprio CSS já supre a maior parte das nossas necessidades, principalmente com a vinda de variáveis, e ele continuará evoluindo;
- Tendo um bom guia de convenções, é muito mais fácil para a nossa equipe criar algo;
- Dependendo do tamanho do projeto e do número de imports, o tempo de compilação do pré-processador pode acabar sendo mais lento, além de precisarmos baixar mais dependências na sua instalação;
- Evitamos de cometer erros como o uso incorreto do extend;
- Temos mais incentivo a apenas escrever no MÁXIMO 2 NÍVEIS de nesting, já que não é tão atraente fazer isso utilizando CSS puro. Mantendo esta restrição, diminuímos a complexidade, forçamos o usuário a quebrar os componentes em mais partes e mantemos a especificidade dos seletores baixa;
- Embora seja vantajoso criar funções nos pré-processadores, a nossa equipe de desenvolvimento acabou não tendo uma boa experiência com isso, pelo fato de poderem ser confusas e, às vezes, desnecessárias. Em alguns casos tentamos prever o futuro criando funções genéricas a fim de escrever menos código, mas como o MPJ fala… nós somos terríveis em prever o futuro
Acabamos então optando pela forma mais simples possível, assim qualquer um poderia entender e nos ajudar a evoluir este sistema. Entretanto, para evitar que as coisas fujam de controle, elaboramos um processo rigoroso para a aprovação de mudanças na implementação do nosso Design System.
Dando início a base
Com tudo devidamente decidido e planejado, começamos com o desenvolvimento da base, a criação do nosso repositório, junto do nosso componente de referência, o botão.
Primeiro, foi criada a base de pastas mínimas:
# Exemplo de estrutura
css/
├── base/
│ ├── variables/
│ │ ├── typhography.css
| | └── variables.css
| └── base.css
│ ├── themes/
| | └── default.css
├── components/
| └── button.css
Neste caso, esta estrutura não seria muito modificada, independente da forma como fôssemos estruturar o nosso repositório. Em paralelo, foram feitas várias interações com o designer, melhorando a documentação (escritas, nomenclaturas e a forma como os mocks estavam distribuídos).
Os exemplos de arquivos que criamos inicialmente:
Tendo o mapeamento de todas as variáveis levantadas pela equipe de UI/UX, foi criado o componente button.css, assim teríamos uma representação mínima do que iríamos precisar.
Em seguida buscamos referências de guias de estilo, e Designs Systems no mercado, tomando como inspiração:
Para a construção da base, queríamos algo simples, que atendesse os seguintes critérios:
- Deveria conter um ambiente no qual fosse possível desenvolver os componentes (HMR, fácil de criar algo novo);
- Poderíamos escrever documentações para cada componente e textos genéricos;
- Deveríamos criar testes de regressão visual;
- Deveria ser possível gerar um build minificado do nosso sistema;
- Deveria ser fácil de utilizar, tanto para um desenvolvedor quanto para um designer;
- Os componentes deveriam estar à mostra (já que não iriamos despender esforços para criar uma página customizada para os componentes naquele momento).
Foi feito um spike e chegamos em 3 possíveis soluções iniciais. A mais palpável era a de tentamos criar uma baseada no primer.css, porém ainda não estávamos contentes com o resultado.
Então um desenvolvedor de outra equipe nos trouxe uma sugestão de ferramenta, que acabou sendo a nossa melhor opção de escolha:
Fractal — https://github.com/frctl/fractal
Esta ferramenta caiu como uma luva. Conseguimos, praticamente sem esforço, criar toda a base necessária, atendendo todos os critérios que tínhamos levantado. Após esta base estar pronta, adaptamos a nossa estrutura de pastas CSS com a estrutura criada e pudemos, finalmente, dar início a criação do nosso Design System como um todo.
Para a Parte 2, detalharemos como cada componente foi desenvolvido, também revelaremos o repositório do nosso Design System (Open Source), abordando mais as partes técnicas.
Gostaria de agradecer a todos os que se envolveram neste post, Augusto Sobieski, o meu time ExD (Monica Possel, Paulo Martins, Gabriel Werlich, Igor Carneiro e Jorge Maronezzi).