<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bruno Noriller</title>
    <description>The latest articles on Forem by Bruno Noriller (@noriller).</description>
    <link>https://forem.com/noriller</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F704107%2Fc5967cc2-b1a9-47e1-a052-6675877b5835.jpeg</url>
      <title>Forem: Bruno Noriller</title>
      <link>https://forem.com/noriller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/noriller"/>
    <language>en</language>
    <item>
      <title>Slop is the new normal</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Wed, 30 Apr 2025 00:08:03 +0000</pubDate>
      <link>https://forem.com/noriller/slop-is-the-new-normal-248l</link>
      <guid>https://forem.com/noriller/slop-is-the-new-normal-248l</guid>
      <description>&lt;p&gt;AI has its uses. In some places, it can be great, but in others, it will be lethal and have unintended and not thought-out consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slop in Time
&lt;/h2&gt;

&lt;p&gt;We are living the what? Second year in the 6 months to be replaced by AI?&lt;/p&gt;

&lt;p&gt;Yes, it’s certainly better. Today, you can run on a cheap GPU a model that will outperform the first iterations of what was being used with GitHub Copilot.&lt;/p&gt;

&lt;p&gt;I remember being excited about using it and how good the completions were. Did I use it to write full functions and whatnot? NO!&lt;/p&gt;

&lt;p&gt;I used it as a “super autocomplete” to finish writing the line of code I was already writing.&lt;/p&gt;

&lt;p&gt;Nowadays, it can complete multiple lines, even full files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slop in Love
&lt;/h2&gt;

&lt;p&gt;While I did remember it completing lines, and today that and more. Nowadays, I see and get more annoyed at how much it fails to do that.&lt;/p&gt;

&lt;p&gt;Why does it keep failing me so much? Wasn’t it supposed to be a better model?&lt;/p&gt;

&lt;p&gt;At first, it will look perfect, but with time, more cracks will show and love will fade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diversity of Slop
&lt;/h2&gt;

&lt;p&gt;This applies to code, images, songs, and any kind of slop there is. Yes, it &lt;em&gt;seems&lt;/em&gt; good, at a distance, without caring too much about the details.&lt;/p&gt;

&lt;p&gt;An image might get a pass. How long do people stare at those?&lt;/p&gt;

&lt;p&gt;A song might get a pass. Just a quirk, some might say.&lt;/p&gt;

&lt;p&gt;But code is a prick of a thing. It either will run or not. And even when it runs, it might not do what you thought it would.&lt;/p&gt;

&lt;p&gt;And the more you see, the worse it all gets. Generated images are only as good as you look at a distance, and generated music always seems to be the same music, and code is a disaster away because no one is thinking about the details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slop is in the Details
&lt;/h2&gt;

&lt;p&gt;I like this masterclass Uncle Bob gave: &lt;a href="https://www.youtube.com/playlist?list=PLo61EKto8ZPHUOld83z0pwpzdlioliu6j" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PLo61EKto8ZPHUOld83z0pwpzdlioliu6j&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And while I would recommend watching everything, I want to point out first to &lt;a href="https://youtu.be/7EmboKQH8lM?si=08jAkwIxvP_s-p2b&amp;amp;t=955" rel="noopener noreferrer"&gt;here&lt;/a&gt; where Uncle Bob starts telling that “when you put your foot in the brake of a car, do you believe that there’s a cable going from the pedal to the brake disks? Or do you realize there are ‘if’ statements in the way? Who wrote those ‘if’ statements deciding whether or not to stop the car when you push on the brake?” and then jump a little forward to &lt;a href="https://youtu.be/7EmboKQH8lM?si=xgjxK4prALqwCndy&amp;amp;t=1190" rel="noopener noreferrer"&gt;here&lt;/a&gt; where he says that society will wake up to the fact that “we” (programmers) rule everything with code when “a poor programmer does some dumb thing and kills 10_000 people in a shot, then the politicians of the world will rise in indignation and point their finger at us”.&lt;/p&gt;

&lt;p&gt;These classes have been on YouTube for over 5 years. I don’t know when it took place, but I’m certain that even before, he probably gave the same speech other times.&lt;/p&gt;

&lt;p&gt;In this case, it was about the craftsmanship and even taking jabs at code being written by “some 22-year-old at 3 in the morning”. This was then.&lt;/p&gt;

&lt;p&gt;Today, it would be a 16-year-old talking to a possibly hallucinating AI that will throw everything in a word mixer and slop a whole new file with code in every interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sloping around
&lt;/h2&gt;

&lt;p&gt;Remember when any grocery store wanted a mobile app? (Or maybe you still suffer because you need an app for some dumb thing that didn’t need to be an app?)&lt;/p&gt;

&lt;p&gt;Today it’s AI, and be certain that there will be a lot of that being shoved and slopped everywhere.&lt;/p&gt;

&lt;p&gt;But more than that… do you trust the custom shopping cart asking for your credit information was “hand-made” or was it “vibe coded”? What about the car you’re driving? Or the one heading your way? Your bank? How about some software that keeps all your memories?&lt;/p&gt;

&lt;p&gt;Some people are announcing that the app was “vibe coded” as a mark of pride. I see it as a giant red flag, and I’m sure that many don’t announce it.&lt;/p&gt;

&lt;p&gt;I might be an alarmist, but then again, I check both sides of a one-way street twice before crossing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Remoto é bom e pode melhorar!</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Mon, 03 Mar 2025 15:25:38 +0000</pubDate>
      <link>https://forem.com/noriller/remoto-e-bom-e-pode-melhorar-1ja4</link>
      <guid>https://forem.com/noriller/remoto-e-bom-e-pode-melhorar-1ja4</guid>
      <description>&lt;p&gt;Tivemos toda a história de trabalhar em um escritório… mas apenas alguns anos trabalhando remotamente e, no pior dos casos… foi apenas um pouco “pior” (em termos de produtividade) e isso sem contar que tudo começou em uma maldita pandemia!&lt;/p&gt;

&lt;p&gt;Trabalho remoto não é para todos os tipos de função e nem para todas as pessoas (algumas já experimentaram trabalhar remotamente em outros contextos e não gostaram), existem razões válidas contra ele e momentos ou lugares onde não é a melhor opção.&lt;/p&gt;

&lt;p&gt;No entanto, há muitas razões que não têm nada a ver com o que se possa dizer sobre o trabalho remoto ser bom ou ruim, e que ficarão fora do escopo deste artigo porque por algum motivo, trabalhar remotamente se tornou algo controverso por razões alheias à própria natureza do trabalho remoto.&lt;/p&gt;

&lt;p&gt;De qualquer forma, este artigo explora a minha jornada pelo trabalho remoto — desde a transição inicial durante a pandemia, passando pelos desafios e benefícios que experimentei como programador com formação em administração, até como torná-lo ainda melhor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Vamos Lembrar de Algumas Coisas
&lt;/h2&gt;

&lt;p&gt;Se você está lendo isto próximo da data de publicação, então provavelmente compartilhamos que passamos pela pandemia. E, para muitos, inclusive eu, foi a primeira vez trabalhando remotamente.&lt;/p&gt;

&lt;p&gt;Alguns gostaram e não querem voltar a um escritório, outros odiaram e nunca mais querem tentar novamente.&lt;/p&gt;

&lt;p&gt;Mas aqui vai o lembrete: não foi tudo ruim ou tudo bom.&lt;/p&gt;

&lt;p&gt;Temos que lembrar que foi uma pandemia, mesmo que algumas pessoas tentassem fingir o contrário. As pessoas foram separadas, ficaram estressadas, solitárias, preocupadas… havia muitas emoções em jogo e os lockdowns não ajudaram.&lt;/p&gt;

&lt;p&gt;No entanto, hoje, sem uma pandemia, as coisas são um pouco diferentes. Você pode trabalhar de casa e depois sair sem preocupações, pode trabalhar e depois encontrar os amigos e fazer outra coisa.&lt;/p&gt;

&lt;p&gt;O trabalho remoto no cenário atual é diferente do que era naquela época. E se as piores estimativas indicavam que o trabalho remoto era apenas um pouco inferior… com tudo o que estava acontecendo, o que dizer hoje, quando está muito melhor?&lt;/p&gt;




&lt;h2&gt;
  
  
  Por que Estou Escrevendo Isto?
&lt;/h2&gt;

&lt;p&gt;Há muito tempo… ou o que parece ser há muito tempo… eu simplesmente “ia trabalhar” porque isso era considerado “normal” e, então, veio a pandemia e eu passei a trabalhar totalmente remoto.&lt;/p&gt;

&lt;p&gt;A pandemia “acabou” ou pelo menos o perigo dela diminuiu graças às vacinas, eu me mudei de cidade para voltar a trabalhar em um escritório, agora longe de casa.&lt;/p&gt;

&lt;p&gt;Todos nós tivemos que voltar aos escritórios, “esquecendo” o trabalho remoto, apenas para que essa brilhante ideia chamada “trabalho remoto” fosse introduzida, passo a passo, mas sem ser totalmente remoto.&lt;/p&gt;

&lt;p&gt;Quando me mudei, preferi conseguir um lugar perto do escritório, mas ele não tinha espaço suficiente para trabalhar remotamente. Então, continuei indo ao escritório, aproveitando para caminhar um pouco todos os dias.&lt;/p&gt;

&lt;p&gt;Há alguns meses, um membro da família teve problemas de saúde e precisaria passar por uma cirurgia, e eu voltei para casa para ajudar.&lt;/p&gt;

&lt;p&gt;Finalmente, de volta ao escritório, novamente.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Pandemia, de Novo?
&lt;/h2&gt;

&lt;p&gt;Ter que voltar ao trabalho remoto por motivos médicos… meio que parecia a pandemia de novo.&lt;/p&gt;

&lt;p&gt;Isso me levou a revisitar uma época em que o trabalho remoto era novidade e algo fresco para quase todos.&lt;/p&gt;

&lt;p&gt;Desta vez, entretanto, algumas coisas estavam diferentes, mais como deveriam e poderiam ter sido se tivéssemos “alcançado” o trabalho remoto por outros meios.&lt;/p&gt;

&lt;h3&gt;
  
  
  “Totalmente Remoto”, Mas de um Jeito Estranho
&lt;/h3&gt;

&lt;p&gt;Devido a regras internas, eu não podia realmente trabalhar totalmente remoto durante o mês inteiro. No entanto, eu podia preencher os dias em que deveria estar no escritório queimando meus dias de folga e férias.&lt;/p&gt;

&lt;p&gt;Antes de tudo, tanto meu lado de programador quanto o lado formado em administração concordam que ter que parar várias vezes em um curto período é simplesmente ruim.&lt;/p&gt;

&lt;p&gt;É impossível ter qualquer tipo de fluxo ou concluir um projeto de longo prazo de forma adequada assim. Esse foi um efeito infeliz das regras que tive que seguir, e foi simplesmente ruim.&lt;/p&gt;

&lt;p&gt;Agora podemos chegar a um ponto em que, enquanto internamente os lados administração e de programação concordam, outras pessoas podem discordar.&lt;/p&gt;

&lt;p&gt;A primeira pausa que tive que fazer, bem antes de iniciar um novo projeto… essa foi uma boa pausa.&lt;/p&gt;

&lt;p&gt;Foi uma forma de “limpar o cache” do que eu estava fazendo antes e recomeçar em preparação para o novo projeto.&lt;/p&gt;

&lt;p&gt;É um &lt;em&gt;problema&lt;/em&gt; o fato de o “ágil” nos fazer passar por uma maratona de sprint após sprint. Simplesmente errado, mesmo quando se tenta considerar do que se tratava o manifesto original ou até mesmo o que o Scrum e outras “metodologias ágeis” pregam.&lt;/p&gt;

&lt;p&gt;Você faz um sprint, revisa… e isso significa que uma pausa precisa ocorrer. Só então você pode iniciar outro sprint.&lt;/p&gt;

&lt;p&gt;Esta parte nem é sobre o remoto, mas acredito que esses intervalos podem melhorar a qualidade em qualquer lugar!&lt;/p&gt;

&lt;h3&gt;
  
  
  A Parte Ruim da Pandemia, de Novo
&lt;/h3&gt;

&lt;p&gt;Lembra quando eu disse que nem tudo era ruim?&lt;/p&gt;

&lt;p&gt;Bem, algumas coisas foram, e eu passei por isso novamente. Você deve se lembrar de estar estressado, cansado, com medo… tudo isso aconteceu porque os motivos médicos envolviam cirurgias e, depois, complicações para alguém com mais de 80 anos.&lt;/p&gt;

&lt;p&gt;Houve dias em que eu me jovaga no trabalho, enquanto em outros, o trabalho era uma tarefa árdua. Deixarei para a sua imaginação, mas considerando que todos passamos por uma pandemia… foi mais ou menos assim.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algo que Não Tivemos na Pandemia
&lt;/h3&gt;

&lt;p&gt;Especialmente quando havia lockdowns, e talvez minha família tenha exagerado um pouco nisso, e depois… Mas, neste caso, eu podia simplesmente sair, encontrar amigos, ir ao cinema, sair para correr… Eu não estava em lockdown e podia liberar o estresse de várias maneiras.&lt;/p&gt;

&lt;p&gt;Este e o ponto anterior não se aplicam apenas ao remoto, mas, já que o escritório é um “lugar de trabalho” e nossa cultura em geral, tendemos a guardar certas coisas para nós mesmos.&lt;/p&gt;

&lt;p&gt;Provavelmente é óbvio apontar, mas algumas demonstrações de emoção provavelmente gerariam muitos problemas no escritório.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Estranheza do Híbrido
&lt;/h2&gt;

&lt;p&gt;Quando surgiu essa nova modalidade “híbrida”, às vezes eu era o único da equipe no escritório enquanto todos trabalhavam remotamente.&lt;/p&gt;

&lt;p&gt;Embora sempre houvesse mais equipes no mesmo andar, houve dias em que eu olhava para a esquerda e para a direita e não via ninguém por perto.&lt;/p&gt;

&lt;p&gt;Então, finalmente, vi o oposto: eu era o único remoto enquanto os outros estavam no escritório.&lt;/p&gt;

&lt;p&gt;Quando eu ia para o escritório “apenas porque sim”, muitos dos meus dias eram resumidos na expressão “entrou quieto e saiu calado”. Por muito tempo, eu estava sempre lá, mas além de alguns acenos e “bão”/“opa”/“bom dia” e outras comunicações superficiais causadas apenas pelo cruzar no corredor ou por olhar acidentalmente nos olhos das pessoas… eu não criei conexões significativas ali.&lt;/p&gt;

&lt;p&gt;Por conta disso, eu ficaria realmente surpreso se alguém realmente sentisse minha falta lá no escritório…&lt;/p&gt;




&lt;h2&gt;
  
  
  O Trabalho Remoto é Bom
&lt;/h2&gt;

&lt;p&gt;Com a história contada, onde o trabalho remoto se destaca:&lt;/p&gt;

&lt;h3&gt;
  
  
  Presuma a Comunicação Assíncrona
&lt;/h3&gt;

&lt;p&gt;Você pode simplesmente assumir que as pessoas não estão presentes e deixar uma mensagem.&lt;/p&gt;

&lt;p&gt;Quando lerem, responderão. O mesmo para você! Se você só quer se concentrar no que está fazendo, pode simplesmente ignorar qualquer distração e focar no que está fazendo.&lt;/p&gt;

&lt;p&gt;Agora… tente fazer isso com alguém olhando por cima do seu ombro!&lt;/p&gt;

&lt;h3&gt;
  
  
  Uma Rotina Melhor
&lt;/h3&gt;

&lt;p&gt;Lembro de algo que o Uncle Bob disse: ao fazer estimativas, você deve considerar os dias em que tudo dá errado.&lt;/p&gt;

&lt;p&gt;Como eu caminhava muito, frequentemente ficava irritado com o quanto a cidade é &lt;a href="https://pt.wikipedia.org/wiki/Motornormatividade" rel="noopener noreferrer"&gt;carrocentrica&lt;/a&gt;. Isso deveria ser incluído nas estimativas, elevando elas.&lt;/p&gt;

&lt;p&gt;Mas, remotamente, você tem muito menos “partes móveis” que podem atrapalhar o seu dia e bagunçar sua rotina. Obviamente, há muitas mais coisas que podem dar errado, mas quanto mais pudermos eliminar, melhor. (Se você realmente quiser entregar mais rápido.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Novas Formas de Comunicar
&lt;/h3&gt;

&lt;p&gt;Algumas pessoas gostam de começar a falar para apenas no meio da conversa chegar a um ponto; algumas pessoas prosperam nisso… Contudo, colocar as ideias por escrito faz com que você pense um pouco mais.&lt;/p&gt;

&lt;p&gt;Esse tempo extra de reflexão pode ser tudo o que algumas pessoas precisam para resolver seus próprios problemas.&lt;/p&gt;

&lt;p&gt;Além disso, é mais fácil colar prints que podem ajudar na comunicação sobre qualquer assunto.&lt;/p&gt;

&lt;p&gt;Mesmo em uma reunião remota, fluxogramas e ferramentas de desenho estão sempre disponíveis e podem fazer com que até a pessoa mais tímida sinta vontade de participar, mesmo sem falar.&lt;/p&gt;




&lt;h2&gt;
  
  
  É Bom, Mas Pode Melhorar!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A Comunicação Assíncrona Não é Obrigatória
&lt;/h3&gt;

&lt;p&gt;Embora as pessoas não estarão por cima do seu ombro, ou você do delas… num ambiente de escritório, você pode sempre aparecer sem avisar e começar a conversar.&lt;/p&gt;

&lt;p&gt;Sim, no escritório você notaria se alguém não estivesse em sua cadeira. Online, você pode simplesmente iniciar uma chamada, deixá-la tocar algumas vezes e, se não houver resposta, enviar uma mensagem e continuar de forma assíncrona.&lt;/p&gt;

&lt;p&gt;Presumo que a maioria das ferramentas de reunião tenha, pelo menos, indicadores “verde”/“vermelho” para mostrar o status das pessoas. Se estiver verde e for algo que levará menos de 5 minutos, apenas ligue. Se estiver vermelho e não for tão urgente, então deixe uma mensagem.&lt;/p&gt;

&lt;p&gt;Por outro lado, use e abuse desses status para informar às pessoas como elas devem interagir com você.&lt;/p&gt;

&lt;p&gt;Além disso… eu não sou o digitador mais rápido; poucas pessoas são tão rápidas. Então, embora a comunicação assíncrona seja legal, se ambos estão digitando e esperando o outro digitar, significa que ambos estão presentes ao mesmo tempo… por que não fazer um upgrade da conexão para uma reunião rápida?&lt;/p&gt;

&lt;p&gt;Talvez venha com ser brasileiro, mas consigo ver como pode ser cansativo ter toda vez que começar na “formalidade” do “Bom dia, como vai, tudo bem, e isso e aquilo?”, resolver o que era necessário rapidinho e depois entrar naquelas cenas de sitcom onde dois amantes ficam esperando que o outro desligue primeiro.&lt;/p&gt;

&lt;p&gt;E quando digo rápido, eu quero dizer rápido. Sem formalidades: entre em uma chamada, comece a conversar, resolva o que precisa ser resolvido e desligue. Simples assim!&lt;/p&gt;

&lt;p&gt;Você sempre pode ter chamadas mais longas e guardar toda a conversa fiada para quando não precisar ser rápido.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conheça Suas Ferramentas
&lt;/h3&gt;

&lt;p&gt;Dependendo do que você utiliza, terá diferentes recursos para explorar. Então, não posso ajudar muito além deste conselho:&lt;/p&gt;

&lt;p&gt;Aprenda as ferramentas. Use elas.&lt;/p&gt;

&lt;p&gt;Não é mais tudo caneta e papel!&lt;/p&gt;

&lt;p&gt;Remoto ou não, sempre haverá recursos prontos para serem usados e explorados para uma melhor comunicação e trabalho em equipe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Peça Ajuda
&lt;/h3&gt;

&lt;p&gt;Quando temos problemas, mostramos isso, seja na cara ou com suspiros (ou talvez atirando coisas macias na tela ou fazendo gestos rudes para ela…).&lt;/p&gt;

&lt;p&gt;No escritório, você pode perceber isso e tentar ajudar, mas remotamente… se você não me disser que tem um problema, não posso ajudar.&lt;/p&gt;

&lt;p&gt;Às vezes, será algo pequeno ou bobo. Talvez você acabe caindo no que disse: enquanto escreve o problema, você encontra a solução.&lt;/p&gt;

&lt;p&gt;Temos um problema com o pedir ajuda, mas você sempre pode encarar isso como uma forma de facilitar o compartilhamento de conhecimento.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pair Programming Turbinada!
&lt;/h3&gt;

&lt;p&gt;Aprendi sobre pair programming através da metodologia XP (Extreme Programming), é realmente uma maneira bacana de trabalhar, então, talvez dê uma olhada nos motivos pelos quais o recomendam e experimente em algum momento.&lt;/p&gt;

&lt;p&gt;Mas eu gosto demais do meu espaço pessoal para considerar fazê-lo por longos períodos no escritório.&lt;/p&gt;

&lt;p&gt;Mas remotamente?&lt;/p&gt;

&lt;p&gt;Cada um com seu próprio IDE e esquema de atalhos estranho (funciona bem para mim, ok?) trabalhando no mesmo problema é mais do que possível com as ferramentas de colaboração que temos online.&lt;/p&gt;

&lt;p&gt;Além disso, há também o mob programming, ou mais provavelmente, às vezes mob programming para aprendizado e compartilhamento de conhecimento, e depois mob programming para resolução de problemas críticos, como quando algo extraordinário acontece e você convoca uma reunião improvisada onde qualquer um pode participar e ajudar a resolver o problema coletivamente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Você Não Pode Falar Sobre Remoto Se Você Não Fizer Isso Também no Escritório
&lt;/h2&gt;

&lt;p&gt;Defendo o que disse anteriormente: seria estranho se as pessoas sentissem minha falta no escritório. Posso conversar com a equipe, não importa onde eu esteja, e colaborar de forma ainda mais fácil e fluida com pessoas de toda a organização.&lt;/p&gt;

&lt;p&gt;Acredito que isso seja o mesmo para muitas pessoas que tiveram que voltar ao escritório.&lt;/p&gt;

&lt;p&gt;Se voltarmos ao início da pandemia, veríamos a alta administração pedindo coisas que nunca haviam sido exigidas antes das pessoas no escritório.&lt;/p&gt;

&lt;p&gt;Algumas empresas estão utilizando spyware hardcore para rastrear o mouse e o teclado das pessoas, ou até mesmo para saber se estão olhando para a tela com precisão de segundos… como se essa métrica realmente importasse para a produtividade.&lt;/p&gt;

&lt;p&gt;Como pessoas que trabalham remotamente, só podemos fazer até certo ponto. Mas se você tem poder de decisão, outras questões são para você resolver.&lt;/p&gt;

&lt;p&gt;Para resumir o que estou prestes a dizer, da forma mais informal e sincera possível:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ei, se você nem faz isso no escritório, por que quer essa merda no remoto?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Quem Não é Visto, Não é Lembrado
&lt;/h3&gt;

&lt;p&gt;Algumas empresas estão anunciando que trabalhadores remotos serão deixados para trás em promoções e afins. No entanto, muitos bons profissionais já são passados pelos “mais barulhentos” e por aqueles que “jogam o jogo”.&lt;/p&gt;

&lt;p&gt;A “política de escritório” é um problema com o qual acredito que todos já tiveram alguma dificuldade.&lt;/p&gt;

&lt;p&gt;As pessoas já mudam de emprego e departamento porque não são vistas onde trabalham, e mesmo quando são, os orçamentos para novas contratações geralmente são maiores do que o orçamento para manter os funcionários...&lt;/p&gt;

&lt;p&gt;Esse é um problema enraizado. Talvez saber sobre isso ajude de alguma forma.&lt;/p&gt;

&lt;p&gt;Ou talvez pense assim: se você tem tarefas críticas para delegar, quem vem à mente primeiro? Ou, para que tipo de tarefa você designaria a pessoa que está avaliando? Comece a questionar isso e você encontrará pessoas que só serão lembradas quando precisarem entregar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Você Não Interage com Outras Equipes Quando Está Remoto
&lt;/h3&gt;

&lt;p&gt;Além de estar fisicamente perto de algumas “outras equipes” no escritório, que tipo de “interação” existe? Quais conexões são feitas ou qual resolução colaborativa de problemas ocorre?&lt;/p&gt;

&lt;p&gt;Eu diria que é mais fácil reunir pessoas de várias equipes em um ambiente remoto do que fisicamente. Não estou dizendo que reunir um grupo de pessoas em uma sala não tem seu valor, mas não seria algo para se fazer todos os dias.&lt;/p&gt;

&lt;p&gt;Remotamente, você pode adicionar e remover pessoas conforme necessário e, se o escritório é apenas um lugar para reuniões online… a forma tradicional de organizar pessoas pode nem ser necessária (duas pizzas já não precisam ser o padrão para uma equipe). Você pode ter pessoas de várias equipes trabalhando em um único projeto ou objetivo.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Escritório, Você Não Tem Ideia do Que as Pessoas Estão Fazendo
&lt;/h3&gt;

&lt;p&gt;Pelo que ouço, acredito que quanto mais alto se está na hierarquia de gestão, maior é a tendência de se ter um viés a favor do trabalho no escritório.&lt;/p&gt;

&lt;p&gt;Uma das razões é que eles gostam de pensar que sabem o que as pessoas abaixo deles estão fazendo só porque as estão “vendo”.&lt;/p&gt;

&lt;p&gt;Se você pensa assim, não se iluda; você não faz ideia do que as pessoas estão fazendo na maior parte do tempo. Talvez você saiba o que algumas pessoas fazem em alguns momentos, uma visão geral… e é isso.&lt;/p&gt;

&lt;p&gt;A menos que você esteja microgerenciando um punhado de pessoas, talvez nem mesmo assim você saberia.&lt;/p&gt;

&lt;p&gt;Aqui vai um experimento divertido: pegue uma lista das pessoas que estão sob sua responsabilidade e escolha três nomes. O que elas fizeram durante toda a semana passada?&lt;/p&gt;

&lt;p&gt;Você sabe? Você realmente se importa? Isso importa?&lt;/p&gt;

&lt;p&gt;Se importa, então vá perguntar a elas! Talvez nem elas se lembrem de tudo o que fizeram.&lt;/p&gt;

&lt;p&gt;Todas as maneiras de parecer ocupado não são o importante. Se elas entregaram o que era esperado é. Porque, mais do que usar o tempo de forma inteligente, é mais importante parecer ocupado para não parecer que você não está fazendo nada. Se eu quisesse torturar alguém, obrigar a não fazer nada num escritório “ocupado” estaria no topo da lista.&lt;/p&gt;

&lt;p&gt;Acho que no “Trabalhe 4 Horas por Semana” (The Four Hour Workweek*)* havia algo como: “se você quer parecer ocupado, pegue algumas folhas de papel e comece a andar apressadamente de um lugar para outro. Os chefes vão pensar: agora, esse é um funcionário produtivo!”&lt;/p&gt;

&lt;p&gt;E lembre-se também, a Lei de Parkinson dita que “o trabalho se expande de modo a preencher o tempo disponível para sua conclusão”.&lt;/p&gt;

&lt;p&gt;Novamente, se você precisasse delegar tarefas, tenho quase certeza de que delegaria para as mesmas pessoas para as quais já delega muito. Assim, algumas pessoas recebem mais tarefas, enquanto outras desperdiçam tempo tentando parecer ocupadas. Tudo isso para dizer: não presuma que sabe o que pensa que sabe e use isso como métrica para outra coisa.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Lá e de volta outra vez. Tanto no remoto quanto no escritório.&lt;/p&gt;

&lt;p&gt;O trabalho remoto veio para ficar e, se nós acreditamos na “melhor ferramenta para o trabalho”, ele deve sempre ser considerado.&lt;/p&gt;

&lt;p&gt;Algumas pessoas estão escolhendo por si mesmas como elas desejam trabalhar, mesmo que isso signifique partir para longe de empresas que resistem à flexibilidade.&lt;/p&gt;

&lt;p&gt;Algumas empresas estão em conflito entre o jeito legado e as novas formas de trabalhar.&lt;/p&gt;

&lt;p&gt;E enquanto existem coisas fora do nosso controle, algumas coisas nós certamente podemos começar a fazer para melhorar hoje.&lt;/p&gt;

&lt;p&gt;Aprendemos muito sobre trabalhar no escritório ou remotamente, e espero que meus insights te incentivem a melhorar no trabalho remoto. Temos feito isso por um período tão curto que levará décadas para encontrarmos um ponto em que possamos dizer “Então… é isso para o trabalho remoto”.&lt;/p&gt;

&lt;p&gt;Então, neste novo mundo, não há caminhos pré-estabelecidos, apenas oportunidades. Enquanto alguns podem erguer barreiras, a direção que você toma é inteiramente sua.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>productivity</category>
      <category>career</category>
      <category>workplace</category>
    </item>
    <item>
      <title>Remote is good and it can get better!</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sun, 23 Feb 2025 21:33:15 +0000</pubDate>
      <link>https://forem.com/noriller/remote-is-good-and-it-can-get-better-33e3</link>
      <guid>https://forem.com/noriller/remote-is-good-and-it-can-get-better-33e3</guid>
      <description>&lt;p&gt;We had all the history of working in an office… but only a few years of working remotely and at worst… it was only slightly “worse” (productivity-wise) and that’s not considering we started it all in a fucking pandemic!&lt;/p&gt;

&lt;p&gt;Remote work is not for every type of job and not for everyone (some people did experience remote working in other settings and didn’t like it), there are valid reasons against it and moments or places where it’s not the best tool.&lt;/p&gt;

&lt;p&gt;However, there are lots of reasons that have nothing to do with whatever anyone might say about remote working being good or bad that will be outside the scope of this article because for some reason, remote working became something controversial and for reasons unrelated to working remotely.&lt;/p&gt;

&lt;p&gt;In any case, this article explores my journey through remote work—from the initial pandemic shift to the challenges and benefits I’ve experienced as a programmer with a business background and finally, how to make it even better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's remember some things
&lt;/h2&gt;

&lt;p&gt;If you're reading this anywhere near the publication date, then we probably share that we went through the pandemic. And for many, myself included, that was the first time working remotely.&lt;/p&gt;

&lt;p&gt;Some liked it and don’t want to go back to an office, others hated it and never want to try again.&lt;/p&gt;

&lt;p&gt;But here comes the reminder: It was not all bad or all good.&lt;/p&gt;

&lt;p&gt;We have to remember that it was a pandemic, even though some people tried to pretend otherwise. People got separated, stressed, lonely, worried… there were a lot of emotions going on and the lockdowns didn’t help.&lt;/p&gt;

&lt;p&gt;However, today, without a pandemic, things get a little different. You can work from home and then go outside without worries, you can work and then go see your friends and do something else later.&lt;/p&gt;

&lt;p&gt;Remote working in today’s setting is something different than it was there. And if the worst estimates were that remote work was only slight worse… with all that that was happening, then what about nowadays when it's so much better?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I’m writing this?
&lt;/h2&gt;

&lt;p&gt;A long time ago… or what seems so long ago… I would “just go to work” because that was just “normal” and then came the pandemic and I went full remote.&lt;/p&gt;

&lt;p&gt;The pandemic “ended” or at least the danger of it because of vaccines, I moved cities to return to working in an office, now far away from home. &lt;/p&gt;

&lt;p&gt;We all had to go back to the offices “forgetting” about remote work only to have this shiny new thing called “remote work” introduced, step by step, but not fully remote.&lt;/p&gt;

&lt;p&gt;When I moved, I preferred getting a place near the office, but it didn’t support enough space to work remote. So I just continued going to the office while squeezing some walking every day.&lt;/p&gt;

&lt;p&gt;A few months back, a family member had some health issues and would go under surgery and I went back home to help.&lt;/p&gt;

&lt;p&gt;Finally back in the office, again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pandemic again?
&lt;/h2&gt;

&lt;p&gt;Having to go back to remote for medical reasons… it kinda felt like the pandemic all over again.&lt;/p&gt;

&lt;p&gt;This led me to revisit a time when remote work was all new and fresh to almost everyone.&lt;/p&gt;

&lt;p&gt;This time, however, some things were different, more like they should and could have been if we had "reached" remote working by other means.&lt;/p&gt;

&lt;h3&gt;
  
  
  “Full remote”, but in a weird way.
&lt;/h3&gt;

&lt;p&gt;Because of internal rules, I couldn’t actually work fully remotely for the whole month. I could, however, fill the days I should be in the office by burning my PTO and vacation days.&lt;/p&gt;

&lt;p&gt;First and foremost, my programmer and business sides will agree that having to stop multiple times in a short period is just bad.&lt;/p&gt;

&lt;p&gt;It’s impossible to have any kind of momentum or to have any long-term project properly done like this. This was an unfortunate effect of the rules I had to follow, and it was just plain bad.&lt;/p&gt;

&lt;p&gt;Now we can enter a place where while internally business and programmer sides agree, other people might not.&lt;/p&gt;

&lt;p&gt;The first pause I had to do, just before starting a new project… now, that one was good.&lt;/p&gt;

&lt;p&gt;It was a way to “clear all the cache” from what I was doing before and reset in &lt;em&gt;lieu&lt;/em&gt; of the new project.&lt;/p&gt;

&lt;p&gt;It IS a problem that “agile” makes us go through a marathon of sprint after sprint. Just plain wrong, even when you try to consider what the original manifesto was about or even what Scrum and other “agile methodologies” preach.&lt;/p&gt;

&lt;p&gt;You sprint, you review… and that means some stop has to happen. Then and only then can you have another sprint.&lt;/p&gt;

&lt;p&gt;This part is not even about remote, but I believe those downtimes can improve quality anywhere!&lt;/p&gt;

&lt;h3&gt;
  
  
  The bad part of the pandemic, again.
&lt;/h3&gt;

&lt;p&gt;Remember when I said that not everything was bad?&lt;/p&gt;

&lt;p&gt;Well, some things were, and I went through that again. You might remember being stressed, tired, afraid… all that happened because the medical reasons were about surgeries and then complications for someone over 80.&lt;/p&gt;

&lt;p&gt;There were days I could throw myself at work while other’s, work was a chore to be done with. I would leave it to your imagination, but considering we all went through a pandemic… it was kinda like that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Something we didn’t have in the pandemic
&lt;/h3&gt;

&lt;p&gt;Especially when there were lockdowns, and maybe my family did go a little too overboard on those, and afterward… But in this case, I could just go out and see friends, go to the movies, go out for a run… I wasn’t in a lockdown and could let some steam out in more ways.&lt;/p&gt;

&lt;p&gt;This and the last point is not something that applies only to remote, but since the office is a “place for working” and culture in general, we tend to keep things to ourselves.&lt;/p&gt;

&lt;p&gt;It’s probably obvious to point out, but some displays of emotion would probably generate a lot of problems in the office.&lt;/p&gt;

&lt;h2&gt;
  
  
  The weirdness of hybrid
&lt;/h2&gt;

&lt;p&gt;When this new “hybrid” thing came, sometimes I would be the only one in the team in the office while everyone would be remote.&lt;/p&gt;

&lt;p&gt;While there were always some teams on the same floor, there were days I could look left and right and see no one near.&lt;/p&gt;

&lt;p&gt;Then, finally, I saw another side where I would be the only one remote while the others were in the office.&lt;/p&gt;

&lt;p&gt;When I was going to the office “just because”, in Portuguese, for many of my days I would say “entrou quieto e saiu calado”, which literally translates to “came in silent, left without a word”. Not sure what kind of similar idiom there is for that, but for a long time, I was always there, but aside from some nods and “sup”/“hey”/“morning” and other non-communications caused just because crossing in the corridor or accidentally looking people in the eye… I didn’t actually have much meaningful connections there.&lt;/p&gt;

&lt;p&gt;Because of that, I would be really surprised if anyone actually were to miss me there in the office…&lt;/p&gt;

&lt;h2&gt;
  
  
  Remote Work is Good
&lt;/h2&gt;

&lt;p&gt;Story out of the way, where does remote work shine:&lt;/p&gt;

&lt;h3&gt;
  
  
  Assume Async Communication
&lt;/h3&gt;

&lt;p&gt;You can just assume they aren't there and drop a message. &lt;/p&gt;

&lt;p&gt;When they read, they will respond. Same for you! When you just want to focus on what you’re doing, you can just ignore anyone and everything else and focus.&lt;/p&gt;

&lt;p&gt;Now… try doing that with someone looking over your shoulder!&lt;/p&gt;

&lt;h3&gt;
  
  
  A Better Routine
&lt;/h3&gt;

&lt;p&gt;I remember something Uncle Bob said, that when estimating, you have to account for the days when everything goes wrong.&lt;/p&gt;

&lt;p&gt;Since I walked a lot, I would often get annoyed by how &lt;a href="https://en.wikipedia.org/wiki/Motonormativity" rel="noopener noreferrer"&gt;carbrain&lt;/a&gt; the city is. This should go into the estimations, and it will bring the estimates up.&lt;/p&gt;

&lt;p&gt;But remotely, you have a lot less “moving parts” that can break your day and throw your routine. There are, obviously, a lot more things that can go wrong, but the more we can remove, the better. (If you actually want to deliver faster.)&lt;/p&gt;

&lt;h3&gt;
  
  
  New Ways to Communicate
&lt;/h3&gt;

&lt;p&gt;Some people like to talk and figure out their point somewhere in the middle; some thrive on that… however, putting it into text makes you think a little more.&lt;/p&gt;

&lt;p&gt;This extra time thinking might be all some people need to solve their own problems.&lt;/p&gt;

&lt;p&gt;Not only that, it’s easier to paste some prints that can help with whatever the communication is about.&lt;/p&gt;

&lt;p&gt;Even in a remote meeting, flowcharts, and drawing tools are always available and can make even the most awkward person feel like participating, even without talking.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s Good, but it can get Better!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Async Communication is Not Mandatory
&lt;/h3&gt;

&lt;p&gt;While people won’t be over your shoulder, or you over theirs… in an office environment, you can always drop by unannounced and start chatting.&lt;/p&gt;

&lt;p&gt;Yes, in an office you would see if they were not in their seat. Online, you can just pop a call, let it ring a couple of times, and if there’s no response, then just drop a message and continue async.&lt;/p&gt;

&lt;p&gt;I’ll assume that most meeting tools have at least “green”/“red” badges to announce people's status. If it’s green and it is something less than 5 minutes, just call. If it’s red and not that urgent, then drop a message.&lt;/p&gt;

&lt;p&gt;On the other hand, use and abuse those statuses to tell people how they should interact with you.&lt;/p&gt;

&lt;p&gt;Also… I’m not the fastest typist; few people are that fast, so, while async is cool and all, if you’re both having to type and then wait for the other type, both of you are there at the same time… why not upgrade the connection to a quick meeting?&lt;/p&gt;

&lt;p&gt;Maybe it comes with being Brazilian, but I can see it getting tiring to have some pleasantries talk for a few minutes (”Good day, how are you, good, what about this and that?”), deal with what was needed really quickly, and then turn on those sitcom sketches where two lovers keep waiting for the other part to disconnect first.&lt;/p&gt;

&lt;p&gt;And when I say quick, I mean it. No pleasantries, get on a call, start talking, solve what you need to solve, and disconnect. Simple as that!&lt;/p&gt;

&lt;p&gt;You can always have longer meetings and save all the chit-chat for when you don’t need it to be quick.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn Your Tools
&lt;/h3&gt;

&lt;p&gt;Depending on what you use you’ll have different features to play with. So, I can’t really help you there except with this advice:&lt;/p&gt;

&lt;p&gt;Learn them. Use them.&lt;/p&gt;

&lt;p&gt;It’s not all pen and paper anymore!&lt;/p&gt;

&lt;p&gt;Remote or not, there will be features ready to be used and abused for better communication and teamwork.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask For Help
&lt;/h3&gt;

&lt;p&gt;When we have problems we show it, be it in our faces or our sighs (or maybe throwing soft things at the screen or doing rude gestures toward it…).&lt;/p&gt;

&lt;p&gt;In an office, you might pick that up and try to help, but remote… if you don’t tell me you have a problem, then I can’t help you.&lt;/p&gt;

&lt;p&gt;Sometimes it will be something small or something dumb. Maybe you’ll fall into what I said above that while you write the problem you will find the solution.&lt;/p&gt;

&lt;p&gt;We have a problem with asking for help, but you can always think of that as a way to facilitate the sharing of knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pair Programming unleashed!
&lt;/h3&gt;

&lt;p&gt;I learned about pair programming from the XP (Extreme Programming) methodology, it’s actually a nice way of working, so maybe check there why they recommend it and give it a try sometime.&lt;/p&gt;

&lt;p&gt;But I like my personal space a bit too much to ever cogitate doing it for long stretches of time in the office. &lt;/p&gt;

&lt;p&gt;But remote? &lt;/p&gt;

&lt;p&gt;Each to its own IDE and weird shortcut schema (it works for me ok?) working on the same problem is more than possible with the tools for collaborative working we have online.&lt;/p&gt;

&lt;p&gt;Then you also have mob programming, or more likely, sometimes mob programming for some learning and knowledge sharing and then mob programming for critical problem solving, as in: something extraordinary happened, and you just pop an impromptu meeting, anyone can join and try to solve the problem collectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  You Don’t Get to Talk About Remote If You Don’t Also Do It in the Office
&lt;/h2&gt;

&lt;p&gt;I stand behind what I said above that it would be weird if people were to miss me there. I can talk with the team no matter where I am and even more easily and seamlessly collaborate with people from all over the organization.&lt;/p&gt;

&lt;p&gt;I believe this is the same for a lot of people who had to go back to the office.&lt;/p&gt;

&lt;p&gt;If we go back to the start of the pandemic, we would see upper management asking for things they never asked before of people in the office.&lt;/p&gt;

&lt;p&gt;There is some hardcore spyware being used by some companies to track people's mouse and keyboard, or even if they are looking at the screen with seconds precision… as if that metric actually mattered for productivity.&lt;/p&gt;

&lt;p&gt;As people who work remotely, there’s only so much we can do. But if you are someone who has decision power, then other things are for you to do.&lt;/p&gt;

&lt;p&gt;To sum up what I’m about to say, in the most informal and heart-to-heart way possible:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey, if you don’t even do this in the office, why you want this shit when remote?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  If You’re Not Seen, You’ll Not Be Remembered
&lt;/h3&gt;

&lt;p&gt;Some companies are announcing that remote workers will get passed over for promotions and such. However, many good workers are already passed by the “loudest” and those who “play the game”.&lt;/p&gt;

&lt;p&gt;“Office politics” is a problem that I believe everyone already had some issue with.&lt;/p&gt;

&lt;p&gt;People already jump jobs and departments because they are not being seen where they work, and even when they are, budgets for new hires are usually higher than the budget to keep people there...&lt;/p&gt;

&lt;p&gt;This is an ingrained problem. Maybe knowing about it might help somewhat.&lt;/p&gt;

&lt;p&gt;Or maybe thinking like this: if you have critical tasks to assign, who comes first to mind? Or, which kind of tasks you would assign to the person you’re evaluating? Start asking that around and you’ll find people that might be only remembered when it is to deliver.&lt;/p&gt;

&lt;h3&gt;
  
  
  You Can’t Network with Other Teams When Remote
&lt;/h3&gt;

&lt;p&gt;Aside from being physically near some “other teams” in the office, what “networking” is there? What connections are made or collaborative problem-solving is there?&lt;/p&gt;

&lt;p&gt;I’ll say it’s easier to gather some people from multiple teams in a remote environment than physically. Not saying gathering a bunch of people in a room doesn’t have its value, but it wouldn’t be something to do every day anyway.&lt;/p&gt;

&lt;p&gt;Remotely, you can add and remove people as needed, and if the office is only a place for online meetings anyway… the traditional way to organize people might not even be needed (two pizzas don’t need to be a standard for a team anymore). You can have people spanning multiple teams all working on one project or objective.&lt;/p&gt;

&lt;h3&gt;
  
  
  In The Office, You Have No Idea What People Are Doing
&lt;/h3&gt;

&lt;p&gt;From what I hear, I believe that the higher one is in the management chain, the more one might be biased toward office work.&lt;/p&gt;

&lt;p&gt;One of the reasons is that they like to think they know what people under them are doing just because they are “seeing” them.&lt;/p&gt;

&lt;p&gt;If you think like this, don’t kid yourself; no, you don’t. You have no idea of what people are doing most of the time. You might know what a few people are doing some of the time, maybe more like an overview… and that’s it.&lt;/p&gt;

&lt;p&gt;Unless you’re micromanaging a team of a handful of people, maybe not even then, you wouldn’t know.&lt;/p&gt;

&lt;p&gt;Here’s a fun experiment: take a list of people under you, and from there pick three names. What did they do the whole week last week?&lt;/p&gt;

&lt;p&gt;Do you know? Do you actually care? Does it matter?&lt;/p&gt;

&lt;p&gt;If it does, then go ask them! Maybe not even they will remember all that they did.&lt;/p&gt;

&lt;p&gt;All the ways to appear busy are not what is important. If they delivered what was expected is. Because more than using the time you have in a smart way, it’s more important to look busy for the sake of not looking like you’re doing nothing. If I wanted to torture someone, mandating they do nothing in a “busy” office would be top of the list.&lt;/p&gt;

&lt;p&gt;I think it was in the Four Hour Workweek something along the lines of “if you want to appear busy, pick some sheets of paper and start walking hastily from one place to another. The bosses will be like: now, that’s one productive employee!”&lt;/p&gt;

&lt;p&gt;And also remember, Parkinson’s Law dictates that "Work expands so as to fill the time available for its completion”.&lt;/p&gt;

&lt;p&gt;Again, if you needed to delegate some tasks, I’m almost sure you would delegate to the same people you already delegate a lot of them. So, some people get more tasks, while others waste more time trying to look busy. All this to say: don’t assume what you think you know and use that as a metric for something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I was there and back again. Both for the remote and in the office.&lt;/p&gt;

&lt;p&gt;Remote work is here to stay and if we believe in the “best tool for the job”, then remote working should always be considered.&lt;/p&gt;

&lt;p&gt;Some people are choosing for themselves how they wish to work, even if it means parting ways with companies that resist flexibility.&lt;/p&gt;

&lt;p&gt;Some companies are conflicted between the legacy way and the new ways of working.&lt;/p&gt;

&lt;p&gt;And while there are things outside our control, some things we can certainly start doing to improve today.&lt;/p&gt;

&lt;p&gt;We learned a lot about working in the office or remotely, and I hope my insights will push you to get better at remote working. We have been doing this for so short a period of time that it will take decades to find a point where we can say “Yep, that's about it for remote working”.&lt;/p&gt;

&lt;p&gt;So, in this new world, there are no set paths, only opportunities. While some may erect barriers, the direction you take is entirely up to you.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>watercooler</category>
      <category>workplace</category>
    </item>
    <item>
      <title>How to Brick your NAS and lose your data</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Tue, 11 Feb 2025 21:18:30 +0000</pubDate>
      <link>https://forem.com/noriller/how-to-brick-your-nas-and-lose-your-data-c3p</link>
      <guid>https://forem.com/noriller/how-to-brick-your-nas-and-lose-your-data-c3p</guid>
      <description>&lt;p&gt;This is a horror story, but don’t worry… I just lost a lot of time… this time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened?
&lt;/h2&gt;

&lt;p&gt;For context, I’ve been messing around with self-hosting. I have a Proxmox and inside I’m running TrueNAS as a VM and passing the disks.&lt;/p&gt;

&lt;p&gt;Before all that, I spent a lot of time running Badblocks and SMART tests, both of which check the health of the disks and are especially helpful in finding problems in a new disk, and then I started dumping data from my laptop and external drives.&lt;/p&gt;

&lt;p&gt;I watched a lot about TrueNAS and ways to speed up it with caches, RAID levels (for data protection even if a disk or two were to stop working), and other important things.&lt;/p&gt;

&lt;p&gt;Then, some days after dumping everything something bugged me about the disk layouts and which &lt;code&gt;/dev/sdX&lt;/code&gt; they were using… since most were just virtualized disks I was passing to speed up the NAS operations… should be easy right? Just remove and then add again…&lt;/p&gt;

&lt;p&gt;But wait! Can’t remove? Why?&lt;/p&gt;

&lt;p&gt;You see…&lt;/p&gt;

&lt;h2&gt;
  
  
  RTFM
&lt;/h2&gt;

&lt;p&gt;RTFM or Read the fucking manual. I was click-happy and just created and added disks willy-nilly. Hell! I even added “mirrored” drives because of “redundancy”.&lt;/p&gt;

&lt;p&gt;The problem?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All those were virtualized drives coming from a single SSD.&lt;/li&gt;
&lt;li&gt;Some of those drives became an integral part of the NAS Pool.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What is a Pool?
&lt;/h3&gt;

&lt;p&gt;If the part above didn’t scare you… it’s because you don’t know what a pool is.&lt;/p&gt;

&lt;p&gt;You gather multiple disks in a pool and they work as a unit. You don’t have multiple disks anymore, you have one Pool that works as such.&lt;/p&gt;

&lt;p&gt;With RAID levels you distribute data between multiple disks so that you can lose disks without losing data (there are trade-offs, but you probably want some redundancy).&lt;/p&gt;

&lt;h3&gt;
  
  
  The horror time
&lt;/h3&gt;

&lt;p&gt;Some of the “extra” disks you can add also became part of the pool.&lt;/p&gt;

&lt;p&gt;They were the dedup tables (to speed handling deduplication) and metadata (to handle small files and metadata).&lt;/p&gt;

&lt;p&gt;Each of those, when lost WILL brick your data. So if you are going to assign disks to them, you really want to assign multiple to each to have redundancy there.&lt;/p&gt;

&lt;p&gt;Meanwhile, what I did was to give it shares of one single SSD.&lt;/p&gt;

&lt;p&gt;I set up RAID 6, losing 2 disks worth of space to have enough redundancy only to add one point of failure to absolutely destroy all my data in that case of losing that single SSD. Isn’t this scary?&lt;/p&gt;

&lt;h2&gt;
  
  
  Test your backup!
&lt;/h2&gt;

&lt;p&gt;More than a couple times I heard about this, you might have also and I’ll be saying here again: TEST YOUR BACKUP!&lt;/p&gt;

&lt;p&gt;One part is: if you do lose your data, you don’t want to be stuck trying to figure out how to retrieve your data.&lt;/p&gt;

&lt;p&gt;Other part is: can you even retrieve that data?&lt;/p&gt;

&lt;p&gt;I removed some of those virtualized drives and bricked the pool. Lesson learned, still had the data, was able to dump everything again.&lt;/p&gt;

&lt;p&gt;I also know that I can turn off a couple drives and still have my data. (Also, after RTFM I’m only using actual cache drives for read/write that won’t affect the pool.)&lt;/p&gt;

&lt;h2&gt;
  
  
  How are &lt;em&gt;your&lt;/em&gt; backups?
&lt;/h2&gt;

&lt;p&gt;Are they available? Can you actually restore them in a pinch?&lt;/p&gt;

&lt;p&gt;Better give a look when you don’t need it, than having to use it and finding yourself without any.&lt;/p&gt;

</description>
      <category>data</category>
      <category>programming</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>Starting with Self-Hosting</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sun, 26 Jan 2025 20:27:34 +0000</pubDate>
      <link>https://forem.com/noriller/starting-with-self-hosting-fhm</link>
      <guid>https://forem.com/noriller/starting-with-self-hosting-fhm</guid>
      <description>&lt;p&gt;My new obsession is self-hosting. And I’m not even saying “VPS” (and yes, I know about the OCI one), I’m saying having a physical server at arms reach like the “webmasters” of old.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I’m using
&lt;/h2&gt;

&lt;p&gt;It’s not the best rig, but I have 5 HDDs of 4 TB each (with an extra slot for later), but using RAID 6, so I have around 11 TB of usable space and I can blow up 2 drives and still lose no data. I also have 128 GB RAM, half of which will go to the NAS to be used for the ZFS cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Glossary
&lt;/h2&gt;

&lt;p&gt;I learned a lot, but I also know that I had to learn a lot to understand what I’m able to say now.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPS - Virtual Private Server (basically a server someone else hosts for you)&lt;/li&gt;
&lt;li&gt;OCI - Oracle Cloud Infrastructure (think AWS. The thing I’m referring there is that you can claim some free VPS there. The amd64 are micro instances, but the arm64 is crazy good totaling with 4 cores, 24 GB RAM, and 200 GB disk to use however you want).&lt;/li&gt;
&lt;li&gt;RAID Level - It’s a way to distribute data in multiple disks with duplication in a way you can lose what's in one (or more) disks and don’t lose the data.&lt;/li&gt;
&lt;li&gt;ZFS - a file system like the more “normal” ext4 for Linux, NTFS for Windows, and FAT for external drives. ZFS has advantages over those for use cases like for a NAS.&lt;/li&gt;
&lt;li&gt;NAS - Network-Attached Storage (think Google Drive).&lt;/li&gt;
&lt;li&gt;VM - Virtual Machine (basically a machine running on another machine)&lt;/li&gt;
&lt;li&gt;KVM - “keyboard, video, and mouse” (there are devices that let you control multiple devices with one set of those, some that work over the internet so you can hard reboot and access BIOS settings without physical access to the hardware)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why self-host
&lt;/h2&gt;

&lt;p&gt;There’s a lot you can do with a private server, not to mention it will teach you a lot about computers, networks, and how to use your hardware...&lt;/p&gt;

&lt;p&gt;You can host utilities and services for you to use (and even share with family and friends) and, of course, host your own services for the world to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost
&lt;/h3&gt;

&lt;p&gt;Initial investment might be high if you just buy new hardware like I did, but if you already have some old PC/Laptop lying around, you can just start there. Not to mention one or more Raspberry Pi in the mix.&lt;/p&gt;

&lt;p&gt;Hardware aside, there will be a time investment (especially if you don’t read the articles to come =P) to make everything work initially.&lt;/p&gt;

&lt;p&gt;But when you check the costs for storing TBs of data, plus VPN, plus other services… You can also compare with VPS costs. Few cores with some RAM can easily go into “I could just buy some Pi every year and host myself”.&lt;/p&gt;

&lt;p&gt;And, obviously, you can host things you build yourself and easily handle hundreds of requests per second without breaking a sweat (most likely even thousands).&lt;/p&gt;

&lt;p&gt;Disclaimer: this might (or not) reflect what I keep repeating myself to justify buying the rig XD. Oh well…&lt;/p&gt;

&lt;h3&gt;
  
  
  Privacy
&lt;/h3&gt;

&lt;p&gt;I don’t have much expectation of it anymore, but having control of some is nice and I haven’t even scratched the surface.&lt;/p&gt;

&lt;h3&gt;
  
  
  NAS
&lt;/h3&gt;

&lt;p&gt;One of the things I’m planning with it is for a NAS, primarily for backups, but the more you learn, the more you can use it. I can run VMs with disks from the NAS and depending on how the services running it uses the disk… I say I wouldn’t know it’s running on spinning HDDs.&lt;/p&gt;

&lt;p&gt;If you’re planning on sharing only within your home, it’s pretty straightforward to mount and use as a “normal disk” on your computer.&lt;/p&gt;

&lt;p&gt;On ethernet cable, if the devices are on 10 GB ports, I understand people can edit 4K video as if the files were on their drives.&lt;/p&gt;

&lt;p&gt;My laptop on wifi could handle files fast enough for my needs that I didn’t even notice they weren’t on my machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  ARR Stack
&lt;/h3&gt;

&lt;p&gt;Some play with the ARR Stack (no glossary for this one =p).&lt;/p&gt;

&lt;p&gt;It’s interesting to play and learn how it works and I guess it has its uses to… hmm… sharing Linux distros or something like that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network-wide Ad Blocking
&lt;/h3&gt;

&lt;p&gt;One of the first things I “installed” was a Pi-Hole, a DNS resolver that you can use as a DNS sinkhole.&lt;/p&gt;

&lt;p&gt;By using lists to have network-level ad blocking, it will work on your computer, phone, and even smart fridge. It works by saying that &lt;a href="https://ads.and.more.ads.com" rel="noopener noreferrer"&gt;&lt;code&gt;https://ads.and.more.ads.com&lt;/code&gt;&lt;/a&gt; is at &lt;code&gt;0.0.0.0&lt;/code&gt;, making ads fail to work. It also makes you use less data since you don’t need to “download” all the assets even if you use another ad blocker on the browser.&lt;/p&gt;

&lt;p&gt;There are also lists to block some tracking and metrics… and from what I heard… people with children can use custom parental filters and also have the power to “turn off” the internet for kid's devices.&lt;/p&gt;

&lt;h3&gt;
  
  
  “Private” VPN
&lt;/h3&gt;

&lt;p&gt;Running a VPN (Virtual Private Network).&lt;/p&gt;

&lt;p&gt;Since I’ll be away from the server for long stretches of time, I want to be able to access it from anywhere in the world and also be able to not care about being on public networks.&lt;/p&gt;

&lt;p&gt;All traffic is encrypted and will end up going out from your server even if you’re on a sketchy wifi labeled “free wifi” (seriously, even then don’t use that).&lt;/p&gt;

&lt;p&gt;I was already “convinced” to buy some VPN, mostly because I knew I would be on public wifi from airports/hotels, and one of the biggest problems with it i that some services block you when using a VPN (since commercial VPN IPs are basically “public” and well known), but with a “private” VPN then it would be like using your home network… and if you don’t have a problem there, you probably won’t have a problem anywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  “Replace Google” and other Services
&lt;/h3&gt;

&lt;p&gt;Without paying for more space, you probably have to delete some things or maybe juggle having multiple accounts.&lt;/p&gt;

&lt;p&gt;Google Drive and Photos are first on my list. There are awesome alternatives that you can host yourself and be limited only by your own hardware.&lt;/p&gt;

&lt;p&gt;There is just so much you can do… I recommend checking &lt;a href="https://awesome-selfhosted.net/index.html" rel="noopener noreferrer"&gt;https://awesome-selfhosted.net&lt;/a&gt; to see if anything piques your interest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Offload your devices
&lt;/h3&gt;

&lt;p&gt;Instead of keeping everything on my computer or phone, I can just have VMs running things I want to be done there and then just use or download if/when needed on my device.&lt;/p&gt;

&lt;p&gt;One example: you have a potato PC lying around but have a good internet. You can connect to a VM in your server and use it instead.&lt;/p&gt;

&lt;p&gt;What I’m really thinking is automating some things I do every day/week and just getting the results later. Hell, might as well run some LLM and mix in the pipeline there.&lt;/p&gt;

&lt;p&gt;Since I’m planning on checking out some other distros, this would allow me to have a “working PC” if I need to do anything before fixing any problems I have.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-Host your projects
&lt;/h3&gt;

&lt;p&gt;I mean… I know it seems a “lost art” to some, but learning to self-host on “bare metal” is teaching me a lot and I plan to do a lot with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  I’m writing this to my “future-past-self”
&lt;/h2&gt;

&lt;p&gt;I’m sure I’ll forget most of the little fixes I did along the way and it will come to bite me later. I’ll probably rediscover some as I fix or when I set a new node and then I might stumble upon this… so, future-past-self.&lt;/p&gt;

&lt;h2&gt;
  
  
  My goals with self-hosting
&lt;/h2&gt;

&lt;p&gt;I want things for me (pi-hole, NAS, VPN) but also to self-host services to the internet.&lt;/p&gt;

&lt;p&gt;I’m on a timer because I have to do things that might screw up the server now since later I won’t have easy physical access to it. A KVM switch over IP would help with it, but unfortunately, I don’t have it… yet.&lt;/p&gt;

&lt;p&gt;But after that critical part, I still need ways to connect from wherever I will be.&lt;/p&gt;

&lt;p&gt;And, BTW, within minutes of setting a DNS record, I got a lot of (probably malicious) requests (and I didn’t even have anything there!) so security is a high priority, and then some segregation for “management” and “services” on top if I can manage.&lt;/p&gt;

&lt;p&gt;After this base is done I can then work on the “fun stuff”.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Nix at level 0 is still awesome</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sun, 29 Dec 2024 13:57:05 +0000</pubDate>
      <link>https://forem.com/noriller/nix-at-level-0-is-still-awesome-bhf</link>
      <guid>https://forem.com/noriller/nix-at-level-0-is-still-awesome-bhf</guid>
      <description>&lt;p&gt;There’s a recurring joke that once you understand monads you lose the ability to explain monads. Well… I think this weirdly applies to Nix.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Nix
&lt;/h2&gt;

&lt;p&gt;There’s nix: the language, nix: the package manager (think apt, dnf…) and related NixOS, the OS based on nix (both language and package manager).&lt;/p&gt;

&lt;p&gt;I won’t go further than that and it’s not necessary for now except to say that it is the one package manager with the most packages available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Nix are we talking about here?
&lt;/h2&gt;

&lt;p&gt;The package manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Nix?
&lt;/h2&gt;

&lt;p&gt;Recently I was playing with IP ranges, so you could use a package like &lt;code&gt;ipcalc&lt;/code&gt; but you have to install it and then it will stay there… even if you do remove it, maybe something will be left behind.&lt;/p&gt;

&lt;p&gt;And let’s not think about conflicts on dependences…&lt;/p&gt;

&lt;p&gt;Nix solves both problems, but for that, you need to install it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Nix
&lt;/h2&gt;

&lt;p&gt;While you can use the official installer: &lt;a href="https://nixos.org/download/" rel="noopener noreferrer"&gt;https://nixos.org/download/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the one I recommend and I’m using is: &lt;a href="https://github.com/DeterminateSystems/nix-installer" rel="noopener noreferrer"&gt;https://github.com/DeterminateSystems/nix-installer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which handles a lot of problems, including some quicks of some distros (including even MacOS and distros under Windows WSL).&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Nix:
&lt;/h2&gt;

&lt;p&gt;Before using it, I do need to expand on what you know about Nix here.&lt;/p&gt;

&lt;p&gt;All packages are packages that have their own list of dependencies, which also might have their own list.&lt;/p&gt;

&lt;p&gt;If you know JS and the &lt;code&gt;package.json&lt;/code&gt;, it’s like that.&lt;/p&gt;

&lt;h3&gt;
  
  
  one-of use
&lt;/h3&gt;

&lt;p&gt;Do you need something only occasionally? Maybe you want to test something or evaluate which option is better?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nix-shell -p&lt;/code&gt; plus the name of the package(s)&lt;/p&gt;

&lt;p&gt;(which, by the way, you can find here: &lt;a href="https://search.nixos.org/packages" rel="noopener noreferrer"&gt;https://search.nixos.org/packages&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That’s it. All you need to know is that it will create a shell with the packages available, and if it has conflicting dependencies? It will just use the ones it needs and ignore the rest.&lt;/p&gt;

&lt;p&gt;Once you exit the shell, it’s all gone (* terms and conditions apply).&lt;/p&gt;

&lt;h3&gt;
  
  
  actually “install”
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;nix profile install nixpkgs#&lt;/code&gt; package name and if needed, &lt;code&gt;nixpkgs#other-package&lt;/code&gt; all in one line.&lt;/p&gt;

&lt;p&gt;Now it’s installed and ready to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  removing things
&lt;/h3&gt;

&lt;p&gt;If you “installed”, then remove with &lt;code&gt;nix profile remove&lt;/code&gt; package name, and that's it.&lt;/p&gt;

&lt;p&gt;Then for those you’ve removed and those you’ve played around with &lt;code&gt;nix-shell&lt;/code&gt;…&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nix-store --gc&lt;/code&gt; and it will be actually, all gone with disk space freed.&lt;/p&gt;

&lt;p&gt;You see… Nix downloads packages and dependencies and uses them from a store. The first time you need something it will take time to download everything (and by everything, I mean everything… even “low-level” utilities you take for granted… all to keep everything pure and working). Again, like in the JS ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;I can’t see myself without Nix anymore… it’s just so handy to pull packages as you need them without worrying about having to remove them later or weird problems happening because you, at some point, had installed something that needed some version of some dependency and it never got updated.&lt;/p&gt;

&lt;p&gt;If you start checking out nix (language), nix (package manager) and NixOS, then you’ll probably be overwhelmed by the sheer amount of information, but believe me that these 2 (3 if you consider the one to clear unused dependencies) is all you need to solve most of the problems you might have and even just manage your dependencies overall.&lt;/p&gt;

&lt;p&gt;And if something didn’t work OOTB? Just install it the way you would normally.&lt;/p&gt;

&lt;p&gt;I hope I can manage to keep learning while retaining the ability to explain it… so that I’m confident in what “level 1” would be… then expect more to come.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>linux</category>
    </item>
    <item>
      <title>Chunk-Busters: Don’t cross the Streams!</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Mon, 25 Nov 2024 17:14:21 +0000</pubDate>
      <link>https://forem.com/noriller/chunk-busters-dont-cross-the-streams-35cg</link>
      <guid>https://forem.com/noriller/chunk-busters-dont-cross-the-streams-35cg</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;⚠️  If you have photosensitivity, you probably want to skip this.&lt;br&gt;
See the static image below, those lights will start blinking real fast!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjldw09c6s0b4hxwgd19o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjldw09c6s0b4hxwgd19o.png" alt="static example" width="800" height="768"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How does the internet work?
&lt;/h2&gt;

&lt;p&gt;Remember the title… we are talking about streams here.&lt;/p&gt;

&lt;p&gt;I could talk about protocols, packets, ordering, acks, and nacks… but we are talking about streams here, and as you probably guessed right (I believe in you =D) with streams… it’s either binary or strings.&lt;/p&gt;

&lt;p&gt;Yes, strings are zipped before being sent… but for what we usually care about in front and backend development… strings and binary.&lt;/p&gt;

&lt;p&gt;In the following examples, I’ll be using JS streams.&lt;/p&gt;

&lt;p&gt;While Node has its own legacy implementations, we have ways to deal with streams that are the same code, be it in the front or back.&lt;/p&gt;

&lt;p&gt;Other languages have their way of dealing with streams, but as you’ll see… the actual code part of dealing with it was not that complicated (not to say there aren’t complex things happening).&lt;/p&gt;

&lt;h2&gt;
  
  
  The example problem
&lt;/h2&gt;

&lt;p&gt;You have a frontend that has to consume data from multiple sources.&lt;/p&gt;

&lt;p&gt;While you could access each source individually via its IP/port, you put them behind an API Gateway for ease of use and control.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Repo
&lt;/h3&gt;

&lt;p&gt;Check the repo at the link, there learn how to run it yourself so you can play with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Noriller/chunk-busters" rel="noopener noreferrer"&gt;https://github.com/Noriller/chunk-busters&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Video
&lt;/h3&gt;

&lt;p&gt;Video version to follow along:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/QucaOfFI0fM" rel="noopener noreferrer"&gt;https://youtu.be/QucaOfFI0fM&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  v0 - the naive implementation
&lt;/h3&gt;

&lt;p&gt;You have the sources, you &lt;code&gt;fetch&lt;/code&gt;, wait, and render. Rinse and repeat.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;handleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;handleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch9&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;handleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be thinking that no one will actually do that…&lt;/p&gt;

&lt;p&gt;In this example, it's clear that something is wrong, but it’s not that hard to fall into this.&lt;/p&gt;

&lt;p&gt;The obvious: it’s slow. You have to fire and wait for each request and if it’s slow… you have to wait.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  v1 - the eager version
&lt;/h3&gt;

&lt;p&gt;You know you don’t want to wait for each request individually… so you fire all and then wait for them to complete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nf"&gt;fetch1&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nf"&gt;fetch2&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nf"&gt;fetch9&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nf"&gt;handleAllResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what you probably do, so it’s good right?&lt;/p&gt;

&lt;p&gt;I mean, except if you have ONE single request being slow… this would mean that even if all the others are already done… you still would have to wait that one to complete.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  v2 - the smarter, eager, version
&lt;/h3&gt;

&lt;p&gt;You know you might have some requests that are slower, so you still fire all and wait, but as they come you already do something with the result when possible, so when the last one arrives, the others are already done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nf"&gt;fetch1&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleResult&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;fetch2&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleResult&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nf"&gt;fetch9&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleResult&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This HAS to be the best solution right?&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Hmm… something weird?&lt;/p&gt;

&lt;h3&gt;
  
  
  v3 - I was lying to you… this is what v1 should look like
&lt;/h3&gt;

&lt;p&gt;Remember v1? Yeah… this is what it should look like:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Turns out there’s a limit to how many connections you can have with the exact same endpoint in http/1 and not only that… it’s browser dependant and each browser might have different limits.&lt;/p&gt;

&lt;p&gt;You might think to just use http/2 and call it a day… but even if this was a good solution, you still have to deal with multiple endpoints in the frontend.&lt;/p&gt;

&lt;p&gt;Is there even a good solution for this?&lt;/p&gt;

&lt;h3&gt;
  
  
  v4 - enter streams!
&lt;/h3&gt;

&lt;p&gt;Let’s revisit &lt;code&gt;v0&lt;/code&gt; but using streams…&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You’re smart, so you were probably expecting this since the warning spoiled it a little… but yeah… what you were seeing before was not all the data that the backend was generating.&lt;/p&gt;

&lt;p&gt;Anyway… as we fetch we render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// usually we do this:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(...).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this json call accumulate all the response&lt;/span&gt;
  &lt;span class="c1"&gt;// that later is returned for you to use&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we instead tap on the stream coming, we can do something with the chunks of data as it comes. (Yes! Like Chat GPT and the like do.)&lt;/p&gt;

&lt;p&gt;Even if v0 is the worst way of handling this problem, it’s greatly improved by using streams. You can trick the user by showing something, anything, even if the total wait time is the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  v5 - v1, again, but with streams!
&lt;/h3&gt;

&lt;p&gt;The http/1 problem is still an issue, but again, you can already see things as they come.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Yeah… I can’t stall this anymore… so…&lt;/p&gt;

&lt;h3&gt;
  
  
  v6 - &lt;strong&gt;one API to rule them all!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Or… maybe I can?&lt;/p&gt;

&lt;p&gt;You see, the frontend had to manage too much… if we can offload that to the backend, then you can have one endpoint that will handle all the sources.&lt;/p&gt;

&lt;p&gt;This solves complexity on the frontend and http/1 issues.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;handleAllResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// if you had already offloaded to the backend,&lt;/span&gt;
&lt;span class="c1"&gt;// then you might had data like&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;data0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
    &lt;span class="na"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;data9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// since the backend would be doing the fetch&lt;/span&gt;
&lt;span class="c1"&gt;// waiting ALL the data and then sending to the front&lt;/span&gt;

&lt;span class="c1"&gt;// in this case, however...&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data9&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;// The backend will stream from the sources,&lt;/span&gt;
&lt;span class="c1"&gt;// it will handle, parse, do something with each,&lt;/span&gt;
&lt;span class="c1"&gt;// then send it to the front&lt;/span&gt;
&lt;span class="c1"&gt;// the order is not guaranteed, it will be out of order&lt;/span&gt;
&lt;span class="c1"&gt;// between the sources and you need to add something&lt;/span&gt;
&lt;span class="c1"&gt;// to know which source sent each piece&lt;/span&gt;
&lt;span class="c1"&gt;// but you can receive piece by piece as it's generated&lt;/span&gt;
&lt;span class="c1"&gt;// and handle them accordingly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  v7 - and finally… one API, multiple sources, and streaming.
&lt;/h3&gt;

&lt;p&gt;We call one API, that will call all the sources, stream the data, handle it, and pass it to the front that will, in turn, render the data as it comes.&lt;/p&gt;

&lt;p&gt;The code used for this is basically the same on both front and back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in both frontend and backend we can use the same `fetch` api&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// we use the AbortController to cancel the request&lt;/span&gt;
  &lt;span class="c1"&gt;// if the user navigates away (or if connection is closed)&lt;/span&gt;
  &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// instead of the "normal" `res.json()` or `res.text()`&lt;/span&gt;
  &lt;span class="c1"&gt;// we use the body of the response&lt;/span&gt;
  &lt;span class="c1"&gt;// and get the reader from the body&lt;/span&gt;
  &lt;span class="c1"&gt;// this is a `ReadableStream`&lt;/span&gt;
  &lt;span class="c1"&gt;// (there are other types of streams and ways to consume them)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// remember we are "low level" here&lt;/span&gt;
  &lt;span class="c1"&gt;// streams can be strings or binary data&lt;/span&gt;
  &lt;span class="c1"&gt;// for this one we know it's a string&lt;/span&gt;
  &lt;span class="c1"&gt;// so we will accumulate it in a string&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// let's read until the stream is done&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// if the stream is done (or the user aborted)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aborted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// cancel the stream, exit the loop&lt;/span&gt;
      &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// if we have a value&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// decode and add to the buffer&lt;/span&gt;
      &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// here is where the magic happens!&lt;/span&gt;
      &lt;span class="c1"&gt;// we check if we can consume something from the buffer&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canConsumeSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// value above might be half or double of one "chunk"&lt;/span&gt;
        &lt;span class="c1"&gt;// so, we need to slice what we can consume&lt;/span&gt;
        &lt;span class="c1"&gt;// the if above might be changed to a "while"&lt;/span&gt;
        &lt;span class="c1"&gt;// or the chunk below might be "multiple"&lt;/span&gt;
        &lt;span class="c1"&gt;// consumable values... it all depends on how&lt;/span&gt;
        &lt;span class="c1"&gt;// you will use it.&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;consumeSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// in the frontend, make it render the chunk&lt;/span&gt;
        &lt;span class="c1"&gt;// (in react, we can simply update the state&lt;/span&gt;
        &lt;span class="c1"&gt;// and let react handle the rerendering based on that)&lt;/span&gt;
        &lt;span class="nf"&gt;renderChunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// in the backend... send the response&lt;/span&gt;
        &lt;span class="c1"&gt;// we can always parse, transform before that&lt;/span&gt;
        &lt;span class="c1"&gt;// but the back will probably either send to the&lt;/span&gt;
        &lt;span class="c1"&gt;// frontend, another service or to a DB.&lt;/span&gt;
        &lt;span class="nf"&gt;sendResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// and then we update the buffer&lt;/span&gt;
        &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes… that's it (as the most basic and easy example goes).&lt;/p&gt;

&lt;p&gt;We add the string coming to a &lt;code&gt;buffer&lt;/code&gt;, parse it, check if there’s a usable &lt;code&gt;chunk&lt;/code&gt;, use it, and forget it. This means you could receive/consume TBs of data… one chunk at a time, with little RAM.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I know what you’re thinking… and it’s stupid… it’s also madness…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MOOOOOOOM I want Websockets!&lt;/p&gt;

&lt;p&gt;No sweetheart, we have websockets at home!&lt;/p&gt;

&lt;p&gt;Websockets at home: next?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  v8 - it’s only stupid if it doesn’t work
&lt;/h3&gt;

&lt;p&gt;You’re smart, you thought that if the source is still generating data… then maybe we could update some variables…&lt;/p&gt;

&lt;p&gt;This way you can keep the one connection being used to get more data or change something from what it’s generating.&lt;/p&gt;

&lt;p&gt;Yes… I guess you could do that… and I did the example on your insistence. =D&lt;/p&gt;

&lt;p&gt;Still… it’s a stupid idea, I don’t know where/if it can be used in a real production environment. Maybe if you travel back in time to that awkward JS phase between MPA and Ajax where you had enough interactivity, but not enough connections to the same server (some browsers had a limit of only 2!) then maybe?&lt;/p&gt;

&lt;p&gt;Aside from that, no idea. If you do have… let me know.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In the example above, attention to the center board, especially the "progress border": you can see that one keeps updating. If you opened the network tab you would see that the &lt;code&gt;GET&lt;/code&gt; connection is never closed before the end. You would also see multiple other requests that change what that one, still alive, connection was doing… all of that with &lt;code&gt;vanilla http/1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  String vs JSON
&lt;/h3&gt;

&lt;p&gt;This example is the most basic I could make. I’m even using simple strings instead of JSON since it’s easier to parse.&lt;/p&gt;

&lt;p&gt;To use JSON, you have to accumulate the string (we do have to &lt;code&gt;JSON.stringify&lt;/code&gt; the backend response for a reason).&lt;/p&gt;

&lt;p&gt;Then either check where to break it and then parse that value or parse as you go.&lt;/p&gt;

&lt;p&gt;For the first one, think NDJSON: instead of a JSON array, you separate the objects with new lines, then you could “more easily” find where to break, then &lt;code&gt;JSON.parse&lt;/code&gt; each and use the object.&lt;/p&gt;

&lt;p&gt;For the latter, you parse as you go as in: you know you’re in an array, now it’s an object, ok first key, now it’s the value of the key, next key, skip that, next key… and so on and on… it’s not something trivial to make manually, but it’s like the jump from the &lt;code&gt;await then render&lt;/code&gt; to the &lt;code&gt;render as you await&lt;/code&gt; this is all about… except… on an even smaller scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Handling
&lt;/h3&gt;

&lt;p&gt;People like to host examples, this one you need to run yourself… I hope the reason for not hosting the example somewhere is clear now, but another one is that we don’t expect any error here, and if you were to add network errors above everything else… well…&lt;/p&gt;

&lt;p&gt;Errors should be handled, but they do add another layer of complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you be using it?
&lt;/h2&gt;

&lt;p&gt;Maybe… you can say it &lt;em&gt;depends&lt;/em&gt;…&lt;/p&gt;

&lt;p&gt;There are places where streaming is the answer but in most cases… &lt;code&gt;await json&lt;/code&gt; is enough (not to mention easier).&lt;/p&gt;

&lt;p&gt;But learning about streams opens up ways to solve some problems, be it in the frontend or the backend.&lt;/p&gt;

&lt;p&gt;In the frontend, you can always use this to “trick” the user. Instead of showing spinners everywhere, you can show something as it comes and then show more as it comes, even if it takes a while. As long as you don’t block the user from interacting with it… you can even make something that is “slower” than just showing spinners &lt;em&gt;feel&lt;/em&gt; like it’s way faster than anything &lt;em&gt;actually&lt;/em&gt; faster.&lt;/p&gt;

&lt;p&gt;In the backend, you can save up on RAM since you can just parse each chunk of data as it comes, be it from the front, a database, or anything else in between. Handle the data as needed, and send it without having to wait for the entire payload that would make it throw an OOM (Out of Memory) Error. GBs or even TBs of data… sure, why not?&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;Is React slow? This whole example frontend was done with React and aside from the “main” thing going on with all the blinking “lights”, there’s a lot of other stuff going on.&lt;/p&gt;

&lt;p&gt;Yes… if you go fast enough the example can’t keep up and start freezing. But since it’s easily thousands of renderings going on per minute… I do think it’s enough for most applications.&lt;/p&gt;

&lt;p&gt;And, you can always improve performance: for the “progress border”, I’ve used deferred values to make it smoother if you need to save some in renderings… I could done this and other performance enhancements for the “lights“ and the title, but it would just make the “lights” stop blinking a lot of the time (which wouldn’t make a nice demo), and also the “electric” underline in the title wouldn’t be as fun as it is.&lt;/p&gt;

&lt;p&gt;In this example, all those “improvements” wouldn't be ideal, but for normal applications... you can make it handle a lot. And if you do need something more, then in this case use another solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Add streams to your arsenal… it might not be a panacea solution, but it surely will come in handy someday.&lt;/p&gt;

&lt;p&gt;And if you’re gonna do something with it and want help, well… maybe give me a call. =P&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>node</category>
    </item>
    <item>
      <title>Fully Typed, Easy React Context API Example</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sat, 26 Oct 2024 14:41:05 +0000</pubDate>
      <link>https://forem.com/noriller/fully-typed-easy-react-context-api-example-4ne5</link>
      <guid>https://forem.com/noriller/fully-typed-easy-react-context-api-example-4ne5</guid>
      <description>&lt;p&gt;The trick to not having to babysit the context types is easy!&lt;/p&gt;

&lt;p&gt;If you use the context API, then one problem is the babysitting of its types. &lt;/p&gt;

&lt;p&gt;Another one is having to use multiple imports to use it when you need it.&lt;/p&gt;

&lt;p&gt;With this example, we solve both problems and make it quick and easy to use the React Context API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copy Paste Example
&lt;/h2&gt;

&lt;p&gt;Copy, paste, then just replace all “example” to what you need to name and you're ready to go.&lt;/p&gt;

&lt;p&gt;(Afterwards, there will be a fully commented version.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useDeferredValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useContextValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubleValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defferedStringValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeferredValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;doubleValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;defferedStringValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;doubleValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;defferedStringValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ExampleContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;useContextValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExampleContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ExampleContext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ExampleContextProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;initValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContextValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useExample must be used within a ExampleContextProvider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commented Version
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useDeferredValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * We create a custom hook that will have everything
 * that would usually be in the context main function
 *
 * this way, we can use the value it returns to infer the
 * type of the context
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useContextValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do whatever you want inside&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubleValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defferedStringValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeferredValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="c1"&gt;// remember to memoize functions&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="c1"&gt;// and also memoize the final value&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;doubleValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;defferedStringValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;doubleValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;defferedStringValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Since we can infer from the hook,
 * no need to create the context type by hand
 */&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ExampleContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;useContextValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExampleContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ExampleContext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ExampleContextProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * this is optional, but it's always a good to remember
   * that the context is still a react component
   * and can receive values other than just the children
   */&lt;/span&gt;
  &lt;span class="nx"&gt;initValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;initValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContextValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * We also export a hook that will use the context
 *
 * this way, we can use it in other components
 * by importing just this one hook
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * this will throw an error if the context
   * is not used within the provider
   *
   * this also avoid the context being "undefined"
   */&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useExample must be used within a ExampleProvider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;That's it. Context API is easier and more subtilized than it should, but it’s a powerful tool for the cases where it needs to be used.&lt;/p&gt;

&lt;p&gt;Just do remember that the React Context API is not Redux (or other state managers) and you shouldn’t shove the whole application state in it.&lt;/p&gt;

&lt;p&gt;Well, you can, but it can cause unnecessary problems.&lt;/p&gt;

&lt;p&gt;This was written with React &amp;lt; 19 in mind, with the new compiler coming, memorization and unnecessary rendering might not cause problems.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>React: State X Derived State</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Mon, 23 Sep 2024 22:56:16 +0000</pubDate>
      <link>https://forem.com/noriller/react-state-x-derived-state-2d2a</link>
      <guid>https://forem.com/noriller/react-state-x-derived-state-2d2a</guid>
      <description>&lt;p&gt;What’s a derived state? Think one state for &lt;code&gt;text&lt;/code&gt; and then another for &lt;code&gt;uppercaseText&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Derived State
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello, za warudo!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;uppercaseText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUppercaseText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setUppercaseText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Putting like that it’s crazy to think anyone would do this… right? RIGHT?&lt;/p&gt;

&lt;p&gt;Yes, an example like this will make clear that this is wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bad of Derived State
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stored separately and out-of-sync with the actual state.&lt;/li&gt;
&lt;li&gt;Triggers (depend) on unnecessary re-renders.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to refactor the derived state?
&lt;/h2&gt;

&lt;p&gt;Say it’s an expensive calculation… the solution is to use &lt;code&gt;useMemo&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello, za warudo!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uppercaseText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to quickly spot state that can be derived?
&lt;/h2&gt;

&lt;p&gt;I came up with a good way of thinking that should make it easier to &lt;em&gt;KNOW&lt;/em&gt; if a state should be “another state” or just a computed property (memorized or not depending on the case).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello, za warudo!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;uppercaseText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Forget react for a moment...&lt;/span&gt;
&lt;span class="c1"&gt;// Would you ever call a function like this?&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello, za warudo!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;uppercaseText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you think of those states as “props”, then this makes it more blatantly what it should be.&lt;/p&gt;

&lt;p&gt;Forget React entirely, think only of functions:&lt;br&gt;
&lt;em&gt;Would you call a function with a variable and then another variable you could just compute inside?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>beginners</category>
    </item>
    <item>
      <title>If you have these three things, you will be fine (as a dev)</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sat, 07 Sep 2024 22:08:51 +0000</pubDate>
      <link>https://forem.com/noriller/if-you-have-these-three-things-you-will-be-fine-as-a-dev-4pgj</link>
      <guid>https://forem.com/noriller/if-you-have-these-three-things-you-will-be-fine-as-a-dev-4pgj</guid>
      <description>&lt;p&gt;2024-09-12 is once again Programmers Day (the 256th day of the year), so following the other years ([&lt;a href="https://dev.to/noriller/if-you-have-these-three-things-then-youre-a-user-and-not-a-programmer-45nk"&gt;2023&lt;/a&gt;, &lt;a href="https://dev.to/noriller/if-you-have-these-three-things-you-can-be-a-programmer-too-v2-2e56"&gt;2022&lt;/a&gt;, &lt;a href="https://dev.to/noriller/if-you-have-this-three-things-you-can-be-a-programmer-too-28b8"&gt;2021&lt;/a&gt;]), here I am again with three things.&lt;/p&gt;

&lt;p&gt;By the 4th year of the dev life, some people might catch themselves doubting if they made the right choice or are fit to be a programmer.&lt;/p&gt;

&lt;p&gt;But some things might tell you that you will do just fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  You read the documentation (maybe even write!)
&lt;/h2&gt;

&lt;p&gt;Especially nowadays with the AI hype, you catch yourself going after the documentation for something you use over and over.&lt;/p&gt;

&lt;p&gt;While some might think they are stupid because they keep going back to read the same things, you know where the docs are and don’t mind defaulting to that over trying to stumble trying to remember how to do something.&lt;/p&gt;

&lt;p&gt;Not only that, you may write some docs yourself. It might be as little as a how/when to use a function you made or some piece of code you spent a few minutes figuring out and instead of just leaving it there like that, you translate what you’ve learned into some helpful commentary for the next time someone might need that.&lt;/p&gt;

&lt;p&gt;If you still don’t: don’t worry and start small, remember to say not what you’re doing, but &lt;em&gt;why&lt;/em&gt; you’re doing something. You know the feeling of going to read some code you’ve made and not remembering why you made it like that? When you wrote, you thought it was clear as day why you did what you did… next time this happens, explain that to your future self by leaving some comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  You double (and triple) check your work
&lt;/h2&gt;

&lt;p&gt;You already know perfect code doesn’t exist. After all, every time you open some code from a month ago you get a little embarrassed of your past self.&lt;/p&gt;

&lt;p&gt;Some people think: “My work is done when the code works”. You, on the other hand, already know that working is just the beginning. You can’t make it perfect, but at least you can make sure you won’t cringe seeing your code in the future.&lt;/p&gt;

&lt;p&gt;It’s working? Then you might commit when it’s a tricky piece of code.&lt;/p&gt;

&lt;p&gt;You might add and commit some tests, to make sure it will keep working.&lt;/p&gt;

&lt;p&gt;Then you refactor a little here and there, make it clear where you can, and comment when you can’t.&lt;/p&gt;

&lt;p&gt;You commit again, now a better piece of code, and might do even another pass.&lt;/p&gt;

&lt;p&gt;Before making a pull request, you check one more time and only then submit the code.&lt;/p&gt;

&lt;p&gt;If you don’t: remember that we read more code than write. Why make your life harder because “it’s already done” or “faster to just code” when you should know that it will come back to hunt you and then it won’t be fresh on your mind anymore and you’ll waste a lot more time to decipher what you did back then.&lt;/p&gt;

&lt;h2&gt;
  
  
  You write code for the most stupid person you know: you!
&lt;/h2&gt;

&lt;p&gt;You stopped all pretense of trying to appear smart, stopped “clever code” and “code golf” code. You know you’re stupid and you learned to make code you can keep up with even after a long day.&lt;/p&gt;

&lt;p&gt;This usually means adding comments and documentation, cleaning, refactoring over and over, and making it as clear as you possibly can… for your future self.&lt;/p&gt;

&lt;p&gt;If you ever caught yourself in this situation, you might think you’re stupid and maybe impostor syndrome might kick in. But if you’re doing code that feels so simple… you’re in the right direction. &lt;/p&gt;

&lt;p&gt;There are things complicated out there, but for most of the time, for most people… code isn’t the thing that should be complicated. &lt;em&gt;WE&lt;/em&gt; complicate things a lot, business rules might be complex, but most of the time: code should be simple and direct.&lt;/p&gt;

&lt;p&gt;If you’re not there yet, don’t worry. Remember to look at things you’ve made last month and try to figure out what the hell were you thinking back then. Do this when you’re not pressed for time and keep in mind that a time will come when you’ll need to check old code, under pressure, maybe with someone breathing down your neck, the &lt;code&gt;git blame&lt;/code&gt; will say it’s “your” code and you’ll have no idea what is happening… So, before that happens, try to think which type of code you would like to see: the “clever code” or the stupid simple one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy Programmer’s Day!
&lt;/h2&gt;

&lt;p&gt;Cover Photo by ready made: &lt;a href="https://www.pexels.com/photo/cute-purebred-dog-resting-on-bed-near-laptop-in-apartment-4297818/" rel="noopener noreferrer"&gt;https://www.pexels.com/photo/cute-purebred-dog-resting-on-bed-near-laptop-in-apartment-4297818/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>code</category>
    </item>
    <item>
      <title>To fold or to double down? That’s a tech question!</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sat, 24 Aug 2024 21:02:23 +0000</pubDate>
      <link>https://forem.com/noriller/to-fold-or-to-double-down-thats-a-tech-question-19o7</link>
      <guid>https://forem.com/noriller/to-fold-or-to-double-down-thats-a-tech-question-19o7</guid>
      <description>&lt;p&gt;We can’t stop now, as we already invested 1x in it, but let’s proceed to spend 100x more over the years! STONKS!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Javascript example
&lt;/h2&gt;

&lt;p&gt;You might have heard it before, but Javascript was written in 10 days. It had a rapid growth of adoption and they didn’t want to introduce breaking changes even after some years of using the language… so, now the language is almost 30 years old (remember it's from 1995!) and we still have to deal with those decisions.&lt;/p&gt;

&lt;p&gt;They knew way back in the early years of JS that there were a lot of changes that would benefit the language, but didn’t want to break the “countless” websites from back then (there were a couple of million total websites worldwide back then, not necessarily using JS at all!).&lt;/p&gt;

&lt;p&gt;Hindsight is 20/20, and they might have broken JS in a way that wouldn’t be what it is today.&lt;/p&gt;

&lt;p&gt;Then again… Angular did just that when breaking and launching “Angular 2”. Just because many people were using Angular, they knew it was not sustainable to keep going with AngularJS, so they started to phase out from it to Angular2 and Angular got better because of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would you invest in this today?
&lt;/h2&gt;

&lt;p&gt;When investing, we feel like “losing” or “quitting” by jumping ship, but the people who can go farther are those who know when to quit a bad decision (not necessarily bad, but things change over time).&lt;/p&gt;

&lt;p&gt;Back to the Angular/JS/2 example. Some companies are still using AngularJS, even though it reached end of life and some more some years ago. Now, they have to support and patch it on its own as they increase their codebase and make the decision to stick to it more and more painful and harder to change because of all the investments in it.&lt;/p&gt;

&lt;p&gt;Of course, on the other side of this are people jumping from fad to fad and creating monsters that show whatever tech was more popular at each time, some that just stopped being used once people tried to start using it or that, some reason or another, just died and stopped being maintained.&lt;/p&gt;

&lt;h2&gt;
  
  
  The name of this is the sunk cost fallacy
&lt;/h2&gt;

&lt;p&gt;You think you’ve invested “too much” already, so you can’t back down. You also think you don’t need the new shiny things if the boring old LAMP stack is enough and working.&lt;/p&gt;

&lt;p&gt;But one thing is “it works” and another is: “in the long term, this will cost more than changing”.&lt;/p&gt;

&lt;p&gt;In the financial sense, some new thing might let you go faster and farther, or at least, will let you be free to pursue other opportunities you might have missed otherwise.&lt;/p&gt;

&lt;h3&gt;
  
  
  The COBOL example
&lt;/h3&gt;

&lt;p&gt;Banks run on COBOL, it’s been decades in “decline” but at each turn, they say it’s worth more to keep their COBOL legacy and hire COBOL developers at higher and higher prices than it is to work on migrating from it. TBF, hopefully, they are strangling their legacy. But if they are still actively developing in COBOL, no LLM will help them when it starts costing prohibitively more to hire COBOL devs in a market with fewer and fewer available people.&lt;/p&gt;

&lt;p&gt;Meanwhile, new competitors without that legacy can enter the market with other stacks that let them move faster, cheaper, and with a bigger hiring pool available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you? When?
&lt;/h2&gt;

&lt;p&gt;The analogy is that of steering a huge ship. When you turn the ship’s wheel, the change is not immediate. You need to prepare beforehand and there are strategies to make this easier. Then it will still take some time until it’s clear that yes, the ship is turning.&lt;/p&gt;

&lt;h2&gt;
  
  
  ROI
&lt;/h2&gt;

&lt;p&gt;But coming back to the financial analogies: ROI (return on investment).&lt;/p&gt;

&lt;p&gt;You use ROI to calculate which investment is better, usually comparing the one you’re assessing against a “base” investment.&lt;/p&gt;

&lt;p&gt;This would mean calculating how much time is “wasted” by keeping the status quo against the estimated gains from the proposed change. Of course, you would need to add the time spent on the change and with that, you would get some number of how much time it would start netting you “profits” on that investment.&lt;/p&gt;

&lt;p&gt;If the calculated gains are so small that it would take a long time to take effect, then it might not be worth it.&lt;/p&gt;

&lt;p&gt;This one was about time spent on a task, but you can also use other metrics like accessibility, security, and reliability… if you can measure something, then it can be used to justify a change.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Your code is NOT special.</title>
      <dc:creator>Bruno Noriller</dc:creator>
      <pubDate>Sat, 27 Jul 2024 18:32:57 +0000</pubDate>
      <link>https://forem.com/noriller/your-code-is-not-special-2oha</link>
      <guid>https://forem.com/noriller/your-code-is-not-special-2oha</guid>
      <description>&lt;p&gt;Why aren’t more things open-source? And to remember: open source doesn’t mean &lt;em&gt;free&lt;/em&gt; and it doesn’t even need to mean &lt;em&gt;open contributions&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switzerland mandates open source for the public sector
&lt;/h2&gt;

&lt;p&gt;I saw some news about the mandate issued by Switzerland.&lt;/p&gt;

&lt;p&gt;As with anything on the internet, mixed reactions.&lt;/p&gt;

&lt;p&gt;For most people outside Switzerland and even there, this doesn’t matter much (sorry Switzerland). &lt;/p&gt;

&lt;p&gt;Between that and the launch of Llama 3.1 with the weights and a comprehensive paper on how it was made… it resurfaced a thought that at one point most of us might have had:&lt;/p&gt;

&lt;h2&gt;
  
  
  Why aren’t more things open-source?
&lt;/h2&gt;

&lt;p&gt;It might be just &lt;em&gt;source-available&lt;/em&gt;, closed to contributions and paid. But why not open source? Is your way of doing CRUDs so innovative or special? How about the way you center divs? Is it that good?&lt;/p&gt;

&lt;p&gt;Because I’m pretty sure most companies and us “out there” are all using the same libraries for that… which are probably open-source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source already does the “heavy lifting”
&lt;/h2&gt;

&lt;p&gt;The most marvelous pieces of engineering are already made in an open-source manner, some of which make money out of it and some are “unicorns” (companies evaluated at 1B without even being publicly traded on the stock market).&lt;/p&gt;

&lt;h2&gt;
  
  
  The case for closed-source:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The bad ones
&lt;/h3&gt;

&lt;p&gt;No need to hide credentials from the code if it’s internal.&lt;/p&gt;

&lt;p&gt;No need to mind using real people's data in tests and the like.&lt;/p&gt;

&lt;p&gt;Easier to obscure shady practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  The good ones
&lt;/h3&gt;

&lt;p&gt;Not show the “next big thing” and make a surprise. (In this one I would argue that after that, why not open the source?)&lt;/p&gt;

&lt;p&gt;Some companies might have something that is their “secret sauce” (intellectual property) that they don’t want others to use or know about. (There are software patents that might cover also this.)&lt;/p&gt;

&lt;h3&gt;
  
  
  The valid ones
&lt;/h3&gt;

&lt;p&gt;Security concerns about vulnerabilities in the open without enough resources to dedicate to a security team.&lt;/p&gt;

&lt;p&gt;Security is hard and closed means a smaller vector of attack, on one hand, you could have people contributing to finding those vectors, but before that, you would probably have someone exploiting then.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case for open-source
&lt;/h2&gt;

&lt;p&gt;My biggest point is that if we learned to learn from each other, maybe a lot of things could be easier to achieve.&lt;/p&gt;

&lt;p&gt;We already joke about “stealing” (copy-pasting) from other sources available, this would just streamline the job. Have a problem? Just show the code, no NDA or its “private code” concerns… it would be all in the open.&lt;/p&gt;

&lt;p&gt;The “shoulders of giants” is where all the foundation is built and why we got so far. If more things were closed source back then, then the internet might have been a different place (or maybe it just wouldn’t be, maybe just a niche thing if that).&lt;/p&gt;

&lt;p&gt;I know it’s a naive view. And that there are more valid reasons not to open source that I just can’t think of.&lt;/p&gt;

&lt;p&gt;A lot of companies probably think they would “lose revenue” because people would just host the solution… coming from a world where people don’t even have “personal pages” anymore and just use whatever centralized solution is more popular.&lt;/p&gt;

&lt;p&gt;Or that some company will just steal their code. Not to mention that companies will already steal if they want and just pay a settlement if needed (or just buy it).&lt;/p&gt;

&lt;h2&gt;
  
  
  Code is just a tool
&lt;/h2&gt;

&lt;p&gt;Think of most social media nowadays: they do the same thing, and they work in the same way. &lt;/p&gt;

&lt;p&gt;The code is a detail, and if a “new thing” appears they will just copy it. The code doesn’t matter and the idea is usually simple enough. All that changes is all the shady &lt;em&gt;“how to keep you here for the most time possible”&lt;/em&gt; (that they probably don’t want out there).&lt;/p&gt;

&lt;p&gt;Even in the “real” tangible world, few things can be truly kept a secret, most are reverse-engineered anyway and copies are out there. But between patents, lawsuits, and “branding” the copies don’t matter and people will still go for the original ones.&lt;/p&gt;

&lt;p&gt;Meanwhile… many brands today started out just copying something (some still do), and started adding their own spin to things and improving further than the “originals”. Then they are the copied ones and the cycle repeats.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
