5 Bibliotecas Essenciais para Desenvolver React Apps
O conjunto de ferramentas, boilerplates e bibliotecas disponĆveis formam um ecossistema incrĆvel em torno do React.
No meio de tudo, existem ferramentas que sĆ£o comuns ā e essenciais āĀ a diversas aplicaƧƵes, independente de suas arquiteturas. Cito cinco delas.
Muitas vezes, no React, um estado representarĆ” um comportamento visual do componente (āselecionadoā, āpressionadoā, āfocadoā), normalmente associado a uma classe CSS.
Um botĆ£o e seus estados disabled e hovered, por exemplo, ficariam assim:
A development branch of VS Code colorization, which is delivered as an extension. Finally got JSX to work properly, but syntax highlighting was still missing something.
So, no success.
Improving your VS Code workflow
After much trial and error, I came up with a better JS workflow in VS Code.
Fortunately, VS Code is an open source project and can be improved by developers like us! Letās not leave it like this. Give useful feedback and help!
Math.random() is a JavaScript function that outputs a random number in the range [0, 1) (from 0 up to 1, but doesnāt include 1). Itās the main source of randomness in JavaScript.
Although the output looks random, itās actually not.
Behind the Scenes
Math.random() uses a pseudo-random number generator (PRNG). Those algorithms work completely determined by a initial value called āseedā.
Given a seed, the sequence of random numbers is deterministic.
Every PRNG requires a seed, which generally is the current system time in milliseconds. Yeah, simple as that.
Speaking of JavaScript language, the PRNG algorithm to deal with the seed is left up to implementors1. The algorithm powering V8ās Math.random() was very poor quality until last year (2015), and implementations between engines were pretty inconsistent.
But the scenario has changed. Currently, JavaScript Engines such as SpiderMonkey, V8, Webkit and Chakra all implements Xorshift128+ algorithm2, faster than the previous one.
Secure Randomness
Although randomness was improved in most JavaScript engines, it isnāt trustworthy as seen that standard PRNGs are highly predictable after a certain period. Thatās where Web Crypto API shines!
Web Cryptography API introduces window.crypto.getRandomValues, a cryptographically secure pseudo-random number generator (CSPNG), whose output is impossible or highly improbable to distinguish from a truly random one.
Example
// Array containing two 32-bit integers
+const arr = new Int32Array(2);
+
+// Override array integers with random values
+const random = crypto.getRandomValues(arr);
+
+for (let i = 0; i < random.length; i++) {
+console.log(random[i]);
+}
+
Of course it comes at a performance cost, so make sure you really need secure random numbers in your program.
Conclusion
If you need apparent randomnessāless and speed, youād probably better off using Math.random(). If you need high-quality randomness, such as in cryptography applications, hashing or statistics, go for a CSPNG such as window.crypto.getRandomValues instead.
Muito embora todos os seres humanos do Planeta Terra tenham odiado sua sintaxe, as variĆ”veis finalmente chegaram ao CSSĀ āĀ e elas sĆ£o mais poderosas do que vocĆŖ imagina!
MotivaĆ§Ć£o
O desenvolvimento de grandes aplicaƧƵes web implica inevitavelmente em grandes folhas de estilo, que devem ser organizadas de forma que facilite a manutenĆ§Ć£o. Muitos valores definidos para propriedades sĆ£o repetidos, quando poderiam ser reutilizados e padronizados, de forma compartilhada, pela folha de estilo.
Cascata, especificidade, heranƧaā¦ Esses conceitos sĆ£o muito importantes para entender o poder das variĆ”veis do CSS ā e do CSS no geral, eu diria.
Aqui, uma das informaƧƵes mais importantes deste artigo: As Custom Properties seguem regras de cascata tal como qualquer outra propriedade do CSS.
Exceto elementos div e seus filhos, que seriam verdes.
Exceto o elemento com id wow e seus filhos, que seriam ciano.
As Ćŗltimas versƵes do Firefox e Chrome jĆ” implementaram as variĆ”veis nativas do CSS. Se estiver utilizando algum desses navegadores, o exemplo abaixo ilustrarĆ” o funcionamento do CSS acima.
As Custom Properties abriram novas possibilidades para o uso de variĆ”veis em folhas de estilo. Depois de diversas especificaƧƵes e sintaxes (nem sempre foi --, acredite!), elas estĆ£o finalmente em fase de implementaĆ§Ć£o nos navegadores.
Estuda Motion Design a fim de desenvolver nĆ£o sĆ³ sites, mas experiĆŖncias fantĆ”sticas? Estuda UX Design e prĆ”ticas de Acessibilidade a fim de desenvolver produtos que engajam o mĆ”ximo de pessoas possĆvel? Estuda padrƵes de arquitetura de software a fim de desenvolver aplicaƧƵes web complexas e escalĆ”veis no client-side?
No fim, suas preferĆŖncias moldarĆ£o vocĆŖ como profissional. Elas farĆ£o com que vocĆŖ seja incluĆdo(a) ou excluĆdo(a) de vĆ”rias oportunidades, o que, por consequĆŖncia, moldarĆ” sua carreira.
Estude o que gosta, reconheƧa suas preferĆŖncias, confie nas suas habilidades, e, entĆ£o, procure vagas sem entrar em desespero.
Perfis de Desenvolvedores Front-end
No fĆ³rum do Front-end Brasil, foi proposta a divisĆ£o de separar profissionais de front-end que desenvolvem a camada de apresentaĆ§Ć£o dos que arquitetam aplicaƧƵes que interagem com back-end. Concordo com a divisĆ£o. Tenho uma visĆ£o bem definida, com base nas exigĆŖncias atuais do mercado internacional.
Dificilmente um rĆ³tulo resumirĆ” todo o seu conhecimento.
Eu nĆ£o me apego a isso, por exemplo. Mesmo exercendo a funĆ§Ć£o de Front-end Engineer atualmente, continuo me denominando āFront-end Developerā.
A Vaga Ideal Para Suas Habilidades
Ć utĆ³pico esperar que todos desenvolvedores front-end sejam bons UX Designers, Motion Designers, JavaScript Developersā¦ Isso nĆ£o existe. As empresas procuram diferentes perfis de desenvolvedores front-end. E elas nem sempre sabem disso.
Independente de como vocĆŖ se posiciona e rotula, dos projetos que trabalha e do caminho que quer seguir, o front-end nĆ£o deixarĆ” de orbitar ao redor da trinca HTML, CSS e JavaScript.
Enquanto vocĆŖ possuir interesse nessas trĆŖs linguagens, os seus outros interesses apenas moldarĆ£o o seu caminho profissional.
Favicon is a simplified visual element associated with a particular website, page or event, which you once found only in your browserās address bar or bookmarks. Nowadays, the scenario is different: they are everywhere.
Introduction
Favicons provide a important visual indicator to people, and help them to easily associate your content (which can be a website, a particular page or even events like a new message) when browsing.
Formerly, they, also called shortcut icons or bookmark icons, were just tiny pieces of art designed to help users to browse through their tabs or bookmarks. Today, shortcut icons can also provide an app-like link on operational systems (Windows 8, Android, OS X and so on), and should therefore be considered for achieving a pleasant cross-platform experience.
This is a guide for using favicons today, the right way. At the end of this article, Iām sure youāll be excited about SVG favicons.
Usage
Favicons in different dimensions are needed, so devices and browsers can pick the picture that fits best based on sizes attribute (little exception for Mozilla Firefox, which always gets the last favicon declared and scale it if necessary).
The images are not requested when not used. As said, browsers will get only what fits them best, therefore itās important to provide the favicon in the required dimensions to avoid ugly scaled images.
General
<!-- I'm lazy -->
+<link rel="icon" href="favicon.png" />
+
+<!-- Browser tabs -->
+<link rel="icon" href="favicon-16x16.png" sizes="16x16" />
+
+<!-- Safari on OS X, IE10 Metro -->
+<link rel="icon" href="favicon-32x32.png" sizes="32x32" />
+
+<!-- Google TV -->
+<link rel="icon" href="favicon-96x96.png" sizes="96x96" />
+
+<!-- Chrome on Android -->
+<link rel="icon" href="favicon-192x192.png" sizes="192x192" />
+
No need for type="image/png" when using HTML5.
Youāll need to provide a manifest in order to Chrome on Androidās icon to work properly. See manifest.json example.
<link rel="manifest" href="manifest.json" />
+
Lacking of PNG support on IE: a workaround
Internet Explorer until version 11 and Safari donāt support PNG favicons. However, you can provide a fallback for IE up to 9:
Notice the shortcut, which is a non-standard. Also, providing this fallback within a conditional comment is necessary; otherwise Chrome will use the ICO favicon, even if it supports PNG ones.
I donāt recommend it, though, because IE 10 doesnāt support conditional comments (so it wonāt get any favicon, as seen that it doesnāt support PNG too), and also because it encourages the use of the non-standard and confusing shortcut.
Luckily, you can workaround everything just placing a favicon.ico in the root directory (the browser will look for it automagically). Then link only the PNG favicon and donāt worry.
Web Clip bookmarks
iOS users can add websites to their home screen āĀ shortcuts called āWeb Clip bookmarksā. The default icon is a thumbnail screenshot of the page, but developers can specify one instead.
You will need to provide a lot of dimensions in order to support both new devices and older (iOS6 and prior), however.
Thereās a no-HTML way and a HTML way to provide those icons. Itās up to you.
No-HTML: Touch Icon file
Add a apple-touch-icon-*.png file, where * is the size to the root directory, instead. iOS Safari will look for the appropriate icon size, and if it doesnāt find any that fits best, itāll use apple-touch-icon.png.
Link tags
You can reuse the image of another favicon specifying a href (not possible while using the solution above).
Using apple-touch-icon-precomposed instead of apple-touch-icon, which prevents iOS icons defaults like rounded corners and reflective shine, isnāt necessary, as seen that there isnāt shiny effects on iOS 7 and up anymore.
Windows Tiles
Tiles are icons that appear on the Start screen, linked as apps. By default, the image on the tile is the websiteās favicon or a default IE11 logo.
To cover a wide range of devices, use an image 1.8 times the standard tile size so the image can be scaled up or down as needed.
Thereās a no-HTML way and a HTML way to provide those icons. Itās up to you, again.
No-HTML: Browser config file
Provide a browserconfig.xml file and save it at the root of your server. Internet Explorer 11 will automatically read the file when the user pins the website. See browserconfig.xml example.
Metadata tags
msapplication-TileColor is the background color of the tile, and msapplication-TileImage is the icon, which can be tiny (70 Ć 70px), square (150 Ć 150px), wide (310 Ć 150px) or large (310 Ć 310px).
Iām sure you are now excited about SVG support for favicons. Providing a lot of different images is quite boring.
I encourage you to support favicons everywhere (or at least retina-ready ones), but unfortunately thereās no human-friendly way to do it nowadays. Use favicons package on npm or, if you are not comfortable with the command line, refer to RealFaviconGenerator.
Ask me for a screenshot of my desktop and all you get is a wallpaper ā if Iām using any. Everything else is hidden, unless actually requested by me.
Thatās the way I work on macOS. The minimal way.
In my workspace, there are no desktop items, app icons, time clock, battery percentage, transition delays, distracting animations, dashboards or context menus.
Too much information makes it easy for me to get stimulated and then distracted. So I like it minimal.
Recipe for the minimal š
Get rid of everything you can. Hide. Disable. Assume everything is useless, not useful. (I actually use this approach for life.)
Youāll get frustrated sometimes, because there are simple things you want so bad to get rid of but then found out itās impossible unless you hack things. SRLSY GOTTA LOVE APPLE ššš
Well, letās begin! Follow the steps below and type the commands in a terminal. If youāre not familiar with a terminal, Iām pretty sure itās possible to find those settings in āSystem Preferencesā as well.
(ā¦But I highly recommend you to open a terminal and start typing around because SRSLY USING A TERMINAL IS LIKE KNOWLEDGE AND POWER 4 UR ENTIRE LIFE!!!!!!!!)
Hide your desktop
Itās easier to live without than to live with it. Disable it and it wonāt be something you have to clean up anymore!
Other cool things you can do too to keep your dock clean are:
# Minimize windows into their application's icon
+defaults write com.apple.dock minimize-to-application -bool true
+
+# Wipe all (default) app icons from the Dock
+defaults write com.apple.dock persistent-apps -array
+
Because I initialise apps from Spotlight, I really donāt mind not having any app in my dock. Sometimes I ask myself why do I have a dock at all. š¤
Usually, such thing would mean regular summer days. However, it wasnāt summer or even a regular day ā this was something else.
February 25th was winter. In that cold afternoon, I ended up into a place Iāll never forget: photographs from my phoneās gallery.
My steps were slow.
Red bricks erected the walls of houses built on top of an equally red-bricked avenue.
The windows of the houses were made of a wood strategically white-colored to match the brickās white grouts. With such detail, it was pretty easy to forgive the toughness those bricks carried.
Houses ended themselves in grey roofing shingles. The roofs were all hipped. Houses with hip roofs, gotta love them!, I thought to myself. (Imagine the āVā letter upside down on top of a square ā thatās a house with a hip roof.)
Showing a winter that was already leaving, dark trees with dry twigs were in contrast against a white sky ā the whitest Iād ever seen in my life. Damn! The whole picture looked like a painting, while the white sky worked as the canvas board on which all that was drawn.
I remember walking and trying to get everything I could, until a freezing wind blew abruptly into my face. It was February, though. From where I come, February meant summer, not freezing winds. Why was February that cold?
In an attempt to clear things up, I told myself what I believed that was true: Youāre just looking at photographs from your phoneās gallery. Thereās no need to get this excited! Ok. So I was home and looking at the āWallpapersā album I had on my phone.
A moment later, I found myself facing a large and wonderful canal, in which someone was solitary paddling a boat to somewhere. What a view.
Then, self-awareness hit me again: Wait. Isnāt my smartphone in my pocket? How could I be possibly looking at photographs on it?
I immediately started touching my entire body in a desperate hunt for my phone. And there it was. In my fucking coat. It wasnāt really possible for me to see photographs on my phone ā that shit was in my pocket all the time.
Besides, why would I be wearing a coat on summer? And, if I was already wearing a coat, how could I be still cold? How inappropriate were my clothes for that weather? Only a person who sensed that winter solely with the eyes would underestimate its coldness like that!
The boat was really leaving through the canal. The view wasnāt photographs. What was all that, then?
I got my phone from my pocket, turned off airplane mode, and opened the Maps app. Come on, where am I?
āNoorder Amstelkanaalā, I read. Wow.
All of a sudden, February 25th was a cold winter in Amsterdam. My very first one.
As a High School student, I remember always finding Chemistry something between the boring and intriguing. Still, it isnāt hard to find myself wondering about the science concepts Iāve learned at that time.
Lately, Iāve been particularly thinking about catalysis.
In Chemistry, catalysis is the acceleration of a reaction due to the participation of a substanceĀ ā the ācatalystā.
The way a catalyst induces a reaction to happen faster is intriguing. Curiously, it neither gives the reaction more energy nor change its environmental conditions. Catalysts have an even better strategy: they lower the amount of energy required for the reaction to take place.
In a catalysed reaction, then, the same product is obtained for less energy. Bringing this concept to our lives is quite thought-provoking.
Sometimes it isnāt possible for us to achieve something because it demands more time or energy than what we currently have. To deal with this, we then try looking for them in our livesĀ ā which mostly means depriving yourself of things.
However, matter of fact is that optimising isnāt always about getting rid of things in your life. If we think of catalysis, we can manage it differently.
What if the problem werenāt the lack of energy or time, but that weāre in need of too much of them in order to get things done? Having a catalyst would totally figure it out. Without something that pushes us forward, weāll always require more energy for the product we want to get.
At this point, you may think your catalyst is your motivation. Motivation is out of our control though ā which makes it a goal, not a source. Itās also too ephemeral, and a catalyst mustnāt ever be consumed by an unique reaction, just like in Chemistry. We canāt count on being motivated!
So it goes more like what habitual and practical things in life would give you productivity for less. Is it everyday meditation? A partner by your side? Self-confidence? Inspiring weekends without thinking of work at all? Eating healthy? Going out for a walk every day?
You have to mind what pushes your forward. Catalysts themselves cannot make a reaction happen that wouldnāt happen on its own, but they sure make it occur under less extreme conditions. Itās an improvement when youāre already motivated.
Choose life. Choose a job. Choose a career. Choose relocation. Choose giving life a fresh1 beginning. Choose an one-way flight ticket. Choose fitting your entire life in a 23 kg suitcase. Choose getting rid of all your crap. Choose a higher Human Development Index. Choose being thousands of kilometers far away. Choose devastating your loved ones. Choose different bureaucracies you still donāt understand. Choose calling another place home. Choose not fitting in (you never did anyway!). Choose saying goodbye to places, food and friends, then choose new places, food, and friends. Choose memories. Choose developing new tastes. Choose being forced to develop social skills. Choose ignorance. Choose mundane and boring activities as exciting adventures. Choose not speaking your mother language. Choose limited self-expression. Choose missing the food from your country, and especially your mumās. Choose letting part of your heart be elsewhere. Choose adapting 24/7. Choose wondering what the fuck you are doing. And choose getting the answer as soon as you go outside. Choose not understanding jokes from natives. Choose recognising you can do anything, anywhere. Choose not knowing if you should. Choose the bittersweet feeling of moving abroad. Choose to be afraid. Choose your future. Choose life.
But why wouldnāt I want to do a thing like that?
I chose to choose life. And the reasons? There are no reasons. Who needs reasons when youāve got Berlin?2
1
See HelloFresh, which helped me relocating to Berlin.
2
The entire essay is inspired by Mark Rentonās āChoose Lifeā speech from Trainspotting, a movie that makes me think a lot about life choices.
O Centro de ConvenƧƵes, ao menos, foi fĆ”cil de achar, e o check-in ocorreu como esperado: pontual. As meninas que forneceram minha credencial estavam de Ć³timo humor ā e olha que era um dos primeiros horĆ”rios da manhĆ£ de sexta! Ano passado, o meu check-in foi feito pelo Jaydson, o que fez eu me perguntar onde estaria ele, se nĆ£o credenciando os participantes do evento.
ā¦E, na verdade, ele tinha se tornado um Power Ranger junto com o Felipe. E Power Rangers nĆ£o fazem check-in. Descobri isso da pior maneira.
Uma abertura idiota
Dois desenvolvedores, os organizadores desse evento que trouxe mais de mil pessoas para o mesmo lugar, brincando de ālutinhaā na frente de todo mundo, vestidos de Power Rangers sĆ³ porque o JavaScript fez 20 anos. Essa foi a abertura da BrazilJS, e eu nĆ£o mudaria nada.
Com uma camiseta do Brasil, Christian chegou com um dos assuntos mais importantes na atualidade, e que estĆ” dando muito o que falar: pushing the web forward. Palavras de protagonismo, reiteraĆ§Ć£o do nosso papel, motivaĆ§Ć£o para acreditar na web e no nosso trabalho, e, o mais importante: como isso deve ser feito. Falou, claro, sobre o ECMAScript 6, sobre o Babel, e fez uma anĆ”lise de como resolvemos os problemas atualmente.
We all know the DOM is slow, terrible and to blame for all our problems. Did we allot it to say that way and still be a problem as we abstracted its issues away?
Os argumentos foram reĆŗnidos, as situaƧƵes em que podemos nos tornar web makers foram apresentadas, e tudo em prol de provar o nosso protagonismo.
You are a creator of the next web!
Sem dĆŗvidas, uma das melhores palestras que jĆ” assisti na minha vida. Ć difĆcil relatar uma interpretaĆ§Ć£o detalhada sobre a mensagem do Christian, mas, aos que jĆ” se sentiram no dever de fazer a web um lugar melhor alguma vez e nunca deixaram de acreditar nessa mĆdia, acho que essas minhas palavras foram mais que o suficiente para compreender o pensamento dele. Simples e sensacional.
Douglas falou sobre compiladores, e engajou os desenvolvedores a entender how things work under the hood, explorando conceitos como AST (Abstract Syntax Tree), um assunto que estĆ” finalmente chamando a atenĆ§Ć£o em JavaScript, tanto que nĆ£o foi a primeira vez que foi abordado na BrazilJS.
Acredito que o questionamento que o palestrante buscou provocar no pĆŗblico nĆ£o teve ĆŖxito. Os 30 minutos, infelizmente, nĆ£o foram bem aproveitados e nĆ£o atenderam Ć s perguntas que o Douglas tentou provocar e responder. Ficou a sensaĆ§Ć£o de uma mensagem subentendida, no entanto:
Itās really important for us to take a look at the things we donāt necessarily like.
JavaScript at Spotify
Felipe Ribeiro juntou os desafios encontrados durante a transiĆ§Ć£o do Spotify (nativo com C++ para hĆbrido), e o resultado foi uma palestra bastante completa sobre arquitetura e engenharia de software. Diversificou bastante a programaĆ§Ć£o da conferĆŖncia, e mostrou que devemos analisar a necessidade de re-escrita de cĆ³digo em uma aplicaĆ§Ć£o complexa sob uma Ć³tica criteriosa que equilibra utilidade, valor e esforƧo necessĆ”rio.
Uma palestra que dividiu bastante o pĆŗblico. Na verdade, acredito que o Raphael Amorim deu o melhor dele para fazer o discurso significar exatamente o que ele queria que significasse. O Raphael sabe se comunicar muito bem, e paciĆŖncia foi o Ćŗnico requisito para captar a mensagem.
A Ju GonƧalves explicou o uso do reduce() na prƔtica. (Na prƔtica mesmo, para sair da BrazilJS usando, caso nunca tenha usado.)
O tema escolhido complementou muito bem a palestra de programaĆ§Ć£o funcional do Jacob Page, anterior a dela. O formato ficou perfeito para 30 minutos (a propĆ³sito, a ideia de abordar apenas o reduce() foi muito legal!), e deu para aprofundar bastante em algo que deve fazer parte do dia a dia. SĆ³ fiquei com a sensaĆ§Ć£o de que 5 minutos a mais ajudariam ela a guiar os exemplos com mais calma. O tempo estava bastante inflexĆvel nesse quesito.
Enfim, a Ju sabe o que faz. NĆ£o a conhecia pessoalmente ainda, mas conheƧo o trabalho e o entusiasmo dela e apostaria nela de longe, tal como a organizaĆ§Ć£o da conferĆŖncia, sem dĆŗvidas, fez.
ECMAScript 6: O que HĆ” de Novo, O que Mudou, O que tem de Bacana ou de Estranho!
Como o Laurie disse, o trabalho feito foi sensacional. Mereceu todos os aplausos recebidos, tanto pela apresentaĆ§Ć£o quanto pelos projetos paralelos que organizou.
Terminou com a frase que foi a grande mensagem da BrazilJS 2015: always bet on JS.
O fim
O evento acabou com um show de rock e cerveja artesanal. NĆ£o sou uma pessoa agitada, nem gosto de beber cerveja, nem queria me arriscar a chegar tarde em casa (voltaria de Ć“nibus), entĆ£o me limitei a finalizar meu dia indo falar com o Daniel Filho, que estava com outras duas pessoas, o Leonardo Balter e o Igor-que-foi-aprender-InglĆŖs.
Muitas pessoas levam notebooks e o EspaƧo BrazilJS foi uma Ć³tima ideia para lidar com isso. Conciliou o Ćŗtil (reconferir palestras, programar durante coffee break) ao agradĆ”vel (nĆ£o ficar no computador durante palestras). Ć muito legal ter um lugar para ficar com o notebook, embora eu nĆ£o recomende levar caso vĆ” embora de Ć“nibus, como vivenciei.
Notas finais
Foi difĆcil comer e beber no primeiro dia. Percebi que, em vez de as pessoas organizarem-se em filas, muitas ficavam no entorno da mesa do coffee break, e isso dificultou muito o fluxo. No segundo dia, no entanto, foi bem mais organizado.
Os organizadores nĆ£o param. EstĆ£o sempre envolvidos com o evento, resolvendo pendĆŖncias e atendendo a feedbacks. Houve dedicaĆ§Ć£o integral por parte do Daniel, Felipe e Jaydson em fazer uma conferĆŖncia confortĆ”vel para todos. O segundo dia nĆ£o foi mais tranquilo porque simplesmente foi e a a conferĆŖncia deste ano nĆ£o foi mais diversa porque simplesmente foi. AgradeƧo a eles por isso.
Basic knowledge of computer languages (mainly JavaScript) is assumed.
Some time ago, a friend of mine asked how skilled Iād say I was with JavaScript. I told him I was fluent.
āĀ Fluent? What does it mean to be fluent?
āĀ Well, think Portuguese. āĀ We both speak Portuguese ā I donāt know every word, but I do know the language enough to express anything I need somehow.
It turned out that āfluentā was just the perfect word.
Fluency is a powerful and straightforward concept to express your ability with a language. When it comes to human languages, itās the ability to fully communicate your intentions to a human; for computer languages, the ability to fully communicate your intentions to a computer.
That line of thought is shared in one of the most important and revolutionary introductory books to Computer Science. In Structure and Interpretation of Computer Programs, right before introducing Lisp (the programming language used throughout the book) a similar analogy is made:
Just as our everyday thoughts are usually expressed in our natural language (such as English, French, or Japanese), and descriptions of quantitative phenomena are expressed with mathematical notations, our procedural thoughts will be expressed in Lisp. 1
For both kinds of languages, the levels are the same: one cannot communicate; can poorly do it (beginner); can do it (native/fluent), or can brilliantly do it (think book authors, public speakers, and Software Engineers in a senior level).
Why do they match so well?
They match because the linguistics of computer and natural languages wonderfully intersect. Both consist of syntax, semantics and pragmatics functions, found in the core of theoretical linguistics.
In their ecosystem, we can also find syntax trees and different style guides.
Syntax
Syntax is the set of rules that govern how language elements are combined to form a valid expression.
In English, the basic rule is that elements like nouns, verbs and punctuation marks must follow the subject-verb-object order to produce a valid sentence. In JavaScript, a programming language, to produce a valid conditional statement, elements such as if, parenthesis, braces, comparison operators (===, <= ) must be combined in a certain order too.
In the same way that āDo they car a put?ā (??) is not valid English, the following code is not valid JavaScript:
if {1 === 2} (
+return true
+)
+// => SyntaxError: missing ( before condition
+
+add x y = x + y // u can't use elm's lambda syntax on js, no
+
And just like a pedant friend would do when you write shitty English, the computer will throw a syntax error when running your program. Forgot closing a brace? Wrote an if statement condition using curly braces instead of parenthesis? Well, SyntaxError!
This, however, is valid JavaScript:
if (1 === 2) {
+return true
+} // "if (1 === 2) return true" is also fine!
+
+const add = (x, y) => x + y
+
In HTML there are syntax rules too. Adding a div inside ul, for instance, is invalid. An unordered list in HTML (ul) only allows list items as children, such as li āĀ and div is not one.
Languages have different degrees of syntax strictness, which is what usually makes some harder to grasp than others. Think the German language ā German imposes very strict rules for articles: they may vary in number, gender, and function. English, on the other hand, has a definite (the) and an indefinite article (a/an)Ā ā and thatās it.
The same applies to computer languages: some happen to be extremely strict when it comes to syntax, while others are designed for greater syntactic flexibility, letting you achieve the same result in different ways. Think semicolons: they are optional when ending statements in JavaScript, but mandatory in C.
Semantics
Semantics is what the language expression evaluates to. In human languages, expressions evaluate to thoughts, questions, answers; while computers evaluate expressions to CPU instructions that comprise a programās flow.
Consider the following English statement:
The ant ran over the car.
I donāt know what ants you are familiar with, but even though the sentence contains the necessary elements in correct order and grammar, that doesnāt make sense. The statement is syntactically correct but semantically wrong āĀ we canāt conceive a meaning from it.
(āThe car ran over the antā, however, would be definitely more acceptable to our ears.)
We can relate semantics to computer languages in several ways (like āsolving the wrong problemā, basically), but the āsemanticā word bubbles up more often when we think about HTML. Consider the following markup:
<span>What is a fruit?</span>
+<div>
+ A fruit is something that humans eat. Some examples of fruits are:
+ watermelon, pineapple and apples.
+</div>
+
The elements span and div do exist in the language and are validly marked in this case (I didnāt do >div<, right?), so the browser will understand and show it accordingly to the user. The syntax is correct; yet, span and divs are non-semantic elements, so computers wonāt get any meaning from it. Again, syntactically correct but semantically wrong.
That text, though, is clearly a title and a paragraph. With a bit of HTML knowledge, we can communicate this in a meaningful way to computers! The language provides elements to achieve that.
The following code improves the previous markup for better semantics.
<h1>What is a fruit?</h1>
+<p>
+ A fruit is something that humans eat. Some examples of fruits are:
+ watermelon, pineapple and apples.
+</p>
+
The element h1 is being used to communicate the main title, and p communicates the paragraph. Both syntax and semantics make sense now!
Pragmatics
Pragmatics is what the language expression evaluates to within its interactional context āĀ which might totally affect semantics and syntax.
In a natural language, the context is essentially built around the cultural aspects of the speaker, place, time, manner, and several others unpredictable aspects that humans introduce when communicating.
For computer languages, we can see pragmatics as the methodology or implementation used when approaching a problem: composition vs. inheritance, functional vs. imperative, picking a Design Pattern etc.
Consider the following examples:
A child saying that the food is horrible to a beginner that started cooking just recently.
A new joiner in the company filters items in an JavaScript array using forEach, but the team expected filter to be used āĀ a more functional approach.
A programmer implements Fibonacci with recursion instead of iteration.
Your friend uses a very erudite language to add a cake recipe on the internet.
What do they all have in common? By themselves, they are neither right or wrong ā unless you consider the context in which they were approached in.
Having either syntax or semantic skills wonāt help you understand whatās wrong, since pragmatics is more about whatās appropriate within a context. Some approaches are more elegant, antiquated, or dialect-basedĀ than others, and we can only tell how valid they are considering what we are trying to achieve.
Syntax trees
Both kinds of languages can be represented using syntax trees, a concept that reuses the mathematical concept of partially ordered sets.
Human languages are analysed through the Concrete Syntax Tree (āCSTā), a context-free analysis that tells us about the function of each language token (word, punctuation etc) used.
This is the Concrete Syntax Tree for the previous sentence, āThe water drank a glass of Mary.ā:
Computer languages are also represented using syntax trees! When the code (high-level) gets translated into instructions for the computer (low-level), a program called compiler make uses of them. The Concrete Syntax Trees for a program contains a lot of detailed information, from whitespaces to language expressions, so you can imagine a CST for a real-world JavaScript program as something really lengthy.
What compilers do might be tough to understand at first, but think of this program inside us that converts languages to meaning ā our internal compiler. Kids improve their compilers while communicating with their families, so every day they get to understand their mother language even more. If you understand English yet struggle with German, we can say your German compiler is pretty bad and has to be improved.
The compiler simplifies the CST down to the expressions that truly represent the program after syntax analysis. Thatās where the Abstract Syntax Tree (AST) comes in: the syntax tree that actually lies at the heart of semantic definitions!
Letās consider the following JavaScript program:
let x = 0
+
+if (x) {
+x++
+}
+
This is the Abstract Syntax Tree for it:
Itās really about the essentials when considering language grammar. If a whitespace means nothing in a language, that wonāt show up in the AST.
When the same expression can be written in several ways because the language is not strict enough about it, style guides aim to answer the question of which style to go for. Curiously, style guides of writing are just as useful for programmers as they are for journalists!
Letās say Iām telling someone my favourite fruits. I could do it in different ways:
My favourite fruits are watermelon, bananas and strawberries.
+
+// or using the Oxford comma
+My favourite fruits are watermelon, bananas, and strawberries.
+
The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. [ā¦] Yet the program construct, unlike the poetās words, is real in the sense that it moves and works, producing visible outputs separately from the construct itself. It prints results, draws pictures, produces sounds, moves arms. 2
Even with all the similarities, programming languages are still artificial, while human languages are natural. Computers are rigorous, wonāt allow you to be ambiguous, and only get what you mean if you put it the right way.
You wonāt have filler words in a computer language, because computers donāt benefit from your thought process. Humans do benefit, though, and Iād even say that those communication imperfections is what connects us to others.
Apart from that, a programming language is an interface between you and a computer, while a natural language is an interface between you and another human being. You are communicating to a computer, but as a human ā and you probably wonāt be the only one doing it.
Writing in a way thatās meaningful for both is therefore part of the writing process ā and probably the most demanding one.
Final thoughts
Just like experienced programmers look at documentation and easily apply language features to create pieces of software, fluent English speakers would look at the dictionary and easily come up with phrases.
Because both computer and natural languages share linguistic structures, speaking about programming skills in terms of fluency works just as well.
After all, fluency is all about how easily our intentions are expressed with a language.
In a life where, by default, thereās no meaning at all, I value creating above all. If Iām creating, thatās a meaningful day.
Lately, Iāve been pondering on the phenomenon of creativity and why creative people are so inspiring to be around. They just broaden my perception of the universe profoundly. What really happens?
The Phenomenon
In an interview in the late 1990s1, Steve Jobs said something that years later would be seen as one of the most simple but accurate definitions of creativity:
Creativity is just connecting things.
And he followed with something I couldnāt help but relate: āWhen you ask creative people how they did something, they feel a little guilty because they didnāt really do it, they just saw something. It seemed obvious to them after a while. [ā¦]ā.
In the wake of being called creative, I was used to responding with the most unfair answer ever: āBut everything I did was mixing stuff from here and there!?!ā. It turns out, however, that āmixing stuffā actually describes precisely the process creative people go through.
And when Steve Jobs said that, he was mixing stuff as well! He most likely got inspired by James Webb Youngās conception of idea, presented in his book A Technique for Producing Ideas, from the 1940s.
An idea is nothing more nor less than a new combination of old elements [and] the capacity to bring old elements into new combinations depends largely on the ability to see relationships.
For James to suggest that, well, guess what? He was inspired by Pareto's idea of the "speculator", a personality type characterized by a constant preoccupation with the possibilities of new combinations of old elements. (Which sort of proves his own point on "ideas as a combination of old elements".)
Creatives are just so overloaded with elements to mix that those overflow and flow out of their heads, and they canāt help but inspire everyone around.
They reframe experiences and mix their elements to be synthesised into something valuable and unique. From songs, painting, programming to scientific theories ā all of them comes from mixtures. When the mixture feels good, either as a homogeneous or heterogeneous result, itās then a creation.
The Creation, The Weird
When the creation distances itself too much from its origin elements (which are things people are already aware of, most likely), itās perceived as weird, rather than authentic. But thatās when we truly innovate! To come up with the weird, though, we have to limit ourselves to certain existing elements ā an outstanding habit people like Alan Turing had.
Alan Turing was an inspiring computer scientist. Among other cool stuff, he proposed humans to consider the question "Can computers think?", and also designed cryptanalytical machines, crucial to cracking German encoded communication during the World War II. Cool stuff!
As described by James Wilkinson, who worked closely with him, Turing avoided looking at previous work on a topic just so he could invent something truly original, truly weird.
āTuring had a strong predilection for working things out from first principles, usually in the first instance without consulting any previous work on the subject, and no doubt it was this habit which gave his work that characteristically original flavor.ā2
Finally, the ones who release their creations end up turning into painters, mathematicians, writers, architects, sculptors, programmers, musicians. Itās a process that happens in absolutely every realm of thinking and work.
And you know what?
ā¦Itās Been Shown by Nature
When Young and Steve Jobs pointed out that the creative process wasnāt magic, they, again, didnāt do anything ānewā either. That definition has been shown by Nature for a long time, and, as early as 450 B.C, the philosopher Anaxagoras described it:
Wrongly do the Greeks suppose that something3 begins or ceases to be; for nothing comes into being or is destroyed; but all is an aggregation or secretion of pre-existing things; so that all becoming might more correctly be called becoming mixed, and all corruption, becoming separate.
That might remember you of the Law of Conservation of Mass, later defined by the chemist Antoine Lavoisier.
Just like in the creative process, Nature has always found a way out of its problems by coming up with solutions from pre-existing elements. Even the Planet Earth has transformed from a violent, molten rock to a supporter of life by using what the Universe had already provided!
Its process of creation was the same as the humanās creative process for the discovery of fire, the invention of the wheel, shitty and useful startup ideas, the Pink Floydās Echoes song, and all quotes in this post: mixing, connecting, combining āstuffā. From the Planet Earth to what youāre reading right now, the laws that ruled their creations were, in essence, the same.
Brushing teeth is a good habit. An easy-to-build one, Iād say, thanks to the immediate reward given by the refreshing sensation. After brushing, you feel clean right away.
On the other hand, flossing teeth isnāt a habit as easy to build. After flossing, what comes to mind is how dirty your teeth still were even though you just brushed, not how cleaner they became. Thereās no such thing as a fresh sensation in your mouth.
When you finish brushing your teeth, theyāre still dirty āĀ no doubt. However, itās still gratifying, since youāre fooled by the menthol ability to trigger the cooling sensation.Ā (Hence the human inclination to brushing rather than flossing!?)
In terms of dental health, though, flossing teeth is more effective on cleaning than brushing1, even if it doesnāt feel like it. Thereās no immediate reward in flossing, but definitely a long-term one.
What am I trying to say? Apart from dental health advice, that sort of reminds me that we shouldnāt rely on feeling instantaneously compensated as a fuel to build habits. After all, some things just need the long-term to pay off; for we to benefit from them.
1
Iāve read that at some point in my life but donāt remember where. You can find some resources out there, such as āWhatās More Important: Flossing or Brushing?ā. Anyway, I think weāre safe assuming that flossing is, at least, as important as brushing.
Se existem recursos no CSS que a total compreensĆ£o se restringe a uma parcela de desenvolvedores, esses sĆ£o os combinadores filhos (>), irmĆ£os adjacentes (+) e adjacentes gerais (~).
Sem dĆŗvidas, esses 3 combinadores sĆ£o tĆ£o poderosĆssimos quanto mal-explicados. Ć importante compreendĆŖ-los integralmente e hĆ” dois bons motivos para isso: o seletor descendente nĆ£o dĆ” conta de tudo e, o Ć³bvio: o CSS estĆ” evoluindo.
Supondo um artigo constituĆdo por um tĆtulo e 3 parĆ”grafos. O primeiro parĆ”grafo apĆ³s o tĆtulo servirĆ” como uma introduĆ§Ć£o ao artigo e, portanto, deve ser destacado com um aumento no tamanho da fonte.
HTML
<article>
+<!-- Z -->
+ <h1>TĆtulo do artigo</h1>
+<!-- X -->
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+<!-- Y -->
+ <p>Debitis sint aperiam numquam nisi animi porro in reprehenderit!</p>
+ <p>Magnam atque placeat fuga sed eligendi maxime neque labore. Doloribus?</p>
+</article>
+
CSS
h1 + p {
+font-size: 20px;
+}
+
Na prƔtica 2
O checkbox hack funciona com o uso do combinador irmĆ£o adjacente.
HTML
<input type="checkbox" id="hider" />
+<div>Hide me if you can!</div>
+<label for="hider">Esconder div</label>
+
CSS
input[type="checkbox"] {
+display: none; /* Esconde o checkbox */
+}
+input:checked + div {
+display: none; /* Quando o checkbox for checado, a div serĆ” escondida */
+}
+
Esse combinador contorna algumas inflexibilidades do combinador irmĆ£o adjacente. Ainda com o exemplo do checkbox hack, podemos personalizar o elemento de forma nĆ£o tĆ£o especĆfica quanto Ć sua posiĆ§Ć£o:
HTML
<input type="checkbox" id="shower" />
+<label for="shower">Mostrar div</label>
+<div>Hide me if you can!</div>
+<div>Hide me too if you can!</div>
+
CSS
input[type="checkbox"],
+div {
+display: none; /* Esconde o checkbox e a div, por padrĆ£o */
+}
+input:checked ~ div {
+display: block; /* Quando o checkbox for checado, a div aparecerĆ” */
+}
+
ConclusĆ£o
As linguagens CSS e HTML foram documentadas para serem intuitivas: os elementos formam famĆlias com outros elementos pais, filhos, descendentes, irmĆ£osā¦. Isso fica claro no nome dos seletores, que tĆŖm papel importante na compreensĆ£o do combinador; afinal, caso o desenvolvedor entenda que irmĆ£os tem o mesmo pai e que filhos sĆ£o descendentes diretos do pai, ele poderĆ” tirar um bom proveito do nome dos combinadores para compreender seus funcionamentos.
[ā¦] In both cases, non-element nodes (e.g. text between elements) are ignored when considering adjacency of elements.
What most people donāt know when they first get into Redux is that, just like React, Redux itself is meant to be simple. And as seen that simplicity is a goal, both React and Redux wonāt and donāt want to tell you how to solve everything.
They wonāt tell you how to deal with side effects, or what HTTP request library you should use. Thatās completely delegated to the JavaScript ecosystem.
React and Redux alone donāt do much for really complex web applications.
React indirectly delegates state management problems to solutions like Flux. On the other hand, Redux, for instance, delegates dealing with async stuff or even the too-much-boilerplate problem that people complain.
But what motivates React and Redux to be that way? Some reasons I can think of are:
Both libraries are highly focused on their principles, not the built-in stuff. The efficiency of them is on the why and how, not the what.
They aim to be a great fit for both simple and large applications, so the āplug-in-playā approach is followed. (A framework wouldnāt ever do everything a programmer needs anywayā¦)
Diversity of solutions. Because React and Redux are more like āplug-in-playā, the āpluginsā (tools, libraries, middlewares) will evolve by themselves. For instance: axios, a HTTP request library, will evolve in parallel to Redux itselfĀ ā which certainly make things move forward faster!
If your applicationās state is messy, donāt blame it on React. If you find yourself writing too much boilerplate, donāt blame it on Redux. React and Redux donāt really do much, but this is by design.
React is awesome not just because it makes it possible to turn a large and complex application into simple components.
Redux is awesome not just because it makes it effortless to deal with and share state throughout an application.
Theyāre also awesome because of their great and diverse ecosystem. So, when you buy into React or Redux, itās better for you to buy into their ecosystem too.
Conditionals! As programmers, we write at least one every day. Easy to write, horrible to read, and sometimes it seems as though thereās no way to work around that.
Today, Iām happy to share some patterns Iāve learned over time and have spread heavily in code reviews. Letās rethink conditionals to make the most out of a languageās power of expression āĀ in the case of this article, JavaScript.
Patterns for Conditionals
First, to put you in the mood, a quote from Literate Programming1, by Donald Knuth.
The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other.
That sums up the approach for this post: purely aimed at how to write code for people to read. Performance doesnāt matter now, since 1) thatās not the goal and 2) I donāt believe in premature optimisation.
Iāll briefly talk about each pattern, but whatās more important here is to read the code carefully and get something out of it (as if it were poetry or something!).
1. Variables that hold conditions
When your condition is made up of an expression (or many of them), you can store it within meaningful-named variables.
Letās say, to illustrate, that our program holds some data about a fruit and we have to check whether that fruit is a banana. We could do this:
const fruit = {
+ colors: ["yellow", "green"],
+ sweet: true,
+}
+
+const isSweet = fruit.sweet === true // or just `fruit.sweet`
+const isYellow = fruit.colors.some((color) => color === "yellow")
+const isBanana = isYellow && isSweet
+
+if (isBanana) {
+alert("do your stuff š")
+return "is banana"
+}
+
Not all conditions need to be in a variable. fruit.sweet, for instance, is quite expressive by its own.
This way, if we or our workmates need to know what makes a fruit a banana in our program, itās just a matter of checking out the variable itself. The logic for how conditions evaluate will be there, behind a meaningful name.
Itās even more useful for composing and reusing conditions.
Filtering arrays
In the previous example, all variables were conditions based on the fruit object, for didactic purposes. Commonly, though, those variables actually store (pure) functions that take any fruit and test against it. I'm changing that to fit this example.
Letās say weāve got an array of fruits and we need to filter all the bananas out of it.
So expressive! I love the way that I can read that last line and even a kid (a non-programmer one!) can understand. (Yes, Iāve tried that.)
The currying technique would help introduce expressiveness without the verbosity for isBanana. An optional appendix at the end of the article elaborates more on that, if youāre curious.
Thatās it. Hold on to that one though ā itās the foundation for whatās next.
2. Define value conditionally
Still considering the variables from the example above, this could also be done:
The value for the myFruit variable will only be assigned to ābananaā if those conditions are true. Pretty useful for when values are defined conditionally!
That saves you from if (isYellow && isSweet) [...], and itās quite expressive, Iād say. An expressive expression. š
3. Define value conditionally with fallback
What if we want something else in case itās not a banana? Instead of an if (isBanana) [...] with else, go for the ternary operator.
Some additional but important advice Iād give regarding ternary expressions:
Make them as compound as possible.
Do NOT nest them. Donāt pretend the nesting is readable āĀ itās not even human to do that.
Donāt avoid writing if statements because you want to look smart.
4. Check for all conditions
Weāve (finally) found out that checking for isYellow and isSweet isnāt enough to make sure the fruit is a banana. After all, yellow pepper is both sweet and yellow and itās still not a banana, right?
Right. We then add more checks to the isBanana variable, and this time theyāre ugly ones: they check whether the fruit is either from Brazil or Ecuador, both top banana producing countries.
Did you see how big isBanana is getting? Weād have to start breaking lines in those && to improve readability, which, personally, I donāt like doing.
If refactoring the booleans into new variables isnāt an option anymore, what about storing the conditions in an array and testing every item for truthiness?
We want something special for when the banana is Brazilian! else conditions would do the trick, wouldnāt they?
const fruit = {
+ colors: ["yellow", "green"],
+ sweet: true,
+ countries: [
+ {
+ name: "Brazil",
+ topProducer: true, // i'm brazilian and therefore biased
+ },
+ {
+ name: "Ecuador",
+ topProducer: false,
+ },
+ ],
+}
+
+const isSweet = fruit.sweet === true // or just `fruit.sweet`
+const isYellow = fruit.colors.some((color) => color === "yellow")
+const isBrazilian = fruit.countries.find((i) => i.name === "Brazil")
+const isEcuadorian = fruit.countries.find((i) => i.name === "Ecuador")
+const isBanana = isYellow && isSweet
+
+if (isBanana && isBrazilian) {
+// first true case!
+alert("i am a brazilian banana i love football š")
+} else if (isBanana && isEcuadorian) {
+alert("i am an ecuadorian banana do not mess with me š")
+} else {
+alert("a normal banana from somewhere else")
+}
+
Alternatively, THOOOUGH, we can early return (nothing at all, i.e. undefined), which will make our code stops its flow at that point.
if (isBanana && isBrazilian) {
+alert("i am a brazilian banana i love football š")
+return // sTAAAAHP!!!1
+}
+
+if (isBanana && isEcuadorian) {
+alert("i am an ecuadorian banana do not mess with me š")
+return // DON'T GO ANY FURTHER, JAVASCRIPT!11
+}
+
+// or do, whatever
+alert("a normal banana from somewhere else")
+
Those checks could also be refactored into a variable named isBrazilianBanana. I found it too much for this example though, so this is just a friendly reminder that your conditions can always be composable.
Keep in mind that early returns might make the flow of your program confusing. Different from when youāre using else conditions, itās not explicit that the conditionals are from the same logical group anymore.
7. Check for the same variable
Letās get the colour of the fruits! Each fruit has one.
Hmmmā¦ Different cases that require different handling, but all handled cases depend on the same thing. What do we do? We conditionally check for its value and handle the case depending on that.
This is a very common technique I first saw on a blog post from Angus Croll in 2010. I love the simplicity of it.
Nowadays thereās even more freedom with this technique, considering features such as computed property names for objects. But donāt get too creative with that! Go for whatās more readable and expressive for you AND the people you work with.
Appendix: Currying, because verbosity isnāt expressiveness
This is an additional reading and requires familiarity with curried functions. For further reading on the currying technique, I recommend the "Currying" chapter of the book Mostly Adequate Guide to Functional Programming, or A Beginnerās Guide to Currying, as a more beginner-friendly introduction.
Letās reconsider:
the problem from the 1st, where we had an array of fruits and had to create a function that checks whether the fruit passed to it was a banana, and
the all util from the 4th pattern.
Check for all conditions, revisited
Imagine if we had a lot of conditions for isBanana. We could use && or even all.
Itās meaningful, easy to read, but introduces too much verbosity. The currying technique could help us introduce more meaning without being verbose. With some changes in the all util, that could be boiled down to:
const isBanana = all([isSweet, isYellow, isEcuadorian, isBrazilian])
+// no explicit fruit here, and still works!
+const bananas = fruits.filter(isBanana)
+
Notice weāre not explicitly passing fruit anymore. How do we do that? By making all a curried function. There are some ways to achieve that, hereās one:
It takes the array of conditions and returns a function that takes the current item and calls each condition with that (as argument!). At the end, we check whether they all evaluated to true. Itās not magic, itās CURRYING!!!112
Thatās, of course, a simplistic implementation, which has costed me an array (from map). Whatās important to get is how we play with function arguments under the hood to achieve currying.
You can curry your functions using Ramdaās curry (or Lodashās, whatever); or, if youāre interested on that as an util, Ramdaās all and its source are really worth-checking!
Final considerations
By striving for conditionals as expressions other than statements, you write code in a functional approach. Code with a clearer sense of what itās being checked without having to unearth to its foundations. Code thatās easier and faster for people to reason about.
But if your code is fine with an if rather than an object lookup or a ternary operator, just stick to it.
Itād break the whole purpose of this post if those patterns were used for looking smart. However, if refactoring your conditionals with them would lead to a more expressive codebase, go for it! Play with the patterns, compound them. Use your creativity to communicate well.
Itās a language, after all.
1
A programming paradigm first introduced by Donald Knuth, with the goal of providing an alternative, human, perspective on the programmerās motivation. Read the article.
2
It may seem more magic than currying sometimes. JavaScript isnāt a purely functional language, so such techniques arenāt as popular as they are in Haskell community, for instance. Simplicity conflicts with easiness here.
The other day, a npm package was released broken to a private GitHub registry and it wouldnāt install:
> npm install @company/my-package
+This error happened while installing the dependencies of @company/my-package@0.0.34
+
+another-package is not in the npm registry, or you have no permission to fetch it.
+
The error message is clear: the released package @company/my-package Iām trying to install depends on a package another-package expected to exist in the npm registry somewhere. But another-package is not there. I already knew those packages came from a monorepo, so likely another-package was only an internal dependency in the monorepo, left unreleased. I wanted to inspect the package contents before releasing any fix to be sure, but couldnāt rely on npm install for that. There used to be an option to download npm packages via GitHub UI, but thatās no longer the case.
Finding the package tarball
One can read the packageās metadata to find a download URL for the packageās latest version. Hereās how:
(For private GitHub registries) Grab a classic GitHub token with packages:read permissions (hereafter {GITHUB_TOKEN}).
The URL of a npm package published to GitHub is https://npm.pkg.github.com/{PACKAGE_NAME}. Use that to fetch the package metadata, which contains the package tarball URL.
Setup for Audio Interface with Guitar Rig 5 on macOS Mojave
Setting up Guitar Rig 5 on macOS Mojave seems not to be straightforward.
Although I had gotten the signals to be sent from my guitar to the audio interface and from the interface to Guitar Rig, somehow itād still not work. Instead of using my audio interface as the input and output device on Guitar Rig, I had to set up an āaggregate deviceā.
This how you can do it too.
(My specs, just so you know:)
macOS Mojave Version 10.10.14
+Guitar Rig Pro 5.2.2
+Audio Interface Steinberg UR22mkII
+
Audio MIDI setup
Open āAudio MIDI setupā in your Mac. (Itās a tiny secret sound manager shipped along with the system, youāll find it.)
At the very bottom of the app, there is a small + (āplusā) button wherein you should select āCreate an aggregate deviceā.
Set up your āaggregate deviceā with your 1) audio inteface and 2) speakers/headphones/whatever āĀ which should be all shown up there, given the setup is correct. Remember to give your device a remarkable name ā I suggest FUCK COMPUTERS AND AUDIO.
Go back to Guitar Rig. In the context menu āFileā, go to āAudio and MIDI Settingsā. In the āAudioā tab, select your aggregate device as the device, instead of only the audio interface as you were doing before; then configure input/output as expected in the āRoutingā tab.
Using translate() is one of the easiest ways^[Flexbox also provides a great solution. See Solved by Flexbox: Vertical Centering] to instantly horizontal and vertical align any element with CSS without knowing its dimensions.
Nevertheless, after witnessing some people getting their bikes stolen, I feel privileged to say that itās been more than 1 year Iāve got my bike. If that is because of my good lock or my good luck, Iāll never know.
But I can tell you about the lock.
My lock setup
I generally agree that you should invest as much as you can afford in your lock setup. Iāve put a considerable amount of money on mine because I deeply care ā in other words, I have no psychological resilience when it comes to bicycles so losing mine would definitely get me in tears.
If you care about numbers without any trustable source, I've seen recommended somewhere that you should be investing between 10%-20% of the bike price in a lock. š¤·
Therefore, considering the price of having to go home by feet and with tears in my eyes, I did the best I could and went for the Kryptonite Evolution Mini-7 with Double Loop Cable (highly recommend you to check their website for more information).
I make sure my bikeās frame and both wheels are locked to a fixed rack ā cemented into the ground, ideally.
I had considered the Kryptnonite's New York Fahgettaboutdit, but I found it way too heavy and the safety factor difference didn't pay off for me at that time. I'd recommend it if an extra weight is no problem for you though.
For I still have my bike after 1 year, I am honestly happy with my choice. The lock came with:
Three keys with an unique number. For your information, Kryptonite has a system where every key gets a number, so you can order replacements online in case you mess up.
A handy mount made by Kryptonite: Transit FlexFrame U-Bracket (not visible in the photo because itās in the top tube), so I donāt have to carry the U-lock in my backpack or whatever.
Iāve read a couple complaints about the lock not fitting both the wheel and frame to most city racks, however Iāve managed to do it in most racks around Berlin. Itās definitely not the most flexible and spacious lock, but thieves would love some extra space to do their work too, so I think itās just the size it should be after all.
When looking for a lock, instead of (only) asking yourself whatās the best lock ever, ask āHow much trouble am I putting a thief into with my lock strategy?ā.
It hasnāt been enough stressed that locks do NOT prevent determined thieves with their lock pics, cable cutters, bolt cutters and angle grinders to steal you bike. Period.
Locks do, though, make it harder for thieves to pick your bike, by increasing the āriskā factor in the risk/reward calculation done before they attempt to steal.
Itās all about making it harder. And how do you do that? By having a diverse lock setup, and, just as important: by being extremely careful on where and how to park.
Donāt think just U-lock: saddle locks, wheel locks might be worth-checking too! One awesome lock is just one at the end of the day, and the more tools the thief needs to carry out, the better.
Looking further
Some articles Iāve read last year and that might be interesting if you own a bike and want to learn more on how to keep it safe.
Best Bike Lock: Review of several bike locks and learnings on how to pick a good one.
How to Lock your Bike: Great tips on where to park your bike and what to lock it to.
How to Exclude CSS, Images, Anything from Unit Tests
Your app needs all those require, but your unit tests may not.
When developing web applications, we deal with assets that our JavaScript tests donāt have to be aware of.
If using Webpack, which enables different imports in your JavaScript files, youāve configured loaders that your test runner probably know nothing about. Therefore, that SVG image in your React component and the imported CSS will both be parsed like JavaScript in your tests. A lot of confusing errors will be thrown, of course.
So letās learn to exclude anything your unit tests, from styles (CSS, Sass), images (PNG, SVG), to other specific imports (like SVG images as React components).
Hook your require() calls
By intercepting require() calls, you can make your testing framework ignore what you want to be ignored the way you want it to be ignored.
Itās also useful in isomorphic setups.
Return an empty module
It all comes to returning an empty module for unwanted imports. It looks like this:
module.exports = "";
+
Jest
For Jest, configure moduleNameMapper to return the empty module for specific extensions. Example:
require-hacker is an option for hooking require() calls.
You can also use built-in compilers (like moduleNameMapper in Jest or Mocha compilers), or even only import ignore-styles into your testing framework (which is preconfigured).
Iāll stick to require-hacker and custom configuration because thereās more flexibility.
Get it from npm:
npm install require-hacker --save-dev
+
Configure
Create a JavaScript file and set custom handlers for specific extensions using require-hackerās hook() method.
Assuming you want to ignore CSS and PNG files, always return an empty module for them:
Because youāre smart, youāll store all extensions in a variable and forEach them, so thereās no need to repeat yourself. Example.
Import into your test runner
Let your favourite testing framework know about the require hacking! Some examples, assuming a ignore-utils.js file:
Mocha
Add to your mocha.opts, or use the --require flag:
mocha --require ./ignore-utils
+
ava
Add to your package.json:
"ava": {
+"require": [
+"./ignore-utils"
+ ]
+}
+
Now some files will be treated like shit in your JavaScript testsĀ ā which is AWESOME!
Bonus: React null component
You donāt need to load that boring SVG icon of a house to test that critical feature in a React component, right?
Right. In case youāre using svg-inline-loader, which transform your SVG files into React components, you cannot just return an empty module because your test case would be actually expecting a React component. Things will break. Annoying errors will be shown.
So, instead of returning an empty module for SVG files, return an empty React component. Letās set a custom handler for that!
Configure
This example uses require-hacker. For Jest, export a React null component and set it in moduleNameMapper.
When we want to test whether a prop has been called, mocking the prop in the component is usually the preferred way. This is how it goes with Jest and Enzyme:
I am using Enzyme however you should be able to spy on similarly using other testing librariesĀ āĀ just make sure you are spying on a function in the props coming from the component prototype (as in wrapper.instance()).
Thatās all. Just posting it here cuz I couldnāt find it easily anywhere else.
What if the user interface is more beautiful-looking than usable, understandable, and intuitive?
The visual aspects of an user interface play an essential role in organising information. Once youāve got the resources, however, that turns out to be the easiest part of an Interface Design process.
Sure we like things that look nice, but looking nice doesnāt compensate a bad product design. Visual communication should not compensate flaws.
If you spend most of the time looking for visual inspiration rather than conducting research, doing usability tests, and studying metrics such as business goals and conversion rates, you will probably come up with a interface that only looks beautiful.
I struggle every day trying not to be one step ahead. Living everywhere else but the present and leaping through time have become part of how my brain is wired, so I often find myself not experiencing much anymore.
A while ago, a friend told me about his sensory-deprivation experience in some kind of pool, the so-called Isolation Tank. No sight, no hearing, no touch, no taste, no smell ā the idea of getting absolutely no input from anywhere struck me as a way to get my perception back on track. I decided to try it out.
On a sunny Saturday of November, I, along with my endless stream of thoughts, floated for 1 hour straight in a soundproof egg-shaped tub shallowly filled up with salt water. This is my report.
Getting In
With my bathing suit on and no expectations of anything, I showered, got into the tub and sealed down its cover. My body floated easily on that water that thermically felt like my own skin, and a relaxing sound was playing in the background up to the moment my surroundings got all pitch-black.
The first 15 minutes were all about withstanding how restlessly my mind wanted to get out of there. Iāve had done meditation before, but 1 hour was something else. I recalled I worked 8 hours a day, 5 days a week, and therefore I should be making the most out of my Saturday instead. Leisure time! In modern life, that usually means stimulation by means of binge-drinking with friends, uplifting music, delicious food, watching heart-breaking moviesā¦. Quite the opposite of soul-crushingly doing nothing.
The mind just plays a lot of games on you all the time. It tricked me into being physically irritated by the water, its salt, that bogus zero-gravity environment, and that Iād be better off giving up for my own survival Ā ā at least, that was how my body anxiously (over-)reacted to it. But there was actually no physiological danger or whatsoever; truth be told, I was way safer than I had ever been throughout that week. I quit panicking.
I came upon different phases of denial, approval and mind-numbness from that onwards. Saw myself bringing up problems and drifting them away. Tried to work out situations I had no control over. Missed music, so made my own by tapping on the water. Went hyper-focused on how I had performed socially last week to what was going to happen in the next few weeks when I eventually hand over my old apartmentās keys to that spiteful Hausmeister who hates my German.
My thoughts just went on super randomly. After a while, I could draw the exact line where each one ended, and got mindful about my weary physical overreactions to them.
Towards the end, I sank into something else: weightlessness, timelessness, solitude were emerging from that isolation. Things started losing shape. Didnāt perceive water. I was either a floating head or a floating body. I had to touch my thighs, boobs, neck just to relieve myself from the uncertainty that being so relaxed made me feel about where I was.
I wanted to come back down to Earth from wherever I was, and, surprisingly, to be myself ā the way I was. Then time was up.
Getting Out
I showered again to wash the salt off. The spa provided a relaxation lounge that was essential to ease the transition, sinceĀ I had neither desire nor need (important!) to rush anywhere. Hung out there for 1 hour.
The readjusting was an interesting and unexpected phase to me. Had an apple and felt how crispy in sound and taste it was. Drank a glass of water and sensed it going right down through. Read a book and couldnāt make sense of why we humans have ever brought up speed reading techniques in the first place.
Stepping out of the spa, I got savagely welcomed by a gloomy afternoon1 undergoing that life I was used to every day. A lot was happening out there: lights of apartments being turned on and out, cars groaning, people running around, traffic noise, the cozy energy of having my friend by my side, sharper textures of the sidewalksā cobblestones, and the joy of a having a sky whose amount of stars doesnāt depend on the many times we screw up as human beings, thankfully.
Berlin-Schƶneberg is quite chill so thatās helped to readjust. I was sensible and my thoughts were vivid and receptive āĀ pretty much the actual poetic mood I strive for, where I settle and listen to whatās being said in order to write it down. A mood that is āhighly disturbed by Philosophyā, as Goethe brilliantly summed up to Schiller once:
āI am still hoping for poetic hours, and philosophy, in my case, disturbs the poetic mood, probably because it drives me into the object, for I am never able to keep myself in a purely speculative mood, but have immediately to try and form a distinct conception, and on this account at once fly out into nature. [ā¦]2
I had finally my mind drifted towards just as much of the world as it was going on.
Lessons Learned
My poetic mood didnāt last muchĀ ā it wore off the day after.
Iāve realized how much we are externally stimulated and easily adapt to it as if it were natural. On top of that, we are internally stimulated by our worries and whatnot: have I paid my taxes? Am I persuading a career? Does my family still love even though I am thousands of kilometers from them? Have I been eating healthy enough?
It turns out itās clear why we donāt feel much anymore. Our brain gets wired to parallelising stimuli, and we have less and less coming from our body to the head than the other way around. Apart from that, our experience of the world is barely passive: we actively generate it with our biases, mental models, what and how much we consume. Mind shortcuts are crucial, but might restrain us from genuinely experiencing life, getting us to either ignore ou hyper-focus unconsciously.
I, now, have a better grasp of what Erling Kagge meant in Silence: In the Age of Noise, written after he had spent fifty days walking solo in Antarctica: āEverything seemed completely flat and white. [ā¦] Eventually, in complete isolation, I began to notice that nothing was completely flat after all. The ice and snow formed small and large abstract shapes. The uniform whiteness was transformed into countless shades of white. [ā¦]ā
Meditation is the absolute protagonist here, but floating got me into a different flow, and faster. The topic of sensory deprivation is definitely worth-exploring. Think like: If you ditch sugar for a while, it tastes sweeter afterwards. ;-)
This is pretty much what floating offers: sensory starvation and you on your own. You may waste your time and never get to anything, or make even most out of that 1 hour than me.
In 2018, circumstances inevitably changed and I began taking up much more in life. I was under stress, regardless of being on the safe side, and the patterns that kept me grounded were no longer holding up.
Back then, seeing the big picture was unattainable with the stress snowballing and skewing my perspective. Dwelling in my head, paving the way to learned helplessness, I decided to try out journaling.
More than a year later, I can finally say alles gut. Although circumstances havenāt changed much, I certainly handle them better. I keep journaling as of today, and am excited to share my setup and (hopefully) motivating takeaways!
How I Journal
I did not go for the traditional diary format. I decided to Bullet Journal, a flexible journal method founded in quick lifelogging by means of a pen, paper, and bullet points.
Pen and paper pull me out of my head and let me continuously evolve my notebook as my needs change, since there is no predefined template. As for bullet points, we all know their efficacy: hasty logging and later reviewing at a glimpse.
The Bullet Journal framework is made out of four fundamental ācollectionsā: Index, Daily Log, Monthly Log, and Future Log, plus custom collections you find valuable. After a while of tinkering around, I came to some insights and tweaks.
Index turned out useful when I added custom collections, as those usually end up scattered across the journal and thus hard to find.
Daily Logs is where I keep track of notes, events, tasks, thoughts, and ideas. (All mixed together, which portrays a day accurately if you ask me.) I recommend using signifiers and nesting (for a tree-like view) in bullet points to convey meaning with ease, as Bullet Journal suggests.
Monthly Log didnāt work for me. I steer towards weekly or quarterly ranges. Also, my online calendar is more practical so I couldnāt bother drawing calendars every month.
Future Logs are useful to migrate tasks or events to upcoming months, for when you donāt get something done but canāt ānevermindā it either.
As for custom collections, the Bullet Journal ecosystem is huge! Iāve seen stuff of all kinds out there: finance/sleep/food/water trackers, recipes, trip planning, doodles, and whatnot. Yet, these are the ones I always come back to:
Diaries: longer diary entries or brain dumps without the limitation of bullet points, for when I feel like it.
Habit Trackers: a simple daily tracker to monitor or develop habits across weeks, e.g. meditation, alcohol intake, call family.
Weekly Logs: my weekly variation of āMonthly Logā, with upcoming events and small goals for the week. Usually done on Sunday or Monday.
Quarterly Logs: my quarterly variation of āMonthly Logā, with upcoming events and big goals for the quarter.
Year Retrospective: a straightforward year review regarding what did and did not go well, what to keep or let go from last year etc. I journal spontaneously throughout the day, but mostly in mornings or evenings. I do it every day, even when I donāt feel like it. In the long run, thatās gotten me to fathom my anxieties by having them logged as well as what was up days before. It goes a long way to flip through logs of piled up chores, social isolation, binge drinking, and sleep deprivation, to later find yourself taking down āI am anxious. Canāt do shitā.
Be that as it may, I donāt keep it all gloomy. With my throughput in mind, I may also soften up my daily logs with receipts from exquisite restaurants I come across, cute post-its from friends, or even silly useless quotes from fortune cookies.
At last, I have to say Iām not really a big planner so you can see thatās not what I optimise my journal for. All I strive for is a little awareness of whatever Iām doing for the time being. I enjoy a spontaneous and organic life, and thatās gotten me far enough to make me happy.
Pen & Paper
In 2019, I used an A5+ (slightly wider than regular A5) dot-grid notebook. Itās bulky to carry around but I donāt regret it: the pages are wide enough to encourage writing. The quality of its pleasing yellow paper is outstanding, thick enough to prevent ink from leaking through. I ended 2019 with a few pages empty.
This year, I went for something more portable: an A6 dot-grid notebook. It took me a while to get used to the size constraints, and Iāve been certainly more straightforward with my logs. I am pretty sure I will have no pages left this time. (Wondering what was the advantage of it all as Iām not going anywhere anyway thanks to COVID-19.)
As for pens, I use different colours of a 0.4 mm fineliner.
What Iāve Learned
I'd not assume these stem necessarily from the way I set myself up. Audio or video recordings, traditional diary, and other journal formats are worth exploring and might help just as well.
Less overwhelm, more time. To truly chill out when life gets overwhelming, you gotta plan ahead. Especially in already busy weeks, I use my journal to put down chores I commit to get done, prioritising what I signify as deadline-sensitive. Before, with my tendency to overfocus, Iād take up activities without planning and end up neglecting my responsibilities and needs. Imagine how far this can go!
Emotional awareness. Iāve gained a grasp of the phenomenology of my emotions and the lens through which I see life, markedly my cognitive distortions on stressful days. Attitudes like pessimism inevitably surface as you jot down negative thoughts all the time. Being mindful allowed me to reframe negative views, and turn obstacles into opportunities.
Better retainment. Itās easy to fall into the trap of āI have a bad memoryā when one has been busy and mooning for so long. Leading a busy life mindlessly is not what I strive for, and journaling only feeds into that: I hold dear people, moments, promises, and no longer miss so many appointments (planning helped here too!).
Constant assessment. Journaling is a tool to assess the present as well as the past and the future. By peeping into where Iāve been, what did/didnāt go well, or who I have been with, for instance, I can ponder more sensibly on my growth and relationships. Early feedback on my own life, sort of, to leverage self-improvement in relationships, health, work, and so on.
Pitfalls
Perfectionism. Obsession over constant logging or perfection is right at the door for you to slip into. On social media (Pinterest, YouTube), everyoneās journal seems visually-appealing every day without fail. Even Bullet Journal, a method dead straightforward, can be a rabbit hole. Remind yourself to solve your problem in a way that enhances your daily life, not burdens it. You gain absolutely nothing from buying into slices of life people sell online.
Habit-building. When not a habit, journaling is just another chore. Make it effortless and engaging: establish a routine (if thatās your thing), designate it a place where itās always within reach, or tailor the framework to your needs. If you enjoy drawing once in a while, why not? If you have no patience for 29872 different pen colours, why do it? If you want to write about your day with your partner in bullet points instead of coming up with a best-seller love story, who cares?
Procrastination. Journaling constantly nudges you to look back at your life and how youāve been spending your time and energy. That can be challenging and wonāt change. For starters, you might come to the unpleasant realisation that you self-sabotage, or that a certain relationship is fading away. If you are avoidant, you will most likely put off journaling often; not because of the method or routine, but fear of what you may find ā fertile soil for procrastination.
For pen & paperā¦ No backup. Some companies have tried, but whatās hand-written wonāt sync with a cloud server. You do carry the weight if traveling or taking it to work, and itās probably gone if you spill coffee on it. I, though, think the trade-off is worth it and havenāt looked back.
Final Takeaway š„”
I am all for simplicity, yet that didnāt keep my mind from boggling when I realised such a simple tool turned out to be a game-changer. Starting off was not easy, but the benefits showed up and kept me motivated ā a rewarding feeling I wouldnāt expect so hastily while building a new habit. Today, itās just effortless and natural.
Ultimately, I hope this stimulates you to try journaling in whatever way and to deem simple tools as helpful to uncomplicate and improve our lives.
Iāve been a VS Code user for years, but today, I am giving vim (motions & editor) another try. Why?
I love keyboard navigation, and vim motions invite you to use your entire keyboard not only to type, going beyond the Ctrl+Shift+Command+Fn+^+{+/ hell.
neovimās plugin ecosystem is GOLD for keyboard enthusiasts e.g. stevearc/oil.nvim.
Thereās a gap between my terminal and VS Code. No matter what extensions I throw at it, I canāt bridge it. Since I spend a lot of time in the terminal anyway, why not edit in it too?
Disclaimer: Not a beginner tutorial. Rather a (hopefully inspiring) diary of my vim journey. But if you're curious, I've dropped some learning resources below.
Today I learned
which vim editor?
Many editors support vim motions, including VS Code itself. Technically, I could just make my VS Code more keyboard-centric without switching editors. But right now, Iām exploring neovim, and learning vim motions across both VS Code and neovim. neovim is cute: small, fast, portable, extendable, widely supported, and not again owned by Microsoft.
vim kinda has 4 modes
insert mode (i key; also other keys, see āthe normal modeā): where you type and insert text, just like a traditional text editor.
visual mode (v key): where you select/highlight text visually, handy for copying/deleting/moving.
normal mode (esc key): where you navigate around the file, most of the time and most efficiently. Keys become āmotionsā and āoperatorsā that move the cursor and act on text (deleting, finding, replacing).
command-line mode (: key): execute commands on vim, mostly editor-related, e.g. saving files, exiting vim.
Traditional text editors offer ways to do the above in a permanent āinsert modeā, but vim separates that across modes. Many mistakes happen because youāre not in the mode you thought you were, it helped me that the ānormalā mode cursor looks different than the other modes.
the normal mode
Thereās nothing normal about the normal mode, so I will say again: in vimās normal mode, keys turn into āmotionsā (move you around the file) and āoperatorsā (act on text, e.g. deleting, finding, replacing). Think of it as a mode with permanently enabled āCmdā or āCtrlā keys which you use to move around in a regular text editor (I hope?).
creating new lines under the cursor (o) and above (O)
jumping to next word (w), end of the word (e), or previous word (b)
jumping around lines of code with gg (line 0), G (end of file), {line number you wanna go to}G, {N}j to go down N lines, {N}k to go up N lines
inserting before cursor (i), inserting after cursor (a), insert in the beginning of line (I) or end of line (A)
jumping to beginning of the line (0), end of line ($), or beginning of word (_)
replacing a char (r) or word (R), deleting current character (x), deleting (d) e.g. a line (dd), next word (dw), previous word (db), basically a lot of the commands Iāve already learned above
searching within a line with f(character), plus next (n) and previous (N) occurrence
undo (u), redo (ctl+r). Pretty damn important, you make mistakes all the time.
I practiced these commands in roughly that order, moving on once I felt mostly accurate, though still slow. It might seem like a lot, but itās easier when itās about muscle memory and not memorizing a cheatsheet. Once you start combining motions and operators, things get fun. For example: I already use j to move down, could 10j jump down 10 lines? Yes (first I tried j10 lol). Deleting 3 words backwards? d3b.
little vim config
Feeling a bit lost in my editor, had to change some things. I said earlier I was curious about the ecosystem, but now Iām a little overwhelmed. For now, keeping it minimal:
-- ~/.config/nvim/init.lua
+local o = vim.opt
+
+o.number = true -- Print the line number in front of each line
+o.syntax = "on" -- When this option is set, the syntax with this name is loaded.
+o.mouse = "a" -- Enable the use of the mouse. "a" you can use on all modes
+o.termguicolors = true
+
(By the way, neovim uses Lua for configuration, if youāre wondering where the good old vimrc wentā¦)
Back in my teenage years, I tried to learn vim and quickly gave up. Coding was already confusing enough, and I figured, āwhatās the point of typing faster if I donāt even know what to type?ā. Which was pretty wise, in hindsight. Pretty sure I peaked in wisdom right there.
Jokes aside (it was not a joke), Iām still far from hyper-productive on vim. But I wrote this blog post with it, felt focused and felt plenty of fun, which is productive enough I guess? Whether this is novelty, or the vim advantage, only time will tell. Plenty of people go from VS Code to neovim and then back again. Who knows.
Now, the text column width on this editor has been full screen since I started this post, and Iām on the edge of installing zen-mode.nvim. Just gotta figure out what is this lazy nvim vs. packer thing.
In the past three years, a wild mix of stuff dragged me away from writing. More time š³ offline ā°ļø, which was great. Then a demanding role in a small team, the chaotic grip of a global pandemic, increasing perfectionism, and a blossoming and ultimately collapsing relationship ā which all conspired to shake up my pursuits and thrust me into an introspective whirlwind. And as if that wasnāt difficult enough, I lost two yearsā worth of drafts in a backup blunder.
Whenever I attempted to restart, I found myself entangled in a web of what still resonated with me and what no longer did. But hey, listing more excuses would only scratch the surface. I recognize now, after seeing how little it takes for me to be back, that parts of me were simply in disarray. Yet, as I come together again, so does my motivation to reclaim what I enjoy, and make time for it despite the busyness and excuses.
So, last night, I did what I do best: I embarked on an in-one-sitting endeavor! I migrated this blog to Zola (a speedy static generator written in Rust), so this WeBpAg3 remains therefore static and snappy af, joining the <512 kB club. Letting my creativity flow with Tailwind, I gave my WeBpAg3 an extravagant-outrageous look, and made sure itās accessible. I rewrote my introduction like a million times. I sifted through my writings, organising and archiving some, and lo and behold!: I stumbled upon those lost drafts hidden away in the depths of my physical backups. Pretty thrilling. As a friend once told me, good things happen when good things happen.
Long time no see! It all feels quite nice, if you ask me. š
Slack comes with limited file storage, so you eventually run out of space. Deleting files isnāt easy though: there is no way to bulk delete them using the web interface.
Slack forces you to delete one by one.
And although Slack can force humans, it canāt force JavaScript. So JavaScript to the rescue!
Since the beginning of this year, Iāve created a lot of different boilerplates for projects. Working as a freelancer makes you challenge yourself everyday to find out what fits better while working. Currently, itās sometimes Stylus, sometimes Sass.
Stylus is flexible, and I love it. Sass isnāt, but itās cool anyway. Sometimes I find it hard to bear its inflexibility, though.
On GitHub, thereās a closed issue about multiline comments on Sass (a Stylus feature!), where I shared a solution for multiline Sass comments. A lot of people still donāt agree.
I just want people on community to know it, because it needs to be discussed.
Solution
Start writing the comment as if it were single-line (//), then just follow its indentation. Example.
// Multine comment
+ Indent the text
+ And this will be a comment too
+
Exploring the country where my surname came from and hacking collaboratively at Science Hack Day Vilnius!
I love to hack stuff, and, this year, Iāve been pushing myself to do more of that along with people.
Thatās how I found a hackathon called Science Hack Day, a weekend event with the goal of āmaking weird, silly or serious things with scienceā1 in collaboration with others. Although I missed the Berlin edition for just a few days after it happened in November, another event was about to come āĀ this time, in Lithuania, where my surname āGurskasā came from.
There it was the perfect replacement: the Science Hack Day Vilnius 2018 would be my great excuse to explore the country where my grandfather was born.
Right on the last minute, I got a bedroom in a cheap hotel booked, and my flight and event tickets ready. All set for the hacking adventure!
Welcome to Vilnius
Approximately 2 hours from Berlin by plane, there I was: Vilnius, the capital of Lithuania. A modest city, so small you can pretty much explore everything by feet.
Temperatures were more negative than in Berlin. Winter, and the city wasnāt the most colourful either, so the atmosphere was somewhat dark ā even though the snow was painting all buildings, houses, and streets in a shining white.
The cold was totally dismissible as soon as I met the Lithuanians, warm and welcoming people who seemed to lead a simple life.
Science Hack Day Vilnius 2018
A Science Hack Day is a 2-day event run by volunteers. Since itās a hackathon, itās pretty hectic and leaves you exhausted at the end. However, also since itās a hackathon, itās remarkably rewarding at the end.
These were my days!
First Day
Early on Saturday, I walked to Technarium, where the event would happen. Itās a laid-back and community-operated hackerspace in Vilnius, where technology enthusiasts work or co-work on their projects and share knowledge. My perfect habitat, sort of.
I found a seat in the middle of a diverse crowd of enthusiasts: kids, teenagers, and adults (in which you could also find scientists and professors). I had forgotten to adjust my clock to the local timezone when I arrived in Lithuania ā 1 hour ahead of Berlin ā, so I was kinda late and the talks on open science had already started.
With honestly no idea on how all thatād end up (a feeling Iām used to, since I always do unexpected stuff to myself anyway), I was watching the talks and telling myself that the worst that could happen was that Iād have no idea and no team, and would end up just exploring what others were building. It didnāt sound any bad at all! Being around creative people is always appreciated anyway.
After the talks, it was time for people to pitch about their potential projects. Most ideas involved Biology, Programming, Physics, Chemistry āĀ anything related to (science) hacking! One of the ideas, from a team of 3 guys, was to build an audio visualiser.
āWe need a Python engineer who understands some audio engineeringā, they said, in Lithuanian (thanks person who was real-time translating everything!). Luckily, in a beautiful coincidence, I love music, Python, and also have been playing with spectrum analysis for audio visualisation in the last year ā so I decided to take a shot and ask them to join the team.
They said they had no idea how to get the input from a microphone, and that they knew more about the hardware part, Arduino, and manipulating those machines in the hackerspace to come up with a cool design for our project. Iām just bad at things that require manual work that isnāt with the keyboard, so my manual help would be typing Python for 2 days on my laptop. They accepted it. So far, we had:
the idea;
an Arduino Nano;
a power supply;
long LED strip lights;
an acrylic sheet.
Since Arduino Nano isnāt powerful enough for that computation, itād be only used for data acquisition, and the spectrometer would live in our Python program in my laptop, computing the Fourier transform of the audio signals.
By the end of the day, we managed to get input from the microphone, analyse its signals in the frequency domain with Python, and start mapping that data to be sent to our Arduino over a serial interface. Some libraries we played with were: pyaudio, numpy, pyserial, matplotlib.
Second Day
Now with the clock correctly set (thanks to my friend that asked what timezone I was in, otherwise I wouldnāt ever know), I was on my way to Technarium again, walking over and under snow in that early Sunday morning.
A day in the Science Hack Day Vilnius was a day with Lithuanian hearty lunch, black coffee, and hard work around kind people. (By the way, if you ever end up there, try the kibinai ā I ate one filled with spinach and will never forget how it smelled and tasted.)
Most people there were Lithuanians and I didnāt know anything about their language besides ālabas vakarasā2 (āgood eveningā), so I felt like an outsider sometimes. My teammates and other Lithuanians in the event āĀ including kids ā, though, were friendly and spoke English flawlessly, and fortunately even translated some stuff into English for me.
Curious fact: A teenager at the event told me that my surname was "wrong" āĀ in Lithuania, single women get a different surname suffix, so my name should be Gurskaite ("skaite" suffix, instead of ākas). In Brazil, of course, they didnāt know that and only cloned my grandfatherās surname ā with the "kas" suffix, since he was a man: Gurskas.
More talks in the morning on open hardware and software. They introduced everyone to GitHub, and many people, even students, were already familiar with it. The importance given to open source was impressive! That made me really happy.
Time flew on the second day! We had got the data we needed, and the next step was to decide on what would be more fun: to map amplitudes from the maximum frequency to RGB values for all LEDs, or map each LED to a frequency and change its colour depending on the amplitude? We picked up the latter, and got our LEDs to blink.
One of my teammates was learning Programming. He told me he didnāt know what programming languages to really sit down and learn, as seen that there were a lot of them out there. True, and a nice question! I gave him a biased answer, of course: āgo for Python or JavaScriptā. My reasons? Way more fun. Besides beginner-friendly, those languages have the most interesting, welcoming and lively ecosystems I know these days.
We were running out of time. While 2 of my teammates were building the LED tower, the other and I were testing the code and trying to improve our algorithm, everything at the same time. Eventually, we got our LEDs to blink the way we wanted them to, and the clock pointed 18:00 sharp. Time for presenting!
Teams came up with a lot of cool things! Projects related to lasers, contactless payment systems security tests, shopping-cart-rocket launch (#SpaceXLithuania!), plant-watering automation, posters with LEDs crafted by kids celebrating the 100th year of the Lithuanian as an independent countryā¦ And ours, of course.
There were different category prizes, and we won as the Best Data Hack!
I got the honor to take home not just this LED-powered trophy below, but also a memorable experience I had the pleasure to share with people I didnāt know in a country I didnāt know.
The Hack Day ended with a science show by N2!Ā Lots of fun with liquid nitrogen and eating cookies at temperatures close to the absolute zero. My teammates, Physics students, knew a lot of the science behind that stuff so I got some extra explanations! (I have to say, though, that one of my greatest learnings of that day was to not to chew those cookies slowly ā they stick to your tongue in a TORTURING way.)
Itās always truly amazing to experience closely how creative and curious humans are! The event was awesome, well-organised, and, last but not least, fun. Organisers provided us all the materials (food included!), borrowing me even the single USB-C adapter they had!
Clearly, the only intent behind Science Hack Days is for people to share and learn openly. And that has been achieved just right.
Final words
Open knowledge is one of the most valuable things in this world. I have no doubt.
Iām happy to have picked such an eccentric travel destination for my weekend, and really grateful for everything I saw and everyone Iāve met on the way.
Lithuania was freezing, yes, but people were warm.
JĆ” existem especificaƧƵes garantindo funcionalidades incrĆveis para o CSS: variĆ”veis; uma nova sintaxe para media queries; nesting; novos seletores, valores e propriedades. E vocĆŖ pode usĆ”-las, hoje.
Sobre o que hĆ” de errado, serei sucinta, pois, para esse artigo, espero um pĆŗblico-alvo preguiƧoso e acomodado.
O que hĆ” de errado
ā¦em usar jQuery em 2015? O que hĆ” de errado em importar jQuery ao iniciar o meu projeto?
Analisando superficialmente, nada.
Mas isso tem dado brecha a uma zona de conforto profunda e, na minha experiĆŖncia, com raĆzes difĆceis de arrancar. Essa cultura se expande e transcende aquilo que lhe deu origem. Portanto, perceba:
Deve-se saber quando abranger uma visĆ£o holĆstica do projeto, e quando separar responsabilidades.
A separaĆ§Ć£o de responsabilidades se daria pela anĆ”lise dos requisitos da aplicaĆ§Ć£o e dos desafios gerados, que trazem consigo o que chamo de āsubproblemasā (necessidades que surgem durante a anĆ”lise do desafio), que devem ser solucionados separadamente. A visĆ£o holĆstica ajudaria a estruturar os componentes de forma consistente em um sistema, definindo uma arquitetura.
Falando de desenvolvimento front-end moderno (e, portanto, falando de front-end modular e de unidades encapsuladas e independentes, os componentes), essa separaĆ§Ć£o de responsabilidades torna-se ainda mais fĆ”cil! Vejamos, abaixo, alguns subproblemas que surgem durante a anĆ”lise de requisitos, apenas para exemplificar o que quero dizer quando trato a decisĆ£o de ferramentas como uma soluĆ§Ć£o para um subproblema.
Os exemplos a seguir nĆ£o explicam o front-end modular na prĆ”tica. Adianto, no entanto, ferramentas como Browserify ou Webpack, que fazem parte do tooling necessĆ”rio.
SoluĆ§Ć£o possĆvel: encapsular, no componente um mĆ³dulo como Reqwest e httpinvoke. VocĆŖ pode, inclusive, utilizar apenas o Ajax do jQuery (e nĆ£o o jQuery inteiro!).
SoluĆ§Ć£o possĆvel: Virtual DOM, que estĆ” embutido em bibliotecas como React e Mithril. Ou, se precisar mesmo do DOM, considere pacotes como qwery ou Dominus, junto com domready.
E se precisĆ”ssemos de Ajax no React, por exemplo? Este mau exemplo na documentaĆ§Ć£o do React importa o jQuery inteiro. Como vocĆŖ faria? ;-)
Basicamente? Tenha um conhecimento decente de arquiteturas front-end (sugiro abrir a mente com Flux, que jĆ” possui bastante materiais e implementaƧƵes da arquitetura disponĆveĆs), e nĆ£o um conhecimento aprofundado de MVC.
Lembre-se de que existem habilidades que a documentaĆ§Ć£o de uma ferramenta nunca_ te ajudarĆ” a desenvolver.
Com o tempo, vocĆŖ vai saber quando adotar um framework especĆfico em escala, quando optar por bibliotecas monolĆticas, e terĆ”, inclusive, seus preferidos a ponto de nĆ£o ter sempre que definir soluƧƵes possĆveis para subproblemas que aplicaƧƵes tĆŖm em comum.
(Em alguns projetos, vocĆŖ enxergarĆ” padrƵes, por exemplo: qwery, domready e lodash sĆ£o usados juntos frequentemente.)
Um dia, no entanto, suas ferramentas falharĆ£o, outras ferramentas se adaptĆ£o melhor Ć realidade de seus projetos, e, entĆ£o, o ciclo de anĆ”lise recomeƧa. E vocĆŖ jĆ” sabe como proceder.
De acordo com o que venho experimentando, desenvolver essa mentalidade tem retornado experiĆŖncias maravilhosas e, inclusive, gerado menos cĆ³digo legado. Basta apenas aplicĆ”-la Ć Engenharia de Software com bom senso.
ConteĆŗdo sugerido
Os complementos abaixo sĆ£o apenas para despertar a curiosidade em relaĆ§Ć£o aos conceitos apresentados neste artigo, e nĆ£o devem substituir o estudo necessĆ”rio para deixar de lado, na prĆ”tica, a ācultura jQueryā.
E, humildemente, o meu prĆ³prio blog, pois pretendo falar mais sobre arquiteturas de aplicaĆ§Ć£o e front-end modular (que adoro!) na teoria e prĆ”tica.
Se vocĆŖ entendeu a razĆ£o pela qual a ācultura jQueryā distancia vocĆŖ do seu papel, a mensagem foi entregue com sucesso.
O NOT significa que todos os bits do operando serĆ£o invertidos (0 vira 1, 1 vira 0). Parece inĆŗtil quando nĆ£o estamos trabalhando com nĆŗmeros binĆ”rios, mas as aplicaƧƵes criativas tornam o operador mais interessante.
let data = "2";
+const dataAsNumber = ~~data;
+
+console.log(dataAsNumber); // => 2
+
Verificar a existĆŖncia de um item no array
let women = ["Ada Lovelace", "Joan of Arc", "Marie Curie"];
+
+if (~women.indexOf("Ada Lovelace")) {
+console.log("Ada Lovelace was such an important woman!");
+}
+
O equivalente humano, utilizando Lodash (_), seria:
let women = ["Ada Lovelace", "Joan of Arc", "Marie Curie"];
+
+if (_(women).contains("Ada Lovelace")) {
+console.log("Ada Lovelace was such an important woman!");
+}
+
No geral, operadores bitwise, principalmente ~, | e &, possuem aplicaƧƵes interessantes e bastante criativas.
Quanto ao ~~, nĆ£o acredito que chegarĆ” a se popularizar como aconteceu com o !!, que converte para um valor booleano. Em anos, a prĆ”tica com til nunca se tornou realmente popular, talvez pelo fato de ser um operador bitwise ā e, portanto, pouco compreendido ā e ter casos de uso bastante excĆŖntricos.
Ficam Ć tĆtulo de curiosidade suas aplicaƧƵes bastante criativas. ;-)
A Saturday afternoon of May and a few square meters in Berlin were what a couple of people needed to openāĀ and voluntarily discuss how we impact the Planet to change and how those changes impact us. Topics ranged from radical solarpunk utopiaĀ to more down-to-earth and short-term ideas within our generationās reach today: musings about climate change awareness, sustainability policies for companies, traveling sustainably, tech tools for political change, and how to get out of our bubbles and active listen to other realities.
In this post, Iāll be sharing my personal notes on that engaging and constructive afternoon. There will be, also, references at the end of this post so you can keep yourself posted.
Pitching and picking topics for discussion
OMG Climate is an unconference, meaning that attendees proactively come up with the agenda and topics to be discussed. To kick it off, we got instructed to pitch topics for discussion thatād be prioritised also by ourselves into tracks, attended based off our preferences. Everyone was expected to have at least a certain knowledge, even if rather tacit, about the challenges weāre facing right now with the climate emergency.
These were the tracks of the first OMG Climate:
Track 1: āLow-carbon travelā / āGreen Mafiaā / āHow do you sleep at night? Coping with climate anxietyā
Track 2: āTech tools for political actionā / āCircular economies: Re-use and techā / āCompany sustainability policy templateā
Track 3: āSolarpunk, imagination and excitementā / āCO2 Offsets as an API and tracking carbonā / āClimate change awareness in developing countriesā
We had enough attendees for tracks to make for productive discussions. Listening and talking to one another, while facilitated by a volunteer, did the job on keeping up an constructive flow between finding root causes and ways to take action.
Iāve joined āLow-carbon travelā, āGreen mafiaā, and āClimate change awareness in developing countriesā, so these are the ones I have more insights about. Towards the end, we all got together to wrap it up, and I have to say: all tracks were interesting, so donāt restrain yourself to this post!
The following notes don't reflect directly what's happened or everything that's been said in the event, it's rather my personal perspective. They are also somewhat vague, but I hope you can benefit from them somehow.
Low-carbon travel
Air travel, even when occasional, has an environmental impact difficult to make up for no matter how many bamboo toothbrushes we gift our friends, how often we commute by bike or how vegan is our diet.
With low airplane ticket prices getting more popular than ever and enabling people to travel more, how can we make traveling sustainable when not traveling to begin with is not an option? That was the question we kicked off the ālow-carbon travelā discussion with.
Meeting notes
In our circle, everyone seemed to have access to the privilege that is air flying.
We began exploring traveling by breaking it down into traveling for work vs. pleasure.
Ground travel might be an option; however, itās rather time-consuming and hence less appealing in a capitalist society where time translates to money. How can we shift the paradigm?
Instead of seeing longer trips as wasted time, we should begin seeing the journey as part of the trip.
Traveling less: We often optimise our trips to visit as many places as possible; instead, we can optimise for depth and start going to fewer places for a longer time. Think: going to a European country and making the most of it, instead of going to 999 different countries just because they are 1-hour-flight away from each other.
Share practical solutions for people to make trade-offs, EcoCost rather than overwhelming scientific evidence.
What if companies supported employees whose carbon footprint is the least?
Green travel agencies and flying policies.
Search engines for flights obviously donāt suggest alternative ways to get to a place when a plane is definitely not the best option.
BVG app, on the other hand, recommends walking instead of taking public transport sometimes.
Transport apps could also order route options by the least environmental impact.
The car industry should be ashamed of its climate record.
The train industry is not modernised and integrated, rather rigid.
Investment on 10 km of autobahn could pay off the renovation for bike lanes all over Berlin.
Globalisation vs. environmental footprint: IT workers immigrating usually go back to their countries often since they have the need and resources. I asked whether there was data available on how that situation in particular couldāve increased our carbon emissions coming from aviation.
Business trips by train are possible only among those who have the privilege of a flexible work schedule, such as freelancers.
Making the most out of idle time: we tend to be more creative in idle times, while in a train; not hunching over a keyboard or in an office environment.
āFast-moving home/officeā as an alternative to turn the journey time into productive time.
Frequent flyer levy: A fairer tax system according to how often people fly. Those that fly more should pay more. (More information: A Free Ride)
Airline campaigns often promote the image that everyone should become part of a group of young, urban frequent flyers, visiting another city every few weeks for very low costs.
Action points
everyone to shift mindsets in regard to traveling.
everyone to vote instead of buying a bamboo toothbrush.
everyone to use and promote tools with different options of transport within a route, instead of blindly going to specific train or flight websites.
everyone to keep consuming local goods.
airline companies to stop promoting flying as a status symbol.
travel agencies to work out more sustainable ways to travel and consider it in their branding.
We should fight back! We mused about beating off lobby groups representing the coal, car, oil, electricity, and aluminium industries using their same sneaky techniques, as a Green Mafia. An intriguing and fun topic!
The brainstorming served as a tool to get a grasp on the way those mafias function, and discuss whether the ethical approach is always the way to go when facing a crisis.
Meeting notes
Leverage civil disobedience and tools of intimidation to influence green policies for the climate, fight extreme wealth and weaken existing mafias such as the oil industry.
How far should one go with non-ethical practices, such as blackmailing or public shaming of those who harm the planet?
Whatās ethics after all?
Could we use illegal money to fund our causes?
Could we use legal money to fund our cases? There are ways to get money from the state in licit ways such as from green parties.
What if we made the green cause as profitable for the mafia as oil?
Sell a belief system, or use an existing one such as āharmony with natureā.
Cyber hacking/hijacking internet algorithms to spread awareness instead of climate change denial and fake news as it happens today.
Coming from a developing country, I was looking forward to this topic! Apart from Brazil, we had people from India too. There was a range of issues that could be tackled within this track, such as the risk of massive displacements of people in developing countries, the need of support to adapt, environment destruction for the sake of economic prosperity, how to approach climate change education etc.
Meeting notes
We are building awareness, not āteachingā others about climate change.
Climate change is an existential threat to life, but it seems rather remote if you think about poverty, disease and economic stagnation. How do we educate children for the long-term if, for some of them, not showing up at school tomorrow means not eating at all?
How do we let them know about the risk of massive displacements of people who have no resources whatsoever to move?
Just by existing in a developed country in Europe, our carbon footprint is more impactful than any developing country.
Indigenous people are already defenders and protectors of the environment more than we will ever be in our generation.
Developing countries idealisation of economic development, influenced by ādeveloped world standardsā: tall buildings and industries all over the place, where often we donāt see the green implications of āsuccessā.
What about a model of development thats puts together the simple living of developing countries with the green development of developed ones?
We could shift the discussion to think about environmental impact in terms of social classes instead of countries. After all, rich lifestyles and āstatusā in general damage the environment in untold ways.
The Swadeshi movement brought back self-manufactured clothing in India to boycott foreign goods, a part of a movement to liberate India from British control and industrialisation.
When teaching, consider whatās in peopleās context, reach and language instead of whatās āout thereā.
We should actively listen more to those communities and whatās happening in those countries. Sometimes, instead of thinking that there is something to be taught, we should rather learn from their realities so we can bring about a meaningful conversation.
This is a problem not to be approached by technology, remotely. Itās rather about Politics and Education.
Action points
everyone to assure inclusivity, cooperation and engagement across boundaries, first and foremost.
countries to keep cooperating efforts internationally through policies, institutional frameworks for development and investments in infrastructure.
Conclusion
Well-led communities that strive for welcoming environments enable the best out of people. OMG Climate has shown that ā its unconference format got everyone to take responsibility and engage towards constructive and meaningful discussions about climate change.
Although most of us had a tech background, everyone seemed aware: tech alone will not solve all problems, but we are eager to address them either way.
React and Form Management: Is Redux Form Worth It?
This is an improvement over my answer to a question in a Brazilian forum: "is using Redux for forms worth it?", in Portuguese. It assumes previous knowledge with React and Redux, and also mentions Redux Form, a library for managing forms in React.
It depends.
I know āit dependsā is far from an interesting answer, yet thatās the perfect-generic answer to any āis using X worth it?ā question. It really depends, yes, but more often you donāt need that.
Last year I picked Redux Form to build a multi-step form wizard, each step containing different forms, with its own fields and validations (some of them asynchronous!). In the end, all forms would be merged into one JavaScript object to be sent at some point.
So, Iād like to share my experiences and hopefully help you to figure it out what your problem is, and help you to decide by telling you how Iāve solved mine.
Where Redux Form thrives
Redux Form is useful for larger and more complex forms where ease of development, high control (especially), consistency, and persistence (especially) are required. There are advantages from:
the state form being in the Redux store, and
Redux Formās abstraction itself.
Which are two different things. You might need both, just one, or none at all.
Yes, you could also get to build forms in a productive way with only React, but I think it's still worth-mentioning that Redux Form makes it really painless.
High control
You can manipulate forms from anywhere in the application: you trigger Redux actions provided by Redux Form and thatās all. No need to create your own Redux reducers and actions.
Redux Form is also flexible on what can be an input. Anything works as a field: custom 3rd-party inputs, a regular HTML input, a fancy select component without any standard form element at allā¦ Just pass the right props to it.
You can set up validation at the form and field level, supporting either synchronous or asynchronous validation. The errors triggered are also in the store āĀ which makes it sweet to give useful feedbacks for users from anywhere, and also to debug! š
Consistency
All forms have the same data structure so youād have the exact same information for every form and its fields, such as field values, field/form validity and further information (is the field touched? Pristine? Dirty?) in the Redux store.
Of course you can build forms consistently just by using React itself, but using Redux Form definitely enforces it.
Persistence
Since the state is already in the Redux store, Redux Form is easily pluggable with tools from the ecosystem.
Letās say you want to save drafts from userās inputs so people can finish and submit the form later. Redux Form + redux-persist make it pretty easy: the rehydrate process in the Redux store autofills the UI like magic!
Where Redux Form might die
In the thread, someone mentioned the article Redux Form is dead.TL;DR: It's not fucking dead, as any library, framework and whatsoever that has an "X is dead" post for it.
Letās not forget that the JavaScript community is flooded with āX is deadā articles for everything in the ecosystem. That post, in particular, mentions valid points to consider such as ephemerality of the state (quoting Dan Abramov), performance issues within Redux Form, and the project maintenance/activity. I will go through them a bit.
Form data in the Redux store
Dan Abramov, creator of Redux, said: āUse React for ephemeral state that doesnāt matter to the app globally and doesnāt mutate in complex ways. For example, a toggle in some UI element, a form input state. [ā¦]ā.
Which is completely accurate. Where your state should live in your app depends entirely on its ephemerality āĀ how trivial it is for the application as a whole when it comes to reading, updating it and so on.
In the post, that quote is used to support the claim that Redux Form fucks up when stores all form data in the Redux store by default ā a pretty bold design decision for sure.
However, Dan did not write that in stone ā he never does and heās clear about it. That should serve as an encouragement for developers to think better about where your applicationās states should go into. So, yes, you should think twice ā and that doesnāt kill Redux Form.
The state of a form wizard, whose input data persists until the end of the steps (in a session or local level, for instance), whose inputs may trigger UI changes, whose inputs gets touched and changed by external components, itās definitely not as ephemeral as the state of a newsletter sign up or a contact form. In the former, the form state is important for the whole application. Just notice thatās a very specific case.
When it comes to performance, though, you should never rest easy anyway. If you measure and find that your forms are slow, you should find bottlenecks and optimise from that.
Project activity
Regarding the project activity, it is something to consider when deciding, and should always be. Is it active? Are there people maintaining it? Can YOU help to maintain it?
Yes, Erik (the author) has recently started working on another solution called Final Form, which moves the form state out of the Redux store. However, Redux Form is mature, still well maintained (check GitHub, and he even said it himself on Reddit), and its documentation is great.
Final words
Only if the state of your form is non-trivial enough to live in the Redux store, Iād give it a chance for Redux Form, especially if you are considering making your own solution. Redux Form has suffered and evolved a lot and nowadays it has a very stable and mature API you can count on, Iād say.
Other React form management solutions you should definitely be looking at are Formik and react-final-form, by Redux Formās author. They donāt rely on Redux for state management and are most likely what you need now āĀ or not.
The price is the abstraction, of course, it always is. š However, their everyday API is indeed minimal though, just be prepared to go through the documentation when you need to achieve specific stuff. In return, donāt forget youāll get a consistent and solid structure to build forms upon.
Because it assures consistency throughout the project and avoids magic numbers, sharing variables between JavaScript and CSS code may help you to keep your project codebase tidy and easier to reason about.
No magic is needed to use those variables in your JS filesĀ ā just import them when you need it. But in order to communicate those variables to your CSS files and use them with var(), some magic is needed.
For this, I will be using cssnext, a PostCSS plugin, and injecting that object into our stylesheets as custom properties.
import MediaQuery from "react-responsive";
+import { customMedia } from "./variables";
+
+function DesktopOnlyComponent() {
+/* (min-width: 1024px), according to variables.js */
+
+return (
+ <MediaQuery query={customMedia.desktop}>
+ <p>My desktop-only component!</p>
+ </MediaQuery>
+ );
+}
+
Final Words
A non-consistent front-end codebase is just messy.
I really use this technique on everyday work, and itās a cheap way to significantly improve the quality of the front-end codebase.
So, donāt underestimate it! Besides breakpoints, there are infinite possibilities for this, such as project colors, layout dimensions and other shared stuff that can easily get out of hand while working on a large project.
Sometimes, we donāt want all of our SVG files to be loaded as React components. If you use a SVG in a img element, for example, it may lead to conflicts. Fortunately, you can avoid them by being more specific in test regular expression:
A memĆ³ria parece distante agora, mas nĆ£o faz muito tempo que eu tive essa conversa. 30 de MarƧo de 2016. JĆ” faz um pouco mais de um ano. FalĆ”vamos de indecisƵes, insatisfaƧƵes e mudanƧas, quando sonhos vieram Ć tona.
Sonhos. Pessoalmente, penso neles como desejos fixos que habitam a nossa consciĆŖncia junto a outros desejos, mais efĆŖmeros, e que, assim que vocĆŖ os deixa de lado (nem que seja um pouco), inconvenientemente voltam a te atormentar; lembrar que eles ainda estĆ£o lĆ” e nĆ£o sĆ£o como os outros desejos.
Iām personally very happy to say that after everything weāve heard and seen, we think youāre a great match for us and would love for you to join our team here in Berlin.
([ā¦] Pessoalmente, estou muito feliz de dizer que, depois de tudo que nĆ³s ouvimos e vimos, achamos que vocĆŖ tem tudo a ver com a gente e gostarĆamos que se juntasse ao nosso time aqui em Berlim!)
O que seria para sempre o meu foco, o desejo que eu descorri por 30 linhas no meu LG R510 em uma carta de maio de 2012, aquilo que eu nunca havia tirado da mente, naquele momento surgia como uma oportunidade. Eu topei.
Foram vĆ”rios passos antes disso, e eu lembro de estar ansiosa antes de cada um deles. Encontrei pessoas maravilhosas durante o caminho, com um coraĆ§Ć£o tĆ£o grande como o meu. Tanto na vida quanto nessa entrevista em particular.
Just got the call! [ā¦] Thatās an important moment of my life for sure. Iām just, you know, happy. Thank you for this.
The call. A ligaĆ§Ć£o se referia a do Consulado Geral da Alemanha de Porto Alegre que recebi no dia 8 de maio, dizendo o que esperei 2 semanas (ou toda a minha vida?) para ouvir. O meu visto estava aprovado. Ali estava, sem dĆŗvidas, um momento importante da minha vida.
Hoje estou voando para Berlim, a capital da Alemanha, para fazer o que amo na HelloFresh, que me ajudou em todo o processo. Sou grata por isso, por tudo.
A few years back, I jumped into the world of ebooks to broaden my reading without stacking so many physical books. I went with the ever-popular Kindle; yet the full weight of āowningā ebooks, particularly from Amazon, was not something I understood.
ā¦Until I decided to break up with Amazon, despite its convenience. You know the drill: Amazon exploits workers, aggressively avoids taxes, dominates markets, and I was just itching to explore alternative bookstores. The hiccup? My Kindle was firmly rooted and entangled in Amazonās ecosystem. Without Amazon, I could no longer conveniently or legally read books on my Kindle, and without Kindle, I could not legally read books I once purchased on Amazon.
Hereās what Iāve learned while attempting to part ways.
It all begins with āDRMā
Digital Rights Management (āDRMā) might not be a household term, yet its fingerprints are everywhere. Ever wondered how we consume content via proprietary software, rather than owning the content?
Think Spotify (you never own the music), Netflix (you never own the film), Adobe Creative Cloud (you never own the software), Steam (you never own the game), and Amazon Kindle (you never own the ebook). You download those proprietary software on your device, not the content itself. While you may have a license to the content, but itās not truly yours.
The use and distribution of the copyrighted content provided by those services (and many others) are restricted by DRM (āDigital Rights Managementā) technologies, implemented in various ways, increasingly restrictive and controversial. While DRM aims to address the legitimate need of copyright protection, it fundamentally reshapes the landscape of intellectual consumption, often at the expense of user privacy and freedom. For example:
Content Sharing: DRM often limits, or restricts altogether, the ability to share, lend and gift content outside of the same ecosystem.
Content Portability: DRM can authorise content to only a specific set of devices or apps, and restrict the supported file formats (even to a proprietary format). That limits content migration across platforms, technologies and devices that better suit you.
The points above reveal an alarming side-effect: dependency on the ecosystem, or "vendor lock-in", which is detrimental to individual freedom and market competition. When content is tightly bound to the platform, disengaging becomes challenging. And when you're limited to sharing only within an ecosystem, your social circle gets roped in too. Kinda seem like cute digital mutualism until it's a toxic relationship you can't leave.
Content Perpetuity: DRM cannot guarantee perpetual access to content. If a service or platform discontinues the content or themselves entirely, you may simply lose what you purchased. In fact, that has already happened, more than once or twice.
Content Geographical Restrictions: DRM can prevent access to certain content based on location. With the internet alone, we could technically provide equal access to cultural and educational resources ā DRM kills that.
Content Offline Access: DRM often requires online authentication or periodic online checks. Not very nice in low connectivity areas or during travel.
All those āside-effectsā (given they are actually unintended š) of copyright protection through DRM conveniences corporations. Corporations may not only protect their profit but also actively profit through DRM, charging high customer cost while delivering zero customer value.
Finally, because DRM implementations vary so much, itās nearly impossible to determine your rights without diving into lengthy terms of use agreements. The restrictions are rather obscured by clever marketing ā youāll soon see.
Leaving Amazon, and failing
Do you still remember I was trying to break up with Kindle? I get too hung up sometimes but letās not forget why weāre both here, right!!?!
First things first, let me make it clear ā I did not want to give up ebooks. Itād been a pleasure to be able to dive into new literature and keep only the gems in my bedroom bookshelf. And I could also carry a multitude of stories effortlessly during my travels.
Secondly, I had no intention of trashing my Kindle. It was a fully functional piece of hardware, and it worked well.
So here was my grand plan: Iād log out of my Amazon account on the Kindle, and source my ebooks somewhere else. Seems pretty straightforward, right? But the hurdles kicked in right from the very first step.
As it turns out, signing out of my Amazon account meant every single piece of content Iād ever acquired through Kindle would vanish into thin air. On Kindle, your books are tied to your Amazon account.
That was an unforeseen repercussion. I naĆÆvely expected to hold rights over books Iād purchased regardless of whether they were digitally or physically distributed. So I was disappointed and surprised ā with myself, the state of things; both. And yes, I clearly had not read Kindle terms of use back when I got into the ecosystem (otherwise you wouldnāt be reading this! š).
FINALLY reading Kindle Terms of Use
The latest Kindle Store Terms of Use (Last updated: November 30, 2022), determines a set of restrictions you buy into when you decide to buy Kindle and Kindle content, DRM-protected or not. The āUse of Kindle Contentā section states a couple of DRM-ish things:
ebooks are meant to be consumed only on Kindle, or Kindle apps.
Upon your download or access of Kindle Content and payment of any applicable fees (including applicable taxes), the Content Provider grants you a non-exclusive right to view, use, and display such Kindle Content an unlimited number of times (for Subscription Content, only as long as you remain an active member of the underlying membership or subscription program), solely through a Kindle Application or as otherwise permitted as part of the Service, solely on the number of Supported Devices specified in the Kindle Store, and solely for your personal, non-commercial use. [...]
when you click āBuy Nowā1, you are actually buying a license i.e. renting.
Kindle Content is licensed, not sold, to you by the Content Provider. [...]
Coming from DRM-based services like Spotify or Netflix, where you subscribe for access to a collection of music or film, the Kindle model might be a surprise.
Within the Kindle ecosystem, you are able to buy individual content, which does evoke a stronger sense of direct ownership. Yet, when you do so, youāre essentially obtaining a license: every ebook is an one-off payment to a mini-subscription. And that was absolutely not straightforward or intuitive to me.
you may not lend or sell your ebooks.
Unless specifically indicated otherwise, you may not sell, rent, lease, distribute, broadcast, sublicense, or otherwise assign any rights to the Kindle Content or any portion of it to any third party [...]
your books might disappear anytime.
We may change, suspend, or discontinue the Service, in whole or in part, including adding or removing Subscription Content from a Service, at any time without notice.
(Funny enough, I checked Wayback Machine and noticed that one was amended around March 2015, after reports of disappearing ebooks years before. š¤·)
ā¦And embracing the sacrifice
Delving into the Kindleās terms brought the truth crashing down on me: I never really had a choice to transition away from Amazon while retaining my content. Severing ties with Kindle came at a cost I hadnāt anticipated, and I felt very exploited for it.
Some might argue I actually had the āchoiceā to enter Kindleās ecosystem. And sure, itās true ā I did it willingly, no one coerced me into becoming a Kindle user. But, hey, thereās a nuanced reality here you canāt brush aside: we make our individual choices within systems. Thereās an entire environment lying behind the notion of individual choice.
Systems can be designed to subtly exert control or exploit personal choice in ways that arenāt always apparent. You canāt look at individual choice alone overseeing the environment in which those decisions are made. In no defensiveness, blaming on individual choice is, I dare to say, exactly how exploitative systems maintain their facade of legitimacy. And I donāt think being exploited or not should be a choice to be made.
Yeah, a bitter pill to swallow, but a new plan has to emerge out of my anger: to log out of my Amazon account, and therefore leave books Iāve purchased behind, and use Kindle only as an e-reader, not a shop.
Leaving Amazon, and failing less
After logging out of my Amazon account, Iām left with an anonymised Kindle (I hope). At this point I wonder if I even have the right to keep the hardware Iāve purchased, but so far nobody hasnāt taken it away from me. š So, how can I rebuild my e-book library?
Using Kindle with other bookstores
Before buying ebooks elsewhere, one needs to understand what file formats are supported by Kindle. The file formats supported by Kindle are MOBI, PRC, PDF, and primarily the proprietary AZW, and the files may or may not be DRM-protected depending on the publisher. Only Amazon sells AZW books2. So my options are:
MOBI. But no bookstores sell them these days.
PDF. But formatting sucks for reading books.
PRC. I donāt know what that is.
So I have no options. \š/ Bookstores sell EPUB books, an open standard well supported by all e-readers in the market but Kindle. Fortunately, you can manually convert EPUB books into one of the Kindle-compatible formats above. Unfortunately, if the book is DRM-protected (very likely!), you would need to strip out DRM before conversion which is downright illegal LMAOOOOOO!!!!! This drives me CRAZY, but letās move on.
For ebook format conversions, Amazon fortunately offers Kindle Previewer, a publishing software, but itās just a little too bloated for my goal. So I went with Calibre, a free and open source e-book manager that does it all. It works wonders!
If you keep your Amazon account, importing EPUB into is easier with Send to Kindle. It's a more convenient option but it often messes up with the book formatting.
Ultimately, using non-Amazon ebooks on a Kindle device can involve various technical and legal considerations, especially when dealing with DRM-protected content. DRM-free book shopping is also limited ā DRM is an industry standard! So using a Kindle without Amazon is not just very inconvenient, itās barely legal. š
The most promising plan seems to be tossing Kindle altogether, and choose an open standard e-reader with less hostile DRM platforms, but thatās for another time.
Amazon caters for publishers, not consumers
It all makes sense when you put it all together. When traditional publishing giants contemplated the world of e-readers and online stores, they had to be a bit careful about it. With physical distribution, they already had a model that offered a clear sense of ownership and control. Then, remember the music industryās digital transformation, marked by piracy and revenue decline3? Obviously publishers would be wary of a similar fate.
But in comes a compelling offer from Amazon: a tight grip on digital ownership of books, and a shortcut into an already profitable book marketplace. All or nothing. A captivating promise of control and access which publishers, late to digital transformation, did not pass up. And so seamlessly, Amazon paved the way towards market dominance. š
Today, Amazon also positions itself as a platform for emerging writers and attracts independent publishers. So does Spotify for musicians, and Steam for game developers. For both publishers and consumers, content discovery is whatās great about such platforms, despite their license model.
Alternatives like Bandcamp (music) and GOG.com (games) also promote publishersā content. In contrast, their DRM-free4 model ethically caters to both consumers and publishers: the consumer has direct ownership to content, and publishers get their content secured, even earning more5. How does that work? Fingerprinting content files (i.e. watermarks), but above all, cultivating consumer trust and transparency, and a sense of community and support for artists.
Final words
While writing this, an analogy came to mind.
Picture when you buy a physical book from a store. You know that book will patiently await you right where you left it and not vanish into thin air, whether you frequent the store or it eventually shuts down. That store is unaware of your identity. It doesnāt know when you open or close the book, nor does it know which passages youāve highlighted. You can even lend the book to a friend, regardless of whether they shop at the same store or if the store recognizes them. And that both of you can go buy books elsewhere later with no strings attached.
But I know thatās kinda corny. Itās an oversimplification. Digital content IS different, and copying files is far easier technically than producing physical copies. We do have new challenges.
Yet, while the analogy might not outright invalidate DRM as a solution, it can serve as a reminder of the current asymmetry of our digital rights today. A nudge to the way our essential rights are exploited within the current framework of digital copyright protection. And, ultimately, it extends an invitation to reimagine it from the ground up. Perhaps looking at how other platforms like Bandcamp have already done so brilliantly, perhaps radically starting at copyright itself.
Keep reading
ā¦on how despite massive technical effort and corporate interest, DRM is a flawed security model.
A cloudy day 1 of Autumn in Berlin, probably something else in the place you live, and youāve read the same date twice and this introduction actually doesnāt matter. But let me tell you about something that matters.
Everything is made up of <div>s and <span>s again, utterly hidden behind abstractions proudly called components. No one seems to remember (or do they?) the difference between p and span, let alone the point of using section rather than div.
Bad decisions ā to not just to say bad and even invalid HTML markupĀ ā are buried in components developers find awesome to compose user interfaces with. The web, and people, pay the price.
Creating components
From now on, to explain my point, I'll be assuming some familiarity with React (a JavaScript library), although this applies to any kind of component abstraction.
Letās say you just started a brand new React web app. You need to create a button at some point, and, because itās reused in other parts of the app, has custom styles and also a fancy icon, you decide to introduce a component with all that abstracted out. Nice! You could do it like this:
The user interface is then composed as the following:
<h1>Brazilian Bananas (1 kg)</h1>
+<p>Sweet and healthy bananas!</p>
+<p>Absolutely the best.</p>
+<Button onClick={() => alert('š')}>Buy $0.99</button>
+
It looks good! You were born for this, werenāt you?
Quite easy to miss whatās wrong when components are just used like that. A button, isnāt it? The engineering team can easily grasp what that means and what that does, after all.
It could also be a <FormLabel /> or <Paragraph /> as span elements, or divs all over that place. Although they all work, mistakes are abstracted in components.
I specifically talk about markup as the mistake throughout this article, however it could be anything really. Components look inoffensive when you're using them.
The web isnāt your abstraction
Now that HTML is all abstracted through JavaScript libraries and frameworks (which is not wrong), I wonder whether developers only went for semantic elements for the sake of making markup more readable for themselves. With React, your <Header> now may be a div. Out of the abstraction, though, youād think twice before going for a div to make a headerĀ ā youād rather use HTML5ās header.
Because of the abstraction, output markup isnāt something we talk that much about anymore.
Did we really get the benefits of HTML5 and why new elements were introduced? Why button? 2 Whatās header useful for? Why should one use section at all?
By the way, do you know how many occurrences of header, article, section I've found on Netflix's landing page? Zero. It's all div soup.
Matter of fact is that browser engines and people ā nothing less thanĀ the ones who you really write code for ā wonāt ever know about your abstractions. A screen reader wonāt know your ābuttonā is actually a button3. (They will definitely get to know the span though, and that wonāt help.)
Also, itās never been easier to write invalid markup without even realizing it! After React, it seems acceptable to place a button inside an anchor link, and even giant elephants inside span. Has anyone ever thought why they are considered invalid markup in the first place?
Donāt make it hard
Browsers and assistive technologies are smarter than ever4, indeed, yet they still count on developers to write code they can understand and people can benefit from. By doing so, you make it easy for:
people, who will be able to navigate around the website, skipping over navigation sections or quickly jumping from one article to another5.
yourself, so you donāt have to reimplement default browser behaviours.
Therefore, please: donāt waste features that technologies try to give users, and developers, out of the box.
Remember who you write code for.
1
If I had managed to publish this yesterday, the day would be sunny. Iāve missed the opportunity to make the article seems a little happier.
2
The button element was first introduced in HTML4. (Source)
3
Whatās wrong with using a non-semantic element as a button? Well, if the button is accessible, nothing really. But doing so demands extra work that nobody is up for, besides that fact that you canāt actually create a button.
4
Technologies may even process <span class="tel">123-456-7890</span> as a telephone, and allow for automatic dialling of it. See microformat for more information.
5
Why not, right? After all, articles are for independent pieces of content, e.g., an user-submitted comment or a forum post. (Source)
Still do it? Iām flattered to tell you that you donāt need that extra variable anymore.
Arrow functions
Go with arrow functions instead. Besides having a shorter syntax, arrow functions bind to the parent scope by default.
The scope that was firstly intuitive to you will work as expected now.
function Requester(data, req) {
+this.data = data;
+
+req.done(() => {
+console.log(this.data); // intuitive as hell!
+ });
+}
+
You can count on them most of the time, but they also have unexpected behaviour in more advanced cases. After all, you're dealing with the `this` keyword. So don't just go around refactoring all anonymous functions into arrow ones and expecting everything to work.
You may also .bind()!
If for some reason (such as no support for IE) you canāt use them, check JavaScriptās bind. Itās not as awesome as arrow functions, but does the job.
We misunderstand learning. We think learning happens as we consume information, so we insist on consumption, hoping it will make sense. Reading sparks new ideasāyet often we merely seek out validation for the ones we already have. We misunderstand learning. We cling to theory like a lifeline, as though it can stand on its own, while overlooking the experimental space where it transforms: practice. Perhaps we gamify it. (Unlearning our addictions is another matter entirely.) We escape the confusion that must lingerāit slips us that lingering isnāt forever. We misunderstand learning. Through edutainment, we satisfy the illusion of smooth progress, estimated reading times, chapter after chapter. True learning is too disjointed, unpredictable, and fraught with setbacks. We obsess over minimising gaps between repetitions, but are these gaps learning breaks, or learning itself? I recall the first time I picked up a guitar: my fingers aching to stretch, shredding like crazy against the strings. The morning after, I played the chordānot through conscious effort or passion, but because my fingers developed dexterity and calluses overnight. We misunderstand learning. Technique matters, yes, but some processes of embedding patterns are handled by our bodies in their own time. Others always seem to have it easier, so we feel ashamed. I wonāt lieāsome do have it easier. But most often we donāt know, we werenāt there to see behind the ease, and nobodyās quite vulnerable these days.
We misunderstand learning, but once, we were in intimate touch with it. Back when we hadnāt yet been subjected to environments of comparison, deadlines, narrow molds, and had our complexities and neuro-diversities amassed into pure functions. Iām still not immune to this. At times, learning as an adult feels like a endless chase of the instinctive dance of curiosity it once was. Throw at it: Pomodoro timers, habit trackers and productivity hacks. Yet, itās only when I sit down to an unmysterious learning practice and truly welcome confusion, chaos, and seeming non-productivity that I feel like I can dance with curiosity again, and learn.
Your teammate worked on a few improvements in all forms of the companyās website. At some point you, also a programmer, are asked for a code review.
This is the feature branchās commit history you get in the Pull Request:
[290xx26] Resolve merge conflicts
+[9efxxf2] Refactor event listener for form fields
+[5d9xx5a] Update snapshots
+[948xxfa] Update dispatch event
+[f5xxea1] WIP
+[f8xxaae] Revert change
+[49xxf55e] Revert changes
+[02xxdf1] Update snapshots
+[21xx329] Pass down prop
+[28xxa865] Fix onChange event and add minimal design in form
+[cfxx37c] U[date snapshots
+[cfxx36c] Update form to handle onChange event for autofill
+[242xx25] Fix another bug with onChange
+[f7xx738] Update form component
+[09xx868] Update snapshots
+
It seems like a lot, when actually those improvements are simply 1) fixing a bug with event handling and 2) introducing a minimal style to them. It just that it takes time to visualise that.
Indeed, committing often to a branch is a good practice1 and commits are supposed to be low-level rather than huge. However, a commit is applicable when you have a meaningful, self-contained batch of work to log to the history āĀ and updating Jest snapshots is not it.
How about the following history?
[9efxxf2] Refactor event listener for form fields
+[cfxx37c] Add minimal design in form
+[cfxx36c] Update form to handle onChange event for autofill
+
That history communicates in a clear way what in the codebase has been changed in order to get the improvements done. If you want to know how itās changed, itās just a matter of checking out a particular commit.
Why a clear history matters
Apart from facilitating code reviews, since reviewers could grasp the context of the changes right at the first glimpse, a clear Git history is healthy for the project.
When commits started to reflect oneās workflow rather than the work done itself, the history turns into a mess of both meaningful and meaningless logs, hard to navigate through and undo changes (since commits are ācheckpointsā of work). Itās highly likely that, as time goes by, developers will stop caring about the source code history as the powerful resource it is.
*The final Git history should reflect your work not the way you worked.
You begin to lose the benefit of source code management with a messy history, which was supposed to reflect how the codebase evolved over time.
A better relationship with Git
There are very common comprehensible reasons ā yet not excuses at all! ā for developers to unnecessarily commit. I can think of:
āI had to update snapshots/fix unit test/code formatting/a typo in something I introduced.ā
āI had to merge master.ā
āI wanted to save my work.ā
āI donāt necessarily follow a clear flow ā I am productive when I work in iterative way and usually do a lot of things at once.ā
They can all be worked out by developing a better relationship with Git itself. That might take a while at first, but when itās part of your daily workflow, you barely think about it at all. (I promise!)
First, letās talk Git rebasing
Git rebase is a very powerful tool to reorganise your commits. It does a lot, so I wonāt get deep into it.
The command git rebase has an important tool you should get comfortable with: interactive rebase. Letās say we want to reorganise the latest 3 commits:
git rebase --interactive HEAD~3
+
HEAD points to the current branch in your Git repository. You can use @ as an alias as well: @~3, or the commit hash.
Interactive rebase will provide you a text interface with the list of the commits (in this case, within the range HEAD~3..HEAD) that are about to be rebased and actions you can apply to them:
pick [242xx25] Fix another bug with onChange
+pick [f7xx738] Update form component
+pick [09xx868] Update snapshots
+
+# Rebase 242xx25..09xx868 onto 242xx25
+#
+# Commands:
+# p, pick = use commit
+# r, reword = use commit, but edit the commit message
+# e, edit = use commit, but stop for amending
+# s, squash = use commit, but meld into previous commit
+# f, fixup = like "squash", but discard this commit's log message
+# x, exec = run command (the rest of the line) using shell
+#
+# These lines can be re-ordered; they are executed from top to bottom.
+#
+# If you remove a line here THAT COMMIT WILL BE LOST.
+#
+# However, if you remove everything, the rebase will be aborted.
+#
+# Note that empty commits are commented out
+
pick just means that commit is included. It's the default.
Editing that file (either by applying actions to commits or reordering them) and closing it will reapply those commits to the branch. Weāll explore some scenarios where that is useful.
Rebase instead of merge
The branch that you branched from has been updated (letās call it master), so you need to fetch latest changes and merge that into yours with git pull. Instead of merging and introducing an ugly new commit for that, you can rebase and pretend that nothing ever happened in the first place.
git pull origin master --rebase
+
"Why isn't that the default then?", you might ask. I'd guess they didn't want to make a feature that rewrites history part of the default behaviour.
Squash commits when you can
You need to fix a typo, update a test, or include anything else that should have actually been part of a commit previously introduced. You can create a new commit and later squash it to the initial one with rebase.
git commit -m "Update contact form tests"
+git rebase -i HEAD~2 # act on top of latest 2 commits
+
Interactive rebase will show up, and you can mark that āUpdate contact form testsā as the commit to be squashed into a previous one by changing pick to s (squash).
The squashed commit has to come exactly before the commit you want to squash into, so you might have to some reordering.
Fix up and save time
Using the --fixup flag along with the commit hash of the previous commit will mark a commit as a fix of an existing one. Then, when you rebase with --autosquash, they willā¦ well, automatically get squashed.
Letās say we have fixed a typo in the commit i2r923:
git commit --fixup i2r923
+git rebase --autosquash 9ef00f2 # one commit before above
+
You can configure Git to use the --autosquash flag by default when rebasing. I do that so you can check my dotfiles if you're curious.
Quite often, youāll know how far youāre traveling from the current commit (HEAD). Instead of specifying hashes, you can just use HEAD as a reference to previous commits:
git commit --fixup HEAD # fix 1 commit before HEAD
+git rebase --autosquash -i HEAD~1 # squash latest 2 commits
+
Stash to save your work in progress
You want to check or change other branchās files, but donāt want to commit unfinished work either. You can stash your work in progress (āWIPā):
git stash
+
That stores everything from your working directory into stash. Itās so useful in my day-to-day work that I honestly often cry using it.
On how to get your work back, name your WIPs, or stash specific files, refer to the docs on Git staging. No way I am better at explaining than the documentation itself!
Commit selected chunks of your work
Remember the āI work in a very messy way, iterating between featuresā excuse? This helps. (It helped me yesterday when I refactored and introduced something new to it ā should not be done altogether!Ā āĀ at the same time without noticing.)
Besides only adding a specific file to your commit with git add, you may want to add only a chunk of the fileās code to a commit. That can be achieved with the --patch flag:
git add --patch
+
Thatās another interface youāll have to get comfortable with. You can also try out its --interactive option.
Using VS Code?
VS Code has a powerful built-in Git editor that allows you to add chunks of code to a commit. To stage specific lines to commit later, open VS Codeās Git editor, select the lines of code you feel should go into a commit, and āStage selected changesā by right-clicking on it.
The Command Palette also has a āGit: Stage selected changesā option.
Rename commit messages for meaning
You had a look at the final history and found out your commit messages need some love. To change your latest commit (HEAD), you can just do git commit --amend; for other commits, youāll have to rebase.
Letās say you want to fix the latest 5 commits:
git rebase -i @~5
+
That will open up the interactive rebase youāre already familiar with. Find the commit you want, change pick to e (edit), and save and close the file; after Git rewinds to that commit, edit its message with git commit --amend, and run git rebase --continue when youāre done.
Make sure that your branch has got a clear, readable and meaningful historyā¦
git log --oneline
+
Then push it into the remote repository!
git push origin head
+
If you have already pushed (Y THO???!), you can (carefully) use the force option (-f) to rewrite the remote history.
Extra: Fixing the first history
Remember the first history? We can fix it. Itās definitely harder to change it after itās done, but totally doable with rebase -i. A possible solution would be:
squash [290xx26] Resolve merge conflicts
+pick [9efxxf2] Refactor event listener for form fields
+squash [5d9xx5a] Update snapshots
+squash [948xxfa] Update dispatch event
+delete [f5xxea1] WIP
+delete [f8xxaae] Revert change
+delete [49xxf55e] Revert changes
+squash [02xxdf1] Update snapshots
+squash [21xx329] Pass down prop
+pick [28xxa865] Fix onChange event and add minimal design in form
+squash [cfxx37c] U[date snapshots
+pick [cfxx36c] Update form to handle onChange event for autofill
+fixup [242xx25] Fix another bug with onChange
+squash [f7xx738] Update form component
+squash [09xx868] Update snapshots
+
Be mindful about your decisions and make sure you are not losing work along the way. I deleted commits unused commits (WIP then reverted), squashed āfixā and āupdate testsā commits, and then picked only those that are meaningful batches of work.
I could have also split Fix onChange event and add minimal design in form into two separate commitsā¦ But thatās for a future post.
Final considerations
Nowadays, I can say for sure that Git helps me to work better. Those techniques youāve learned are all part of my daily workflow.
There is always something I donāt know about Git though, so I keep exploring. I recommend you do to do the same, and you can start right from your command line:
git help -w reset
+
Finally, if somehow you donāt feel comfortable with moving around your work from the command line, Iād recommend Git GUI clients2 ā they are powerful and simplify visualising branches and its commits, especially when it gets tough3.
I hope you have better, more sane, work days after that!
It will get tough, because source code management is not easy. Anyhow, itās always tougher when you care about things anyway. Easiest thing is not to care about anything at all.
Iām a big fan of writing. Iām also a big fan of using my code editor and Markdown for that!
Code editors are usually packed with a bunch of useful features, such as multi-selection, syntax highlighting, a file tree easy to operate, and sometimes even Markdown supportĀ ā which I need for writing my articles, notes, to-do lists, and absolutely everything I can write using Markdown. I love having a consistent workflow and thatās crucial to me, so why not?
After configuring my editor of choice, VS Code, to get rid of the coding mode clutter (and also after an important update on its zen mode ā¤ļø), Iāve finally achieved a totally distraction-free writing experience!
Setting up the āWriting Modeā
1. User Settings
There are some important details to achieve total focus on writing. No line numbers, word wrap enabled, comfortable line height, no rulers, are some of them.
Since I only write in Markdown, I only set up those settings (and other tweaks) specifically for that language.
// github.com/diessica/dotfiles/blob/master/vscode/settings.json
+{
+....
+
+"[markdown]": {
+// force centering in zen mode
+"zenMode.centerLayout": true,
+// use the beautiful duospace font when available
+"editor.fontFamily": "iA Writer Duospace, monospace",
+// enable word wrap, since horizontal scroll while writing isn't human
+"editor.wordWrap": true,
+// i don't need line numbers, i'm not coding
+"editor.lineNumbers": "off",
+// light by default, but can be easily toggled to dark
+"workbench.colorTheme": "Default Light+",
+// i don't need rules, i'm not coding
+"editor.rulers": [],
+// larger text, to improve focus on writing
+"editor.fontSize": 14,
+// more comfortable line height
+"editor.lineHeight": 25,
+// disable editor suggestions based on previous words
+"editor.quickSuggestions": false,
+ },
+
+...
+}
+
Now, toggle zen mode in VS Code (see Keybindings, or View > Toggle Zen Mode) and check if that fits you!
2. Theme
Honestly, I think the default themes provided by VS Code do a great job. I use Dark+ as the dark theme; for light themes, either Quiet Light or Solarized Light.
If you don't like them, feel free to pick anything else, since most themes provide sufficient Markdown support anyway. Just don't procrastinate ā a good theme won't make you a better writer.
3. Font
My font of choice for writing is the Duospace, designed by the people behind the text editor iaWriter. Itās a free and beautiful font shaped for the perfect writing experience.
Configure the spell checker for your language, there are dictionary extensions for that available in the marketplace. I also have the Brazilian Portuguese package installed, for instance.
Like extensions? Keep exploring! The extension alex, for instance, catches insensitive, inconsiderate writing in texts.
Learn the Markdown keybindings provided by the All in One extension for a better workflow.
I'm based in ever-changing Berlin, but grew up in never-changing ViamĆ£o, a humble town in Brazil which taught me to be resourceful. Whether it was making kites out of bags and twigs, playing DIY football and cricket on muddy dirt roads, or ringing neighbors' doorbells and dashing away, I hacked whatever came my way.
That ultimately led me to unearth a fascination for computers. Back when I hacked my first game and setup a pirate server just so everything was free, I felt empowered by how computers could help solve our problems. Coming of age, I also realised how they may create new ones. š
Having honed my skills, and developed a passion for audio along the way, I am nowadays a Lead Software Engineer at Native Instruments. I manage web architecture and operations for leading audio brands, including iZotope.
Raised by the internet, I wholeheartedly support and draw on open knowledge to teach myself, experiment, and have fun. I wish nothing but for everyone to empower themselves towards never-ending exploration as I do.
Beyond my silly online presence, Iām a multidisciplinary creative partner in projects and can likely assist you from idea to launch! With over a decade of experience as a computer programmer, Iāve honed my skills in web development, led engineering teams, managed projects, and even designed UI/UX. Just get in touch :-)
Get in touch
Iām happy to hear from most humans on most things. Say hi!
Signal for serious stuff. ā Preferred as itās encrypted ā
Donāt have my Signal? Please email me with your name and your reason to contact me.
Metadata
This is my independent home on the internet. On my blog, I try to share knowledge and perspectives on what I find interesting ā sometimes computers. When I write, please assume IMHO/IMNHSO and openness for dialogue.
You may receive my blog updates by subscribing to my RSS Feed.
License & Attribution
Pages are statically generated with Zola as engine.
\ No newline at end of file
diff --git a/tags/books/index.html b/tags/books/index.html
new file mode 100644
index 0000000..b4b9f63
--- /dev/null
+++ b/tags/books/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/climate-change/index.html b/tags/climate-change/index.html
new file mode 100644
index 0000000..8828ba8
--- /dev/null
+++ b/tags/climate-change/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/css/index.html b/tags/css/index.html
new file mode 100644
index 0000000..18fec13
--- /dev/null
+++ b/tags/css/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/design/index.html b/tags/design/index.html
new file mode 100644
index 0000000..dbfe25d
--- /dev/null
+++ b/tags/design/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/digital-rights/index.html b/tags/digital-rights/index.html
new file mode 100644
index 0000000..ad93a49
--- /dev/null
+++ b/tags/digital-rights/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/essay/index.html b/tags/essay/index.html
new file mode 100644
index 0000000..00a0fcc
--- /dev/null
+++ b/tags/essay/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/html/index.html b/tags/html/index.html
new file mode 100644
index 0000000..4069baa
--- /dev/null
+++ b/tags/html/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/index.html b/tags/index.html
new file mode 100644
index 0000000..84717fc
--- /dev/null
+++ b/tags/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/javascript/index.html b/tags/javascript/index.html
new file mode 100644
index 0000000..f8f753a
--- /dev/null
+++ b/tags/javascript/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/language/index.html b/tags/language/index.html
new file mode 100644
index 0000000..8a630ae
--- /dev/null
+++ b/tags/language/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/music/index.html b/tags/music/index.html
new file mode 100644
index 0000000..21a9e7f
--- /dev/null
+++ b/tags/music/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/personal/index.html b/tags/personal/index.html
new file mode 100644
index 0000000..86240cd
--- /dev/null
+++ b/tags/personal/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/productivity/index.html b/tags/productivity/index.html
new file mode 100644
index 0000000..669b552
--- /dev/null
+++ b/tags/productivity/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/pt-br/index.html b/tags/pt-br/index.html
new file mode 100644
index 0000000..839c25d
--- /dev/null
+++ b/tags/pt-br/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/react/index.html b/tags/react/index.html
new file mode 100644
index 0000000..a8de723
--- /dev/null
+++ b/tags/react/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/script/index.html b/tags/script/index.html
new file mode 100644
index 0000000..fca9408
--- /dev/null
+++ b/tags/script/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/software/index.html b/tags/software/index.html
new file mode 100644
index 0000000..0c1ce5d
--- /dev/null
+++ b/tags/software/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/test/index.html b/tags/test/index.html
new file mode 100644
index 0000000..5d07431
--- /dev/null
+++ b/tags/test/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/travel/index.html b/tags/travel/index.html
new file mode 100644
index 0000000..f2c6483
--- /dev/null
+++ b/tags/travel/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/work/index.html b/tags/work/index.html
new file mode 100644
index 0000000..8d5abda
--- /dev/null
+++ b/tags/work/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/workflow/index.html b/tags/workflow/index.html
new file mode 100644
index 0000000..d7b7312
--- /dev/null
+++ b/tags/workflow/index.html
@@ -0,0 +1 @@
+