Projetando e construindo um aplicativo da Web progressivo sem uma estrutura (Parte 3)
Publicados: 2022-03-10De volta à primeira parte desta série, explicamos por que esse projeto surgiu. Ou seja, um desejo de aprender como um pequeno aplicativo da Web pode ser feito em JavaScript vanilla e fazer com que um desenvolvedor não projetista trabalhe um pouco em suas habilidades de design.
Na parte dois, pegamos alguns projetos iniciais básicos e colocamos as coisas em funcionamento com algumas opções de ferramentas e tecnologia. Cobrimos como e por que partes do design mudaram e as ramificações dessas mudanças.
Nesta parte final, abordaremos como transformar um aplicativo Web básico em um Aplicativo Web Progressivo (PWA) e 'enviar' o aplicativo antes de examinar as lições mais valiosas aprendidas ao tornar o aplicativo Web simples In/Out:
- O enorme valor dos métodos de array JavaScript;
- Depuração;
- Quando você é o único desenvolvedor, você é o outro desenvolvedor;
- Design é desenvolvimento;
- Problemas contínuos de manutenção e segurança;
- Trabalhar em projetos paralelos sem perder a cabeça, a motivação ou ambos;
- O envio de algum produto supera o envio de nenhum produto.
Portanto, antes de analisar as lições aprendidas, vamos ver como você transforma um aplicativo da Web básico escrito em HTML, CSS e JavaScript em um aplicativo da Web progressivo (PWA).
Em termos de tempo total gasto para fazer este pequeno aplicativo da web, eu diria que provavelmente foi em torno de duas a três semanas. No entanto, como foi feito em pedaços de 30 a 60 minutos à noite, demorou cerca de um ano desde o primeiro commit até o upload do que considero a versão '1.0' em agosto de 2018. Como eu obtive o aplicativo ' recurso completo', ou mais simplesmente falando, em um estágio com o qual eu estava feliz, eu antecipei um grande empurrão final. Veja bem, eu não tinha feito nada para transformar o aplicativo em um Progressive Web Application. Acontece que essa foi realmente a parte mais fácil de todo o processo.
Fazendo um aplicativo da Web progressivo
A boa notícia é que, quando se trata de transformar um pequeno aplicativo baseado em JavaScript em um 'Progressive Web App', existem muitas ferramentas para facilitar a vida. Se você voltar à primeira parte desta série, lembrará que ser um Progressive Web App significa atender a um conjunto de critérios.
Para entender como o seu aplicativo da web se comporta, sua primeira parada provavelmente deve ser as ferramentas Lighthouse do Google Chrome. Você pode encontrar a auditoria do Progressive Web App na guia 'Auditorias'.
Isto é o que Lighthouse me disse quando executei o In/Out pela primeira vez.
No início, o In/Out estava obtendo apenas uma pontuação de 55 ⁄ 100 para um Progressive Web App. No entanto, eu levei de lá para 100 ⁄ 100 em menos de uma hora!
A conveniência em melhorar essa pontuação tinha pouco a ver com minha habilidade. Foi simplesmente porque Lighthouse me disse exatamente o que precisava ser feito!
Alguns exemplos de etapas de requisitos: inclua um arquivo manifest.json
(essencialmente um arquivo JSON fornecendo metadados sobre o aplicativo), adicione uma grande quantidade de metatags no cabeçalho, troque as imagens que foram incorporadas no CSS para imagens referenciadas em URL padrão, e adicione um monte de imagens da tela inicial.
Criar várias imagens da tela inicial, criar um arquivo de manifesto e adicionar várias metatags pode parecer muito para fazer em menos de uma hora, mas existem aplicativos da Web maravilhosos para ajudá-lo a criar aplicativos da Web. Que legal isso! Eu usei https://app-manifest.firebaseapp.com. Alimente-o com alguns dados sobre seu aplicativo e seu logotipo, clique em enviar e ele fornecerá um arquivo zip contendo tudo o que você precisa! A partir daí, é só copiar e colar.
Coisas que eu adiei por algum tempo devido à falta de conhecimento, como um Service Worker, também foram adicionadas com bastante facilidade graças a inúmeras postagens de blog e sites dedicados a service workers como https://serviceworke.rs. Com um service worker, isso significava que o aplicativo poderia funcionar offline, um recurso necessário de um Progressive Web Application.
Embora não esteja estritamente relacionado a tornar o aplicativo um PWA, a guia 'cobertura' do Chrome Dev Tools também foi muito útil. Após tantas iterações esporádicas no design e no código ao longo de meses, foi útil obter uma indicação clara de onde havia código redundante. Encontrei algumas funções antigas espalhadas pela base de código que eu simplesmente esqueci!
Em pouco tempo, tendo trabalhado com as recomendações de auditoria do Lighthouse, me senti como o animal de estimação do professor:
A realidade é que pegar o aplicativo e torná-lo um Progressive Web Application foi incrivelmente simples.
Com essa parte final do desenvolvimento concluído, fiz o upload do pequeno aplicativo para um subdomínio do meu site e foi isso.
Retrospectivo
Meses se passaram desde que estacionei o desenvolvimento do meu pequeno aplicativo da web.
Eu usei o aplicativo casualmente nos meses desde então. A realidade é que muito da organização de esportes coletivos que faço ainda acontece via mensagem de texto. A aplicação é, no entanto, definitivamente mais fácil do que anotar quem está dentro e fora do que encontrar um pedaço de papel todas as noites de jogo.
Então, a verdade é que dificilmente é um serviço indispensável. Tampouco estabelece limites para desenvolvimento ou design. Eu não poderia dizer que estou 100% feliz com isso também. Cheguei a um ponto em que fiquei feliz em abandoná-lo.
Mas esse nunca foi o objetivo do exercício. Tirei muito da experiência. O que se segue são os que considero os mais importantes.
Design é desenvolvimento
No início, eu não valorizava o design o suficiente. Comecei este projeto acreditando que meu tempo gasto desenhando com um bloco e caneta ou no aplicativo Sketch, era um tempo que poderia ser melhor gasto com codificação. No entanto, acontece que quando fui direto para o código, muitas vezes eu estava apenas sendo um tolo ocupado. Explorar os conceitos primeiro com a menor fidelidade possível, economizou muito mais tempo a longo prazo.
Houve inúmeras ocasiões no início em que horas foram gastas fazendo algo funcionar no código apenas para perceber que era fundamentalmente falho do ponto de vista da experiência do usuário.
Minha opinião agora é que papel e lápis são as melhores ferramentas de planejamento, design e codificação. Todos os problemas significativos enfrentados eram resolvidos principalmente com papel e lápis; o editor de texto apenas um meio de executar a solução. Sem algo que faça sentido no papel, não há chance de funcionar em código.
A próxima coisa que aprendi a apreciar, e não sei por que demorou tanto para descobrir, é que o design é iterativo. Eu subconscientemente acreditei no mito de um Designer com “D” maiúsculo. Alguém se agitando, segurando sua lapiseira nas bordas retas, encerando letras líricas sobre tipos de letra e bebendo um branco liso (com leite de soja, obviamente) antes de casualmente dar à luz a perfeição visual totalmente formada no mundo.
Isso, não muito diferente da noção do programador 'gênio', é um mito. Se você é novo no design, mas está tentando, sugiro que não fique preso à primeira ideia que desperta sua empolgação. É tão barato tentar variações, então abrace essa possibilidade. Nenhuma das coisas que eu gosto no design de In/Out estava lá nos primeiros designs.
Acredito que foi o romancista Michael Crichton quem cunhou a máxima: “Livros não são escritos – eles são reescritos”. Aceite que todo processo criativo é essencialmente o mesmo. Esteja ciente de que confiar no processo diminui a ansiedade e a prática refinará sua compreensão e julgamento estéticos.
Você é o outro desenvolvedor do seu projeto
Não tenho certeza se isso é específico para projetos que só são trabalhados esporadicamente, mas fiz a seguinte suposição imprudente:
“Não preciso documentar nada disso porque sou só eu, e obviamente vou entender porque escrevi.”
Nada poderia estar mais longe da verdade!
Houve noites em que, durante os 30 minutos que tive para trabalhar no projeto, não fiz nada além de tentar entender uma função que havia escrito seis meses atrás. As principais razões pelas quais a reorientação do código demorou tanto foi a falta de comentários de qualidade e variáveis mal nomeadas e argumentos de função.
Sou muito diligente em comentar código no meu trabalho diário, sempre consciente de que outra pessoa pode precisar entender o que estou escrevendo. No entanto, neste caso, eu era essa outra pessoa. Você realmente acha que vai se lembrar de como funciona o bloco de código que você escreveu em seis meses? Você não vai. Confie em mim, tire um tempo e comente essa coisa!
Desde então, li um post no blog intitulado Seu marcador de sintaxe está errado sobre a importância dos comentários. A premissa básica é que os marcadores de sintaxe não devem desaparecer os comentários, eles devem ser a coisa mais importante. Estou inclinado a concordar e se eu não encontrar um tema de editor de código em breve que coce essa coceira, talvez tenha que adaptar um para esse fim!
Depuração
Quando você encontra bugs e escreveu todo o código, não é injusto sugerir que o erro provavelmente se originou entre o teclado e a cadeira. No entanto, antes de assumir isso, sugiro que você teste até mesmo suas suposições mais básicas. Por exemplo, lembro-me de ter demorado mais de duas horas para corrigir um problema que presumi ser devido ao meu código; no iOS, não consegui que minha caixa de entrada aceitasse entrada de texto. Não me lembro por que isso não me parou antes, mas me lembro da minha frustração com o problema.
Acontece que foi devido a um bug, ainda a ser corrigido, no Safari. Acontece que no Safari se você tiver:
* { user-select: none; }
Em sua folha de estilo, as caixas de entrada não aceitam nenhuma entrada. Você pode contornar isso com:
* { user-select: none; } input[type] { user-select: text; }
Qual é a abordagem que adoto no meu reset CSS “App Reset”. No entanto, a parte realmente frustrante disso foi que eu já havia aprendido isso e, posteriormente, esquecido. Quando finalmente consegui verificar o rastreamento de bugs do WebKit enquanto solucionava o problema, descobri que havia escrito uma solução alternativa no tópico de relatório de bug há mais de um ano, completa com redução!
Quer construir com dados? Aprenda métodos de array JavaScript
Talvez o maior avanço que minhas habilidades em JavaScript obtiveram ao passar por este exercício de criação de aplicativos foi me familiarizar com os métodos de matriz de JavaScript. Agora eu os uso diariamente para todas as minhas necessidades de iteração e manipulação de dados. Eu não posso enfatizar o suficiente como métodos úteis como map()
, filter()
, every()
, findIndex()
, find()
e reduce()
são. Você pode resolver praticamente qualquer problema de dados com eles. Se você ainda não os tem em seu arsenal, marque https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array agora e pesquise assim que puder. Meu próprio resumo dos meus métodos de array favoritos está documentado aqui.
O ES6 introduziu outras economias de tempo para manipular arrays, como Set
, Rest
e Spread
. Mime-se enquanto compartilho um exemplo; costumava haver um monte de problemas se você quisesse remover duplicatas até mesmo de uma simples matriz plana. Não mais.
Considere este exemplo simples de um Array com a entrada duplicada, “Mr Pink”:
let myArray = [ "Mr Orange", "Mr Pink", "Mr Brown", "Mr White", "Mr Blue", "Mr Pink" ];
Para se livrar das duplicatas com o JavaScript ES6, agora você pode fazer:
let deDuped = [...new Set(myArray)]; // deDuped logs ["Mr Orange", "Mr Pink", "Mr Brown", "Mr White", "Mr Blue"]
Algo que costumava exigir a execução manual de uma solução ou a busca por uma biblioteca agora está incorporado à linguagem. É certo que, em um Array curto, isso pode não parecer grande coisa, mas imagine quanto tempo isso economiza ao olhar para arrays com centenas de entradas e duplicatas.
Manutenção e segurança
Qualquer coisa que você construa que faça qualquer uso do NPM, mesmo que apenas para ferramentas de compilação, traz a possibilidade de ser vulnerável a problemas de segurança. O GitHub faz um bom trabalho em mantê-lo ciente de possíveis problemas, mas ainda há algum fardo de manutenção.
Para algo que é um mero projeto paralelo, isso pode ser um pouco doloroso nos meses e anos que seguem o desenvolvimento ativo.
A realidade é que toda vez que você atualiza dependências para corrigir um problema de segurança, você introduz a possibilidade de quebrar sua compilação.
Por meses, meu package.json
ficou assim:
{ "dependencies": { "gulp": "^3.9.1", "postcss": "^6.0.22", "postcss-assets": "^5.0.0" }, "name": "In Out", "version": "1.0.0", "description": "simple utility to see who's in and who's out", "main": "index.js", "author": "Ben Frain", "license": "MIT", "devDependencies": { "autoprefixer": "^8.5.1", "browser-sync": "^2.24.6", "cssnano": "^4.0.4", "del": "^3.0.0", "gulp-htmlmin": "^4.0.0", "gulp-postcss": "^7.0.1", "gulp-sourcemaps": "^2.6.4", "gulp-typescript": "^4.0.2", "gulp-uglify": "^3.0.1", "postcss-color-function": "^4.0.1", "postcss-import": "^11.1.0", "postcss-mixins": "^6.2.0", "postcss-nested": "^3.0.0", "postcss-simple-vars": "^4.1.0", "typescript": "^2.8.3" } }
E em junho de 2019, eu estava recebendo esses avisos do GitHub:
Nenhum estava relacionado a plugins que eu estava usando diretamente, todos eram subdependências das ferramentas de construção que eu tinha usado. Essa é a faca de dois gumes dos pacotes JavaScript. Em termos do aplicativo em si, não houve problema com o In/Out; que não estava usando nenhuma das dependências do projeto. Mas como o código estava no GitHub, me senti no dever de tentar consertar as coisas.
É possível atualizar os pacotes manualmente, com algumas alterações de escolha no package.json. No entanto, tanto o Yarn quanto o NPM têm seus próprios comandos de atualização. Optei por executar o yarn upgrade-interactive
que oferece um meio simples de atualizar as coisas do terminal.
Parece bastante fácil, há até uma pequena tecla colorida para informar quais atualizações são mais importantes.
Você pode adicionar o sinalizador --latest
para atualizar para a versão principal mais recente das dependências, em vez de apenas para a versão corrigida mais recente. Por um centavo…
O problema é que as coisas se movem rapidamente no mundo dos pacotes JavaScript, então atualizar alguns pacotes para a versão mais recente e tentar uma compilação resultou nisso:
Como tal, reverti meu arquivo package.json
e tentei novamente desta vez sem o sinalizador --latest
. Isso resolveu meus problemas de segurança. Não é o mais divertido que tive em uma noite de segunda-feira, embora eu seja honesto.
Isso toca em uma parte importante de qualquer projeto paralelo. Ser realista com suas expectativas.
Projetos paralelos
Não sei se você é o mesmo, mas descobri que um otimismo vertiginoso e a excitação me fazem começar projetos e se algo der certo, o constrangimento e a culpa me fazem terminá-los.
Seria uma mentira dizer que a experiência de fazer este pequeno aplicativo no meu tempo livre foi divertida. Houve ocasiões em que eu gostaria de nunca ter aberto minha boca sobre isso para ninguém. Mas agora que está feito, estou 100% convencido de que valeu a pena o tempo investido.
Dito isso, é possível mitigar a frustração com esse projeto paralelo sendo realista sobre quanto tempo levará para entender e resolver os problemas que você enfrenta. Só tem 30 minutos por noite, algumas noites por semana? Você ainda pode concluir um projeto paralelo; apenas não fique descontente se o seu ritmo parecer glacial. Se as coisas não puderem desfrutar de toda a sua atenção, prepare-se para um ritmo mais lento e constante do que talvez esteja acostumado. Isso é verdade, seja codificando, concluindo um curso, aprendendo a fazer malabarismos ou escrevendo uma série de artigos sobre por que demorou tanto para escrever um pequeno aplicativo da web!
Definição simples de metas
Você não precisa de um processo sofisticado para definir metas. Mas pode ajudar a dividir as coisas em tarefas pequenas/curtas. Coisas tão simples como 'escrever CSS para o menu suspenso' são perfeitamente alcançáveis em um espaço de tempo limitado. Enquanto 'pesquisar e implementar um padrão de projeto para gerenciamento de estado' provavelmente não. Quebre as coisas. Então, assim como Lego, os pequenos pedaços vão juntos.
Pensando nesse processo como uma solução para o problema maior, lembro-me da famosa citação de Bill Gates:
“A maioria das pessoas superestima o que pode fazer em um ano e subestima o que pode fazer em dez anos.”
Isto de um homem que está ajudando a erradicar a pólio. Bill conhece suas coisas. Ouçam Bill vocês.
Enviar algo é melhor do que enviar nada
Antes de 'enviar' este aplicativo da web, revisei o código e fiquei completamente desanimado.
Embora eu tivesse iniciado essa jornada a partir de um ponto de completa ingenuidade e inexperiência, eu tinha feito algumas escolhas decentes quando se tratava de como eu poderia arquitetar (se você me perdoa um termo tão grandioso) o código. Eu pesquisei e implementei um padrão de design e gostei de tudo que esse padrão tinha a oferecer. Infelizmente, como fiquei mais desesperado para concluir o projeto, falhei em manter a disciplina. O código como está é uma verdadeira miscelânea de abordagens e repleta de ineficiências.
Nos meses desde que percebi que essas deficiências realmente não importam. Na verdade.
Eu sou um fã desta citação de Helmuth von Moltke.
“Nenhum plano de operações se estende com certeza além do primeiro contato com a principal força hostil.”
Isso foi parafraseado como:
“Nenhum plano sobrevive ao primeiro contato com o inimigo”.
Talvez possamos resumir ainda mais e simplesmente ir com “merda acontece”?
Posso supor que cheguei a um acordo com o que foi enviado através da seguinte analogia.
Se um amigo anunciasse que tentaria correr sua primeira maratona, o que importaria seria que eles ultrapassassem a linha de chegada – eu não estaria repreendendo-os pelo tempo de chegada.
Eu não me propus a escrever o melhor aplicativo da web. A missão que me propus era simplesmente projetar e fazer um.
Mais especificamente, de uma perspectiva de desenvolvimento, eu queria aprender os fundamentos de como um aplicativo da web foi construído. Do ponto de vista do design, eu queria tentar resolver alguns problemas de design (embora simples) para mim. Fazer este pequeno aplicativo atendeu a esses desafios e mais alguns. O JavaScript para todo o aplicativo era de apenas 5 KB (gzipado). Um tamanho de arquivo pequeno que eu lutaria para chegar com qualquer estrutura. Exceto talvez Svelte.
Se você está se colocando em um desafio dessa natureza e espera em algum momento 'enviar' algo, anote desde o início por que você está fazendo isso. Mantenha essas razões na vanguarda de sua mente e seja guiado por elas. Em última análise, tudo é algum tipo de compromisso. Não deixe que ideais elevados o impeçam de terminar o que você se propôs a fazer.
Resumo
No geral, como faz um ano desde que trabalhei no In/Out, meus sentimentos se dividem amplamente em três áreas: coisas das quais me arrependi, coisas que gostaria de melhorar/consertar e possibilidades futuras.
Coisas que me arrependi
Como já mencionado, fiquei desapontado por não ter aderido ao que considerava um método mais elegante de alterar o estado do aplicativo e renderizá-lo para o DOM. O padrão do observador, conforme discutido na segunda parte desta série, que resolveu tantos problemas de maneira previsível, acabou sendo deixado de lado quando o 'transporte' do projeto se tornou uma prioridade.
Fiquei envergonhado com meu código no início, mas nos meses seguintes, fiquei mais filosófico. Se eu não tivesse usado mais técnicas de pedestres mais tarde, há uma possibilidade muito real de o projeto nunca ter sido concluído. Colocar algo no mundo que precisa ser melhorado ainda é melhor do que nunca ter nascido no mundo.
Melhorando a entrada/saída
Além de escolher a marcação semântica, não fiz possibilidades de acessibilidade. Quando criei o In/Out, eu estava confiante com a acessibilidade padrão da página da Web, mas não tinha conhecimento suficiente para lidar com um aplicativo. Eu fiz muito mais trabalho/pesquisa nessa área agora, então eu gostaria de dedicar um tempo para fazer um trabalho decente de tornar este aplicativo mais acessível.
A implementação do design revisado da funcionalidade 'Adicionar pessoa' foi apressada. Não é um desastre, apenas um pouco mais áspero do que eu gostaria. Seria bom fazer isso mais escorregadio.
Também não considerei telas maiores. Seria interessante considerar os desafios de design de fazê-lo funcionar em tamanhos maiores, além de simplesmente torná-lo um tubo de conteúdo.
Possibilidades
Usar localStorage funcionou para minhas necessidades simplistas, mas seria bom ter um armazenamento de dados 'adequado' para que não fosse necessário se preocupar em fazer backup dos dados. Adicionar capacidade de login também abriria a possibilidade de compartilhar a organização do jogo com outro indivíduo. Ou talvez cada jogador pudesse apenas marcar se eles estavam jogando sozinhos? É incrível quantos caminhos para explorar você pode imaginar a partir de um começo tão simples e humilde.
O desenvolvimento de aplicativos SwiftUI para iOS também é intrigante. Para alguém que só trabalhou com linguagens da web, à primeira vista, o SwiftUI parece algo que agora estou encorajado a experimentar. Eu provavelmente tentaria reconstruir o In/Out com o SwiftUI — apenas para ter algo específico para construir e comparar a experiência de desenvolvimento e os resultados.
E então, é hora de encerrar as coisas e dar a você a versão TL;DR de tudo isso.
Se você quiser aprender como algo funciona na web, sugiro pular as abstrações. Abandone os frameworks, sejam CSS ou JavaScript, até que você realmente entenda o que eles estão fazendo para você.
O design é iterativo, abrace esse processo.
Resolva problemas no meio de menor fidelidade à sua disposição. Não vá para o código se você puder testar a ideia no Sketch. Não desenhe no Sketch se você puder usar papel e caneta. Escreva a lógica primeiro. Em seguida, escreva-o em código.
Seja realista, mas nunca desanimado. Desenvolver o hábito de fazer algo por apenas 30 minutos por dia pode obter resultados. Esse fato é verdadeiro qualquer que seja a forma que sua busca assuma.