Holy Dev Newsletter November 2022
Welcome to the Holy Dev newsletter, which brings you gems I found on the web, updates from my blog, and a few scattered thoughts. You can get the next one into your mailbox if you subscribe.
What is happening
I have helped recently on a large JavaScript and React frontend and have been shocked by its complexity. So I am trying to understand how to make frontends simple (which is not easy :)). It lead so far to my study of "A simple front-end architecture that works" (presented below). Stay tuned! On a related note, I am reading the 2012 report from the STEPS project, which postulates that our codebases are 100, 1000 times larger than they need to be (oh yes!) and explores ways to improve that. Their approach is to use small, purpose-built languages and it produces very promising results.
Gems from the world wide web
π₯ A very good and entertaining criticism of today's state of software developement that has on the strait jacket of historical...
A very good and entertaining criticism of today's state of software developement that has on the strait jacket of historical burden, with demonstrations of some of the possibilites, including f.ex. interactive programming, visual tools for exploring program's state and code, Lisp-style recoverable errors, Erlang OTP's evolvable, killable, observable processes. The conclusion: we should use languages and tooling that is at least as good as Smalltalk's and Lisp's.
"[W]e're still digging ourselves into a kind of a pit by continuing to preserve practices that have no rational basis beyond being historical." - and make our job unnecessarily hard. The 80 char limit comes from the width of punch cards. Vi keybindings were optimized for a particular keyboard of the time. We still use fixed-width text as the primary/only medium, ignoring our powerful visual cortext. We still create programs as static artefacts that run from start to finish. (Long-lived serivces, anyone?) Little thought is typically given to evolving state over time.
Programming is a design discipline, i.e. you find out what youβre building as you build. Moreover, "the spec is always wrong" - it is always incomplete and it will change. So debuggability and evolvability are much more important that being "correct by construction," i.e. the (unproven) promise of static typing. We should embrace interactive development, have great tools for inspecting the running program, ones that leverage what we excel at including visual processing (here, the Glamorous toolkit looks as a step in the right direction). Our languages should empower us to express the business logic rather than drown in ceremony.
Transcript here.
π lilactown/pyramid: A library for storing and querying graph data in Clojure [clojure, library, data]
A fast, more limited, in-memory "graph database" composed of Clojure maps and queried via EQL. When the power/performance tradeoff of Datascript is not worth it. Also supports transforming data as it is being retrieved.
π GoatCounter β open source web analytics [SaaS, open-source, analytics]
Β Very lightweight stats for your website: visitors, top pages, referrers, etc. Includes automatic bot detection and campaign stats. Tracking JS is very small (3.5 kB) and has the option to use a pixel, trigger from server middleware or import raw logs. Doesnβt track users with IDs. Open source and can be self-hosted (written in Go and uses either SQLite or Postgres.
Via console.dev
π epiccastle/bbssh: Babashka pod for SSH support. [tool, devops, automation]
Babashka pod that enables you to script ssh - establish a connection, send commands etc.
π Meta Tags β Preview, Edit and Generate [writing, tool]
Great site to preview how social sites see your blog etc., to make sure previews will work as intended.
π Best security key in 2022: hardware keys for top online protection [security]
A 2022 overview of security keys - physical devices you plug into your PC and use for MFA, keeping your passwords really secure, etc. Features multiple variants of YubiKey, Thetis Fido U2F Security Key, CryptoTrust OnlyKey, uQontrol Qkey Password Vault, and HyperFido K18.
π drduh/YubiKey-Guide: Guide to using YubiKey for GPG and SSH [security]
Guide to using YubiKey for GPG and SSH, with a master key used for creating sub-keys that are then used for signing/encruption/authentication. You can also only use it for SSH with the key type ed25519-sk without bothering with GPG - you will touch your yubikey during creation and then anytime you want to use that ssh key.
π Debugging with tmate - GitHub Marketplace [productivity]
Get an interactive terminal into a GitHub Actions workflow for troubleshooting, f.ex. automatically when it failed. Uses the tmux fork tmate and connection proxying via tmate.io or your own tmate server. You can limit access to your own GH ssh key only.
π The Dhall configuration language [programming languages, productivity, devops]
"Dhall is a programmable configuration language that you can think of as: JSON + functions + types + imports". It is designed to solve the problems that template/configuration languages - such as the one used by Terraform or Kubernetes - have with limited reusability, verbosity, lacking/limited parametrization etc. It has integrations with a number of languages (e.g. Clojure, Go, Rust) and bindings for a bunch of configuration systems such as Ansible, CloudFormation, and Kubernetes (and you can always make your own).
π Netflix/concurrency-limits [library, java, performance]
The successur to the famous Netflix' Hystrix resillience library, born of the realization that fixed limits are impractical in complex, dynamic systems. This lib implements and integrates concepts from TCP congestion control to auto-detect concurrency limits for services in order to achieve optimal throughput with optimal latency.
Envoy has similarly working Adaptive Concurrency filter, which "dynamically adjusts the allowed number of requests that can be outstanding (concurrency) to all hosts in a given cluster at any time. Concurrency values are calculated using latency sampling of completed requests and comparing the measured samples in a time window against the expected latency for hosts in the cluster."
π mpenet/flex: Using TCP congestion control methods to find/set real limits of a system over time [clojure, library, performance, devops]
A Clojure library inspired by Netflix' concurrency-limits and the talk "Stop Rate Limiting! Capacity Management Done Right" by Jon Moore. - using TCP congestion control methods to find/set real limits of a system over time.
π Conventional Commits [software development, productivity]
The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. Title line:
Key types are feat and fix but you can use others, such as chore, docs, ci, refactor, perf, test, and others.
Examples:
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
feat(api)!: send an email to the customer when a product is shipped
π Preemptive Pluralization is (Probably) Not Evil [thoughts, design] - What if we just assumed we might have two of everything?
"Before you write any code β ask if you could ever possibly want multiple kinds of the thing you are coding. If yes, just do it. Now, not later."
π₯ Great 15 min intro into RxJS, the popular JS lib for reactive streams that I am forced to use.
Great 15 min intro into RxJS, the popular JS lib for reactive streams that I am forced to use.
A simple front-end architecture that works
A great, short article, auto-translated acceptably from Norwegian (the link preview below is not translated but the page it leads to is):
π A simple front-end architecture that works [webapp, architecture] - Det er mange store stilaser Γ₯ velge blant for din frontendarkitektur, men
trenger du all leamikken? Her er en enkel arkitektur som jeg har h
The key points: All the data needed by the app is kept at a single place as a monolithic state object (a cljs atom or JS object). The state is mapped to exactly the data the UI needs and then sent down to the root component and its children etc. Finally, the UI is built from generic, design-based components that are ignorant of any domain concepts.
The "single monolithic state" is known from re-frame and Redux. But contrary to these frameworks, the components here are passive and simply receive their props from their parent instead of pulling it in themselves via subscribe or Redux.connect. There is only one-way data flow from the root to the leaves.
A key factor that the data is fitted - "prepared" - to the UI before being handed over to the root component, i.e. the data is exactly in the form and shape the UI needs it. Thus there is little need for any logic in the components. Every parent component simply destructures its props and passes each one to the respective child.
Equally revolutionary is the insistence on generic, reusable components based on the design and ignorant of the domain (e.g. PrimaryButton instead of SignInButton, or DataTable instead of StudentList). Such design components are quite stable, while what should be displayed where and how changes often. Personally I think you might want some domain-oriented "layout" components that essentially only delegate to appropriate design components to display parts of a (UI-fitted) data entity. The generic components would imply that the prepare-d data also produces their generic props, for example not 'universityClasses' but 'rows'.
The original Norwegian article:
π A simple front-end architecture that works [webapp, architecture] - Det er mange store stilaser Γ₯ velge blant for din frontendarkitektur, men
trenger du all leamikken? Her er en enkel arkitektur som jeg har h
--
Thank you for reading!