diff --git a/content/journal/dispatch-5-july-2023/index.md b/content/journal/dispatch-5-july-2023/index.md
new file mode 100644
index 0000000..f7ff50d
--- /dev/null
+++ b/content/journal/dispatch-5-july-2023/index.md
@@ -0,0 +1,88 @@
+---
+title: "Dispatch #5 (July 2023)"
+date: 2023-07-02T16:55:57-04:00
+draft: false
+tags:
+- dispatch
+references:
+- title: "My thoughts on Helix after 6 months - Tim Hårek"
+ url: https://timharek.no/blog/my-thoughts-on-helix-after-6-months/
+ date: 2023-07-02T12:53:51Z
+ file: timharek-no-ah7ilz.txt
+- title: "What App is That?"
+ url: https://maggieappleton.com/apps
+ date: 2023-07-02T12:53:51Z
+ file: maggieappleton-com-7am49k.txt
+- title: "Modern software quality, or why I think using language models for programming is a bad idea"
+ url: https://softwarecrisis.dev/letters/ai-and-software-quality/
+ date: 2023-07-03T00:54:57Z
+ file: softwarecrisis-dev-7c7z9g.txt
+- title: "The small web is beautiful"
+ url: https://benhoyt.com/writings/the-small-web-is-beautiful/
+ date: 2023-07-03T00:52:08Z
+ file: benhoyt-com-vfdv1s.txt
+- title: "Why You Own an iPad and Still Can’t Draw"
+ url: https://maggieappleton.com/still-cant-draw
+ date: 2023-07-03T01:05:26Z
+ file: maggieappleton-com-fube9k.txt
+---
+
+June was dominated by work and travel. Weekdays were filled up with a client project we were working hard to wrap, weekends by plans with friends and both of our families: [Running of the Bulls][1], canoe camping near Saxapahaw, our yearly trip to Beaufort with Claire's college friends, and then a cruise in the Caribbean with Claire's family followed immediately by a trip up to DC to see mine.
+
+[1]: https://bullcityrunning.com/our-races/running-of-the-bulls-8k/
+
+
+
+
+ {{}}
+ {{}}
+ {{}}
+ {{}}
+
+
+Most everything else fell by the wayside, but that's OK -- these were all awesome experiences, and I'm excited for a (relatively) quiet July.
+
+After getting the trailer hitch installed last month, we picked up a [bike rack][2] and a [seat for Nev][3] and brought the bikes with us to Beaufort. This was **awesome** -- Beaufort's an idyllic coastal town in just about every way but one: parking sucks. Being able to zip up and down the main street on our bikes (and parking them right at our destination) was such a joy, and Nev seems to enjoy the rack-mounted seat a lot more than the trailer we've been using.
+
+I'm still enjoying using Obsidian to collect link and make notes, though mostly in the "capture" phase[^1], collecting information and starting to put some structure around it. When something comes up and I think, man, I read something good about that at some point in the past, I'm using that as a cue to create a dedicated note, with the hope that the _next_ time it comes up, I'll have a useful thing to reference.
+
+I also read some good articles about [Helix][4] and [Procreate][5], and I'm hoping to give those some attention this month.
+
+[2]: https://1up-usa.com/product/2-super-duty-double
+[3]: https://www.thule.com/en-us/child-bike-seats/rear-mounted-child-bike-seats/thule-yepp-nexxt-maxi-_-12080211
+[4]: https://timharek.no/blog/my-thoughts-on-helix-after-6-months/
+[5]: https://maggieappleton.com/apps
+
+This month:
+
+* Adventure: dust off the road bike, fill the tires, grease the chain, throw it on the rack, and get out for a long ride
+* Project: publish an article on [testing][14] on my company's website
+* Skill: learn [Helix][13] movements, see if it'd be a good Vim replacement (I still love Vim, and I'm pretty good at it, but my config's dated and I'm wary of how much effort it'll take to modernize)
+
+[13]: https://helix-editor.com/
+[14]: /notes/good-tests
+
+Reading:
+
+* Fiction: [_The Golden Enclaves_][6], Naomi Novik
+* Non-fiction:
+ * [_Rapt_][7], Winifred Gallagher
+ * [_Visual Thinking_][8], Williemien Brand
+ * [_The Manual: A Philosopher's Guide to Life_][9], Epictetus
+
+[7]: https://bookshop.org/p/books/rapt-attention-and-the-focused-life-winifred-gallagher/7485226?ean=9780143116905
+[6]: https://bookshop.org/p/books/the-golden-enclaves-naomi-novik/17789027?ean=9780593158357
+[8]: https://bookshop.org/p/books/visual-thinking-empowering-people-and-organisations-through-visual-collaboration-williemien-brand/12408256?ean=9789063694531
+[9]: https://bookshop.org/p/books/the-manual-a-philosopher-s-guide-to-life-epictetus/15150488?ean=9781545461112
+
+Links:
+
+* [Modern software quality, or why I think using language models for programming is a bad idea][10] -- I refer people to this article a lot in discussions around LLMs and software development
+* [The small web is beautiful][11]
+* [Why You Own an iPad and Still Can't Draw][12]
+
+[10]: https://softwarecrisis.dev/letters/ai-and-software-quality/
+[11]: https://benhoyt.com/writings/the-small-web-is-beautiful/
+[12]: https://maggieappleton.com/still-cant-draw
+
+[^1]: Tiago Forte's _Building a Second Brain_ outlines a four-step process: Capture, Organize, Distill, Express.
diff --git a/content/notes/first-it-must-work/index.md b/content/notes/first-it-must-work/index.md
index 943ce3f..b8e40f1 100644
--- a/content/notes/first-it-must-work/index.md
+++ b/content/notes/first-it-must-work/index.md
@@ -15,6 +15,10 @@ references:
url: https://cerebralab.com/Imaginary_Problems_Are_the_Root_of_Bad_Software
date: 2023-06-20T16:28:39Z
file: cerebralab-com-qy5zqs.txt
+- title: "When to Build Millennia Sewers"
+ url: https://taylor.town/millennium-sewer
+ date: 2023-07-03T00:32:43Z
+ file: taylor-town-5siv9a.txt
---
### Thoughts on priorities in software development
@@ -28,7 +32,9 @@ references:
* [The Grug Brained Developer][1]
* [Even Amazon can't make sense of serverless or microservices][2]
* [Imaginary Problems Are the Root of Bad Software][3]
+* [When to Build Millennia Sewers][4]
[1]: https://grugbrain.dev/
[2]: https://world.hey.com/dhh/even-amazon-can-t-make-sense-of-serverless-or-microservices-59625580
[3]: https://cerebralab.com/Imaginary_Problems_Are_the_Root_of_Bad_Software
+[4]: https://taylor.town/millennium-sewer
diff --git a/content/notes/golang/index.md b/content/notes/golang/index.md
index 9fa064c..e5daa6d 100644
--- a/content/notes/golang/index.md
+++ b/content/notes/golang/index.md
@@ -47,6 +47,7 @@ I find [Go][1] really compelling, even though it's not super applicable to my jo
* [SyncThing][5]
* [Restic][6]
* [Gotenberg][7]
+* [Shiori][8]
[2]: https://gohugo.io/
[3]: https://caddyserver.com/
@@ -54,29 +55,30 @@ I find [Go][1] really compelling, even though it's not super applicable to my jo
[5]: https://syncthing.net/
[6]: https://restic.net/
[7]: https://gotenberg.dev/
+[8]: https://github.com/go-shiori/shiori
### Project Ideas
* Bookmarking app (Pinboard replacement)
* Note-taking / journaling app
-* [StevieBlocks][8]
+* [StevieBlocks][9]
{{}}
-[8]: https://gist.github.com/dce/f975cb21b50a2cf998bf7230cbf89d85
+[9]: https://gist.github.com/dce/f975cb21b50a2cf998bf7230cbf89d85
### Resources
-* [Standard Go Project Layout][9]
-* [The files & folders of Go projects][10]
-* [Why David Yach Loves Go][11]
-* [One process programming notes (with Go and SQLite)][12]
-* [Go Project Layout][13]
-* [Gopher Wrangling. Effective error handling in Go][14]
+* [Standard Go Project Layout][10]
+* [The files & folders of Go projects][11]
+* [Why David Yach Loves Go][12]
+* [One process programming notes (with Go and SQLite)][13]
+* [Go Project Layout][14]
+* [Gopher Wrangling. Effective error handling in Go][15]
-[9]: https://github.com/golang-standards/project-layout
-[10]: https://changelog.com/gotime/278
-[11]: https://cloud.google.com/blog/products/application-modernization/why-david-yach-loves-go
-[12]: https://crawshaw.io/blog/one-process-programming-notes
-[13]: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
-[14]: https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/
+[10]: https://github.com/golang-standards/project-layout
+[11]: https://changelog.com/gotime/278
+[12]: https://cloud.google.com/blog/products/application-modernization/why-david-yach-loves-go
+[13]: https://crawshaw.io/blog/one-process-programming-notes
+[14]: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
+[15]: https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/
diff --git a/content/notes/good-tests/index.md b/content/notes/good-tests/index.md
index 194d8f8..420d60f 100644
--- a/content/notes/good-tests/index.md
+++ b/content/notes/good-tests/index.md
@@ -2,6 +2,11 @@
title: "Good Tests"
date: 2023-05-12T23:40:19-04:00
draft: false
+references:
+- title: "A year of Rails - macwright.com"
+ url: https://macwright.com/2021/02/18/a-year-of-rails.html
+ date: 2023-07-03T02:52:03Z
+ file: macwright-com-o4dndf.txt
---
_(Notes for a Viget article I'm putting together)_
diff --git a/static/archive/benhoyt-com-vfdv1s.txt b/static/archive/benhoyt-com-vfdv1s.txt
new file mode 100644
index 0000000..bd88105
--- /dev/null
+++ b/static/archive/benhoyt-com-vfdv1s.txt
@@ -0,0 +1,728 @@
+ [1]Ben Hoyt
+ * [2]Home
+ * [3]Resume/CV
+ * [4]Projects
+ * [5]Tech Writing
+ * [6]Non-Tech
+ * [7]Email
+
+ * [8]benhoyt.com
+ * [9]benhoyt@gmail.com
+
+The small web is beautiful
+
+ March 2021
+
+ Summary: I believe that small websites are compelling aesthetically,
+ but are also important to help us resist selling our souls to large
+ tech companies. In this essay I present a vision for the “small web”
+ as well as the small software and architectures that power it. Also,
+ a bonus rant about microservices.
+
+ Go to: [10]Software | [11]Web | [12]Server-side | [13]Static sites |
+ [14]Dependencies | [15]Analytics | [16]Microservices
+
+ About fifteen years ago, I read E. F. Schumacher’s Small is Beautiful
+ and, despite not being interested in economics, I was moved by its
+ message. Perhaps even more, I loved the terse poetry of the book’s
+ title – it resonated with my frugal upbringing and my own aesthetic.
+
+ I think it’s time for a version of that book about technology, with a
+ chapter on web development: The Small Web is Beautiful: A Study of Web
+ Development as if People Mattered. Until someone writes that, this
+ essay will have to do.
+
+ There are two aspects of this: first, small teams and companies. I’m
+ not going to talk much about that here, but [17]Basecamp and many
+ others have. What I’m going to focus on in this essay is small websites
+ and architectures.
+
+ I’m not the first to talk about the “small web”, but, somewhat
+ surprisingly, only a few people have discussed it using that term. Here
+ are the main web pages I can find that do:
+ * [18]Rediscovering the Small Web by Parimal Satyal: a fabulous
+ article about the joy of small, independent (and sometimes retro)
+ websites in contrast to the “commercial web”.
+ * [19]What is the Small Web?, by Aral Balkan of the Small Technology
+ Foundation: more of a manifesto against the surveillance of Big
+ Tech than something concrete, but still interesting.
+
+ Why aim small in this era of fast computers with plenty of RAM? A
+ number of reasons, but the ones that are most important to me are:
+ * Fewer moving parts. It’s easier to create more robust systems and
+ to fix things when they do go wrong.
+ * Small software is faster. Fewer bits to download and clog your
+ computer’s memory.
+ * Reduced power consumption. This is important on a “save the planet”
+ scale, but also on the very local scale of increasing the battery
+ life of your phone and laptop.
+ * The light, frugal aesthetic. That’s personal, I know, but as you’ll
+ see, I’m not alone.
+
+ So let’s dive in. I want to cover a bunch of different angles, each
+ with its own subheading.
+
+Small software
+
+ If we’re going to talk about a small web, we need to start with small
+ software.
+
+ As a teen, I learned to program using x86 assembly and [20]Forth –
+ perhaps odd choices, but my dad was heavily into Forth, and I loved how
+ the language was so simple I could write [21]my own bootstrapped
+ compiler.
+
+ In terms of career, I started as an embedded programmer – not as in
+ “embedded Linux” but as in microcontrollers where 16KB of RAM was
+ generous. My current laptop has 16GB of RAM, and that’s not a lot by
+ today’s standards. We were building IP-networked products with one
+ millionth the amount of RAM. Those kinds of micros are as cheap as
+ chips (ahem), and still widely used for small electronic devices,
+ sensors, internet-of-things products, and so on.
+
+ You have to think about every byte, compile with size optimizations
+ enabled, and reuse buffers. It’s a very different thing from modern web
+ development, where a JavaScript app compiles “down” to a 1MB bundle, or
+ a single Python object header is 16 bytes before you’ve even got any
+ data, or a Go hello-world binary is 2MB even before you’ve added any
+ real code.
+
+ How do you create small programs? I think the main thing is that you
+ have to care about size, and most of us don’t think we have time for
+ that. Apart from embedded development, there’s an entire programming
+ subculture called the [22]demoscene that cares about this. They have
+ competitions for the smallest 4KB demos: who can pack the most
+ graphical punch into 4096 bytes of executable. That’s smaller than many
+ favicons! ([23]Elevated and [24]cdak are two of the highest-rated 4K
+ demos.) Many demosceners go on to become game developers.
+
+ It’s not just about executable size … when you’re developing your next
+ command line tool, if you use Go or Rust or even C, your program will
+ be much faster, smaller, and use less memory than a Python or Java
+ equivalent. And easier to install. If you don’t understand why, please
+ do learn. (It’s out of scope for this essay, but to summarize: Go,
+ Rust, and C compile to ready-to-execute machine code, don’t carry
+ around a virtual machine, and don’t have memory overhead for objects
+ like integers.)
+
+ But why not apply some of the same principles to web development? In
+ the web world, I think the main trick is to be careful what
+ dependencies you include, and also what dependencies they pull in. In
+ short, know node_modules – or maybe better, no node_modules. More about
+ this [25]below.
+
+ Niklaus Wirth of Pascal fame wrote a famous paper in 1995 called [26]A
+ Plea for Lean Software [PDF]. His take is that “a primary cause for the
+ complexity is that software vendors uncritically adopt almost any
+ feature that users want”, and “when a system’s power is measured by the
+ number of its features, quantity becomes more important than quality”.
+ He goes on to describe Oberon, a computer language (which reminds me of
+ Go in several ways) and an operating system that he believes helps
+ solve the complexity problem. Definitely wirth a read!
+
+ I’ve been mulling over this for a number of years – back in 2008 I
+ wrote a sarcastic dig at how bloated Adobe Reader had become: [27]Thank
+ you, Adobe Reader 9! It was a 33MB download and required 220MB of hard
+ drive space even in 2008 (it’s now a 150MB download, and I don’t know
+ how much hard drive space it requires, because I don’t install it these
+ days).
+
+ But instead of just complaining, how do we actually solve this problem?
+ Concretely, I think we need to start doing the following:
+ * Care about size: this sounds obvious, but things only change when
+ people think they’re important.
+ * Measure: both your executable’s size, and your program’s memory
+ usage. You may want to measure over time, and make it a blocking
+ issue if the measurements grow more than x% in a release. Or you
+ could hold a memory-reduction sprint every so often.
+ * Language: choose a backend language that has a chance, for example
+ Rust, C or C++, or for servers, Go. These languages aren’t right
+ for everything (like data transformation scripts), but they produce
+ small executables, and they’re good for CLIs and desktop apps.
+ * Remove: cut down your feature set. Aim for a small number of
+ high-quality features. My car can’t fly or float, and that’s okay –
+ it drives well.
+ * Say no to new features: unless they really fit your philosophy, or
+ add more than they cost over the lifetime of your project.
+ * Dependencies: understand the size and complexity of each dependency
+ you pull in. Use only built-in libraries if you can.
+
+Small websites
+
+ I’m glad there’s a growing number of people interested in small
+ websites.
+
+ A few months ago there was a sequence of posts to Hacker News about
+ various “clubs” you could post your small website on: the [28]1MB Club
+ ([29]comments), [30]512KB Club ([31]comments), [32]250KB Club
+ ([33]comments), and even the [34]10KB Club ([35]comments). I think
+ those are a fun indicator of renewed interested in minimalism, but I
+ will say that raw size isn’t enough – a 2KB site with no real content
+ isn’t much good, and a page with 512KB of very slow JavaScript is worse
+ than a snappy site with 4MB of well-chosen images.
+
+ Some of my favourite small websites are:
+
+ [36]Hacker News: I personally like the minimalist, almost brutalist
+ design, but I love its lightness even more. I just downloaded the home
+ page, and loading all resources transfers only 21KB (61KB
+ uncompressed). Even pages with huge comment threads only transfer about
+ 100KB of compressed data, and load quickly. Reddit has become such a
+ bloated mess in comparison. Hacker News, never change!
+
+ [37]Lobsters: a similar news-and-voting site, with slightly more
+ “modern” styling. It uses some JavaScript and profile icons, but it’s
+ still clean and fast, and the total transfer size for the homepage is
+ only 102KB. You just don’t need megabytes to make a good website.
+
+ [38]Sourcehut: I like the concept behind Drew DeVault’s business, but I
+ love how small and anti-fluff the website is. He has set up a mini-site
+ called the [39]Software Forge Performance Index that tracks size and
+ browser performance of the prominent source code websites – Sourcehut
+ is far and away the lightest and fastest. Even his homepage is only
+ 81KB, including several screenshot thumbnails.
+
+ [40]SQLite: not only is SQLite a small, powerful SQL database engine,
+ the website is fantastically small and content-rich. Even their
+ 7000-word [41]page about testing is only 70KB. How do they do this?
+ It’s not magic: focus on high-quality textual content, minimal CSS, no
+ JavaScript, and very few images (a small logo and some SVGs).
+
+ [42]LWN: I’m a little biased, because I’ve written [43]articles for
+ them, but they’re an excellent website for Linux and programming news.
+ Extremely high-quality technical content (and a high bar for authors).
+ They’re definitely niche, and have a “we focus on quality content, not
+ updating our CSS every year” kind of look – they’ve been putting out
+ great content for 23 years! Their homepage only downloads 44KB (90KB
+ uncompressed).
+
+ [44]Dan Luu’s blog: this is one of the more hardcore examples. His
+ inline CSS is only about 200 bytes (the pages are basically unstyled),
+ and his HTML source code doesn’t use any linefeed characters. Kind of a
+ fun point, although then he goes on to load 20KB of Google Analytics
+ JavaScript…
+
+ As a friend pointed out, those websites have something of an
+ “anti-aesthetic aesthetic”. I confess to not minding that at all, but
+ on the other hand, small doesn’t have to mean ugly. More and more
+ personal blogs and websites have adopted a small web approach but are
+ more typographically appealing:
+ * [45]Armin Ronacher’s Thoughts and Writings
+ * [46]Chris Wellons’ “Null program” blog
+ * [47]Eric Radman’s BSD and SQL blog
+ * [48]Hugo Tunius’ programming blog
+ * [49]James Hague’s “Programming in the Twenty-First Century”
+ * [50]Julia Evans’ programming blog
+
+ There are many, many more. Programmer Sijmen Mulder created a nice list
+ of [51]text-only websites – not quite the same thing as small, but it
+ definitely overlaps!
+
+ However, it’s not just about raw size, but about an “ethos of small”.
+ It’s caring about the users of your site: that your pages download
+ fast, are easy to read, have interesting content, and don’t load scads
+ of JavaScript for Google or Facebook’s trackers. Building a website
+ from scratch is not everyone’s cup of tea, but for those of us who do
+ it, maybe we can promote templates and tools that produce small sites
+ that encourage quality over quantity.
+
+ For this website, I lovingly crafted each byte of HTML and CSS by hand,
+ like a hipster creating a craft beer. Seriously though, if your focus
+ is good content, it’s not hard to create a simple template from scratch
+ with just a few lines of HTML and CSS. It will be small and fast, and
+ it’ll be yours.
+
+ Loading this essay transfers about 23KB (56KB uncompressed), including
+ the favicon and analytics script. It’s small, fast, and readable on
+ desktop or mobile. I don’t think it’s too bad looking, but I’m
+ primarily aiming for a minimalist design focussed on the content.
+
+ In addition to making sure your HTML and CSS are small, be sure to
+ compress your images properly. Two basic things here: don’t upload
+ ultra-high resolution images straight from your camera, and use a
+ reasonable amount of JPEG compression for photos (and PNG for
+ screenshots or vector art). Even for large images, you can usually use
+ 75% or 80% compression and still have an image without JPEG noise. For
+ example, the large 1920x775 image on the top of my [52]side business’s
+ homepage is only 300KB.
+
+ Speaking of hero images, you don’t need big irrelevant images at the
+ top of your blog posts. They just add hundreds of kilobytes (even
+ megabytes) to your page weight, and don’t provide value. And please
+ don’t scatter your article with animated GIFs: if there’s something
+ animated on the screen, I can hardly concentrate enough to read the
+ text – and I’m [53]not the [54]only one. Include relevant, non-stock
+ images that provide value equal to their weight in bytes. Bare text is
+ okay, too, like a magazine article.
+
+ [55]IndieWeb.org is a great resource here, though they use the term
+ “indie” rather than “small”. This movement looks more organic than the
+ [56]Small Technology Foundation (which has even been [57]critiqued as
+ “digital green-washing”), and their wiki has a lot more real content.
+ IndieWeb also promotes local [58]Homebrew Website Clubs and
+ [59]IndieWebCamp meetups.
+
+Emphasize server-side, not JavaScript
+
+ JavaScript is a mixed blessing for the web, and more often than not a
+ bane for small websites: it adds to the download size and time, it can
+ be a performance killer, it’s bad for accessibility, and if you don’t
+ hold it right, it’s [60]bad for search engines. Plus, if your website
+ is content-heavy, it probably isn’t adding much.
+
+ Don’t get me wrong: JavaScript is sometimes unavoidable, and is great
+ where it’s great. If you’re developing a browser-based application like
+ Gmail or Google Maps, you should almost certainly be using JavaScript.
+ But for your next blog, brochure website, or project documentation
+ site, please consider plain HTML and CSS.
+
+ If your site – like a lot of sites – is somewhere in between and
+ contains some light interaction, consider using JavaScript only for the
+ parts of the page that need it. There’s no need to overhaul your whole
+ site using React and Redux just to add a form. Letting your server
+ generate HTML is still an effective way to create fast websites.
+
+ [61]Stack Overflow is a case in point. From day one, they’ve made
+ [62]performance a feature by rendering their pages on the server, and
+ by measuring and reducing render time. I’m sure the Stack Overflow code
+ has changed quite a lot since the Jeff Atwood days – it now makes a ton
+ of extra requests for advertising purposes – but the content still
+ loads fast.
+
+ [63]Hacker News (there’s that site again) is a server-side classic.
+ With only [64]one tiny JavaScript file for voting, the HTML generated
+ on the server does the rest. And [65]apparently it still runs on a
+ single machine.
+
+ Around fifteen years ago there was this great idea called
+ [66]progressive enhancement. The idea was to serve usable HTML content
+ to everyone, but users with JavaScript enabled or fast internet
+ connections would get an enhanced version with a more streamlined user
+ interface. In fact, Hacker News itself uses progressive enhancement:
+ even in 2021, you can still turn off JavaScript and use the voting
+ buttons. It’s a bit clunkier because voting now requires a page reload,
+ but it works fine.
+
+ Is progressive enhancement still relevant in 2021? Arguably not, though
+ some die-hards still turn JavaScript off, or at least enable it only
+ for sites they trust. However, I think it’s the mentality that’s most
+ important: it shows the developer cares about performance, size, and
+ alternative users. If Hacker News voting didn’t work without
+ JavaScript, I don’t think that would be a big problem – but it shows a
+ certain kind of nerdish care that it does work. Plus, the JavaScript
+ they do have is only 2KB (5KB uncompressed).
+
+ Compare that to the 8MB (14MB uncompressed) that the [67]Reddit
+ homepage loads. And this across 201 requests – I kid you not! – most of
+ which is JavaScript to power all the ads and tracking. Lovely…
+
+ You don’t need a “framework” to develop this way, of course, but there
+ are some tools that make this style of server-side development easier.
+ [68]Turbolinks from the Basecamp folks was an early one, and it’s now
+ been superseded by [69]Turbo, which is apparently used to power their
+ email service [70]Hey. I haven’t used these personally, but the ideas
+ are clever (and surprisingly old-skool): use standard links and form
+ submissions, [71]serve plain HTML, but speed it up with WebSockets and
+ JavaScript if available. Just today, in fact, someone posted a new
+ article on Hacker News which claims [72]“The Future of Web Software Is
+ HTML-over-WebSockets”. If Hey is anything to go by, this technique is
+ fast!
+
+ On the other hand, sometimes you can reduce overall complexity by using
+ JavaScript for the whole page if you’re going to need it anyway. For
+ example, the registry pages on my wedding registry website are rendered
+ on the client (they actually [73]use Elm, which compiles to
+ JavaScript). I do need the interactivity of JavaScript (it’s more
+ “single page application” than mere content), but I don’t need
+ server-side rendering or good SEO for these pages. The homepage is a
+ simple server-rendered template, but the registry pages are fully
+ client-rendered.
+
+Static sites and site generators
+
+ Another thing there’s been renewed interest in recently is static
+ websites (these used to be called just “websites”). You upload some
+ static HTML (and CSS and JavaScript) to a static file server, and
+ that’s it.
+
+ Improving on that, there are many “static site generators” available.
+ These are tools that generate a static site from simple templates, so
+ that you don’t have to copy your site’s header and footer into every
+ HTML file by hand. When you add an article or make a change, run the
+ script to re-generate. If you’re hosting a simple site or blog or even
+ a news site, this is a great way to go. It’s content, after all, not an
+ interactive application.
+
+ I use [74]GitHub Pages on this site just because it’s a free host that
+ supports SSL, and automatically builds your site using the [75]Jekyll
+ static site generator whenever you push a change. I have a standard
+ header and include the same CSS across all pages easily, though you can
+ have multiple templates or “layouts” if you want. Because most people
+ only view one or two articles on my site, I include my CSS inline. With
+ HTTP/2, this doesn’t make much difference, but Lighthouse showed around
+ 200ms with inline CSS, 300ms with external CSS.
+
+ Here’s an example of what a simple Jekyll page looks like (the start of
+ this essay, in fact):
+ ---
+ layout: default
+ title: "The small web is beautiful"
+ permalink: /writings/the-small-web-is-beautiful/
+ description: A vision for the "small web", small software, and ...
+ ---
+ Markdown text here.
+
+ I’ve also used [76]Hugo, which is a really fast static site generator
+ written in Go – it generates even large sites with thousands of pages
+ in a few seconds. And there are [77]many other options available.
+
+Fewer dependencies
+
+ There’s nothing that blows up the size of your software (or JavaScript
+ bundle) like third party dependencies. I always find a web project’s
+ node_modules directory hard to look at – just the sheer volume of stuff
+ in there makes me sad.
+
+ Different languages seem to have different “dependency cultures”.
+ JavaScript, of course, is notorious for an “if it can be a library, it
+ should be” attitude, resulting in the [78]left-pad disaster as well as
+ other minuscule libraries like the 3-line [79]isarray. There are also
+ big, heavy packages like [80]Moment.js, which takes [81]160KB even when
+ minified. There are ways to shrink it down if you don’t need all
+ locales, but it’s not the default, so most people don’t (you’re
+ probably better off choosing a more modular approach like
+ [82]date-fns).
+
+ Go now has good dependency management with the recent [83]modules
+ tooling, but it also has a culture of “use the standard library if you
+ can”. Russ Cox wrote an excellent essay about the downsides of not
+ being careful with your dependencies: [84]Our Software Dependency
+ Problem. Go co-creator Rob Pike even made this one of his [85]Go
+ proverbs: “A little copying is better than a little dependency.” You
+ can probably guess by now, but I like this minimalist approach: apart
+ from reducing the number of points of failure, it makes programs
+ smaller.
+
+ Python, Ruby, Java, and C# seem to be somewhere in between: people use
+ a fair number of dependencies, but from what I’ve seen there’s more
+ care taken and it doesn’t get as out of hand as node_modules.
+ Admittedly it is a little unfair, as Python (and those other languages)
+ have standard libraries that have more in them than JavaScript’s.
+
+ The website [86]YouMightNotNeedjQuery.com shows how many of the tasks
+ you think you might need a library for are actually quite simple to do
+ with plain JavaScript. For example, in one of my projects I use a
+ function like the following to make an API request with plain old
+ XMLHttpRequest:
+function postJson(url, data, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === xhr.DONE) {
+ callback(xhr.status, JSON.parse(xhr.responseText));
+ }
+ };
+ xhr.open("POST", url, true);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.send(JSON.stringify(data));
+}
+
+ The moral of the story: think twice before adding dependencies. You’ll
+ keep your websites and programs smaller and more reliable, and you’ll
+ thank Russ Cox later.
+
+Small analytics
+
+ Most website owners want some form of analytics to see how many
+ visitors are coming to their site, and from where. The go-to tool is
+ Google Analytics: it’s easy to set up and the UI is pretty
+ comprehensive. But there’s a cost: it adds a significant amount of
+ weight to your page (19KB of JavaScript, 46KB uncompressed), and it
+ sends a lot of user data for Google to collect.
+
+ Once again, there’s been renewed interest in smaller, more
+ privacy-friendly analytics systems in recent times. Just this morning I
+ read a provocative article that was highly-voted on Hacker News called
+ [87]“Google Analytics: Stop feeding the beast”.
+
+ Last year I wrote two articles for LWN on the subject, so I won’t say
+ too much more here:
+ * [88]Lightweight alternatives to Google Analytics: replacing it with
+ lightweight open source and privacy-conscious alternatives,
+ specifically [89]GoatCounter and [90]Plausible.
+ * [91]More alternatives to Google Analytics: some heavier
+ alternatives, and a brief look at log-based analytics tools.
+
+ For this website I use GoatCounter, which is available as a low-cost
+ hosted service (free for non-commercial use) or as a self-hosted tool.
+ I really like what Martin is doing here, and how small and simple the
+ tool is: no bells and whistles, just the basic traffic numbers that
+ most people want.
+
+Small architectures (not microservices)
+
+ Small websites are great for users, but small architectures are great
+ for developers. A small, simple codebase is easy to maintain, and will
+ have fewer bugs than a large, sprawling system with lots of interaction
+ points.
+
+ I contend that the “microservices everywhere” buzz is a big problem.
+ Microservices may be used successfully at Google and Amazon, but most
+ companies don’t need to build that way. They introduce complexity in
+ the code, API definitions, networking, deployment, server
+ infrastructure, monitoring, database transactions – just about every
+ aspect of a system is made more complex. Why is that?
+ * Code: you have lots of little repositories, possibly in different
+ languages, and each has to have some way to talk to the other
+ services (JSON over HTTP, gRPC, etc). With a monolithic system,
+ it’s all in one language (much better for a small team), calling
+ other modules is just a function call, and system-wide refactoring
+ is comparatively easy (especially in a statically typed language
+ like Go or Java).
+ * API definitions: with many services talking to each other, suddenly
+ you need standardized interfaces for how they communicate. You
+ spend a lot of time setting up gRPC or JSON schema definitions. In
+ a single codebase, a function signature is the API definition.
+ * Networking: with microservices, a function call is a network call,
+ and you spend time setting up your network infrastructure, thinking
+ about timeouts and retries, and maybe even designing inter-service
+ authentication. In monolithic systems, you only worry about
+ networking when talking to your database, cloud provider, and
+ users.
+ * Deployment: at a previous company I worked at, once we started
+ building with microservices, suddenly we needed fancy deployment
+ tooling and a dedicated infrastructure team to manage it all. You
+ can get by with a lot less if you’re only deploying a few services.
+ * Server infrastructure: you’ll probably need to set up new
+ infrastructure – lots of small virtual machines, or a
+ Kubernetes-based system. Kubernetes in itself is a complex
+ distributed application (even [92]Google admits it’s too complex),
+ and it takes a lot of work – or a lot of money – to run properly.
+ * Monitoring: to debug issues, you’ll need costly
+ distributed-monitoring software like Datadog to see what’s going
+ on. When an outage occurs, you’ll scramble to determine which
+ service is responsible, which team to page, and so on. Compare that
+ with a simple stack trace or single-service issue.
+ * Database transactions: these are difficult to impossible in a
+ microservices architecture. You may be able to design your way out
+ of them, but that’s not easy either. With a monolith, just type
+ BEGIN ... COMMIT, or however your database library spells it.
+
+ It’s been said before, but microservices solve a people problem, not a
+ technical one. But beware of [93]Conway’s Law: your architecture will
+ mimic your company structure. Or the reverse – you’ll have to hire and
+ reorg so that your company structure matches the architecture that
+ microservices require: lots of engineers on lots of small teams, with
+ each team managing a couple of microservices.
+
+ That doesn’t mean microservices are always the wrong choice: they may
+ be necessary in huge engineering organizations. However, if you’re
+ working at such a company, you’ve probably already been using
+ microservices for years. If you’re not “Google size”, you should think
+ twice before copying their development practices.
+
+ What’s the alternative? The term “monolith” has a bad rap, but I agree
+ with David at Basecamp that [94]monoliths can be majestic. Basecamp is
+ a large, monolithic application, and they run it with just a dozen
+ programmers. David is quick to point out that “the Majestic Monolith
+ doesn’t pretend to provide a failsafe architectural road to glory”. You
+ still have to think, design, and write good code.
+
+ Thankfully, people are bouncing back from the cargo culting. Just do a
+ search for [95]“why not microservices” and you’ll find lots of good
+ articles on the subject. One of the recent ones I’ve read is from
+ Tailscale: [96]Modules, monoliths, and microservices.
+
+ So what’s my advice?
+ * Unless your company name is Google or Amazon, start with a
+ monolith.
+ * Once it starts having problems, optimize or refactor the pain
+ points.
+ * If it’s still having issues, buy a bigger server.
+ * If you have a specific technical reason to split it up, fix that
+ problem.
+ * If there are still problems, split off only the component that
+ needs splitting off. You’ll have two services to deploy and
+ monitor, but that’s far simpler than going all-in on microservices.
+
+ Okay, so this became more of an anti-microservices rant than I was
+ planning, but so be it.
+
+ In terms of counter-examples, Stack Overflow once again comes to mind.
+ They’re one of the web’s busiest sites, but they have a relatively
+ simple, two-tier [97]architecture that they’ve scaled vertically – in
+ other words, big servers with lots of RAM, rather than hundreds of
+ small servers. They have 9 web servers and 4 very chunky SQL servers,
+ with a few additional servers for their tag engine, Redis,
+ Elasticsearch, and HAProxy. This architecture helps them get great
+ performance and the ability to develop with a small team.
+
+ My own side business, [98]GiftyWeddings.com, only gets a small amount
+ of traffic, so it’s nothing like Stack Overflow, but it uses a Go HTTP
+ server with SQLite on one of the smallest EC2 instances available,
+ [99]t2.micro. It costs about $8 per month, and I only have one tiny
+ piece of infrastructure to maintain. I deploy using [100]Ansible – a
+ tool that is another good example of simple architecture and boils down
+ to “just use ssh”.
+
+ Speaking of SQLite, there’s a growing number of developers who advocate
+ using SQLite to run their websites. SQLite’s [101]“when to use SQLite”
+ page says “any site that gets fewer than 100K hits/day should work fine
+ with SQLite. The 100K hits/day figure is a conservative estimate, not a
+ hard upper bound. SQLite has been demonstrated to work with 10 times
+ that amount of traffic.” Here are some other SQLite success stories:
+ * [102]Litestream is an open source tool that provides streaming
+ replication for SQLite. Read author Ben Johnson’s article, [103]Why
+ I Built Litestream.
+ * Go developer David Crawshaw has an article about what he calls
+ [104]“one process programming” (with Go and SQLite), that can be
+ summed up with his phrase “don’t use N computers when 1 will do”.
+ He also created a [105]Go SQLite library that supports more
+ SQLite-specific features than the other drivers.
+ * Peewee ORM author Charles Leifer wrote an article [106]“Five
+ reasons you should use SQLite in 2016” that’s still very relevant
+ in 2021. It ends with “I hope you’ll give SQLite a try. Don’t
+ believe the FUD about it not being production-worthy, or not being
+ suitable for use in web-applications.”
+ * Sam Eaton of [107]Crave Cookie runs a $200,000 per month side
+ business (wow!) using a single server and SQLite. Read his
+ [108]Indie Hackers interview.
+
+Summing up
+
+ Companies will do what companies do, and continue to make
+ flashy-looking, bloated websites that “convert” well. Maybe you can
+ have an influence at work, and come home to your better half and say
+ “honey, I shrunk the web”. Or maybe you’ll just focus on the small web
+ for your personal projects. (Disclaimer: I mostly do the latter – as
+ part of my day job, I work on [109]Juju, which is not a small system by
+ most measures.)
+
+ Either way, I believe the “small web” is a compelling term and a
+ compelling aesthetic. Not necessarily in the visual sense, but in the
+ sense that you built it yourself, you understand all of it, and you run
+ it on a single server or static file host.
+
+ There are thousands of excellent examples of small websites, and
+ hundreds of ways to create simple architectures – this essay touches on
+ only a few of the ones I’m passionate about. I’d love to hear your own
+ ideas and stories! Comment over at [110]Lobsters or [111]Hacker News or
+ [112]programming Reddit.
+
+ I’d love it if you [113]sponsored me on GitHub – it will motivate me to
+ work on my open source projects and write more good content. Thanks!
+
+References
+
+ 1. file:///
+ 2. file:///
+ 3. file:///cv/
+ 4. file:///projects/
+ 5. file:///writings/
+ 6. file:///writings/non-tech/
+ 7. mailto:benhoyt@gmail.com
+ 8. https://benhoyt.com/
+ 9. mailto:benhoyt@gmail.com
+ 10. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#small-software
+ 11. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#small-websites
+ 12. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#emphasize-server-side-not-javascript
+ 13. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#static-sites-and-site-generators
+ 14. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#fewer-dependencies
+ 15. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#small-analytics
+ 16. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#small-architectures-not-microservices
+ 17. https://basecamp.com/books
+ 18. https://neustadt.fr/essays/the-small-web/
+ 19. https://ar.al/2020/08/07/what-is-the-small-web/
+ 20. https://en.wikipedia.org/wiki/Forth_(programming_language)
+ 21. https://github.com/benhoyt/third
+ 22. https://en.wikipedia.org/wiki/Demoscene
+ 23. https://www.youtube.com/watch?v=jB0vBmiTr6o
+ 24. https://www.youtube.com/watch?v=RCh3Q08HMfs
+ 25. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83225-8351TMP.html#fewer-dependencies
+ 26. https://cr.yp.to/bib/1995/wirth.pdf
+ 27. https://blog.brush.co.nz/2008/07/adobe-reader-9/
+ 28. https://1mb.club/
+ 29. https://news.ycombinator.com/item?id=25151773
+ 30. https://512kb.club/
+ 31. https://news.ycombinator.com/item?id=25450451
+ 32. https://250kb.club/
+ 33. https://news.ycombinator.com/item?id=25176663
+ 34. https://10kbclub.com/
+ 35. https://news.ycombinator.com/item?id=25556860
+ 36. https://news.ycombinator.com/news
+ 37. https://lobste.rs/
+ 38. https://sourcehut.org/
+ 39. https://forgeperf.org/
+ 40. https://sqlite.org/
+ 41. https://sqlite.org/testing.html
+ 42. https://lwn.net/
+ 43. https://lwn.net/Archives/GuestIndex/#Hoyt_Ben
+ 44. https://danluu.com/
+ 45. https://lucumr.pocoo.org/
+ 46. https://nullprogram.com/
+ 47. http://eradman.com/
+ 48. https://hugotunius.se/
+ 49. https://prog21.dadgum.com/
+ 50. https://jvns.ca/
+ 51. https://sjmulder.nl/en/textonly.html
+ 52. https://giftyweddings.com/
+ 53. https://news.ycombinator.com/item?id=26057078
+ 54. https://news.ycombinator.com/item?id=11210860
+ 55. https://indieweb.org/
+ 56. https://small-tech.org/
+ 57. https://news.ycombinator.com/item?id=24269071
+ 58. https://indieweb.org/Homebrew_Website_Club
+ 59. https://indieweb.org/IndieWebCamps
+ 60. https://benhoyt.com/writings/seo-for-software-engineers/
+ 61. https://stackoverflow.com/
+ 62. https://blog.codinghorror.com/performance-is-a-feature/
+ 63. https://news.ycombinator.com/
+ 64. https://news.ycombinator.com/hn.js
+ 65. https://news.ycombinator.com/item?id=23876281
+ 66. https://alistapart.com/article/understandingprogressiveenhancement/
+ 67. https://www.reddit.com/
+ 68. https://github.com/turbolinks/turbolinks
+ 69. https://turbo.hotwire.dev/
+ 70. https://hey.com/
+ 71. https://m.signalvnoise.com/html-over-the-wire/
+ 72. https://alistapart.com/article/the-future-of-web-software-is-html-over-websockets/
+ 73. https://benhoyt.com/writings/learning-elm/
+ 74. https://pages.github.com/
+ 75. https://jekyllrb.com/
+ 76. https://gohugo.io/
+ 77. https://staticsitegenerators.net/
+ 78. https://www.davidhaney.io/npm-left-pad-have-we-forgotten-how-to-program/
+ 79. https://github.com/juliangruber/isarray/blob/c9b0c5b4f44d366c9f51c7e85e70339bdeaa97b0/index.js#L3-L5
+ 80. https://momentjs.com/
+ 81. https://momentjs.com/docs/#/use-it/webpack/
+ 82. https://date-fns.org/
+ 83. https://golang.org/doc/modules/managing-dependencies
+ 84. https://research.swtch.com/deps
+ 85. https://go-proverbs.github.io/
+ 86. http://youmightnotneedjquery.com/
+ 87. https://casparwre.de/blog/stop-using-google-analytics/
+ 88. https://lwn.net/Articles/822568/
+ 89. https://www.goatcounter.com/
+ 90. https://plausible.io/
+ 91. https://lwn.net/Articles/824294/
+ 92. https://www.theregister.com/2021/02/25/google_kubernetes_autopilot/
+ 93. https://en.wikipedia.org/wiki/Conway's_law
+ 94. https://m.signalvnoise.com/the-majestic-monolith/
+ 95. https://duckduckgo.com/?t=canonical&q=why+not+microservices&ia=web
+ 96. https://tailscale.com/blog/modules-monoliths-and-microservices/
+ 97. https://stackexchange.com/performance
+ 98. https://giftyweddings.com/
+ 99. https://aws.amazon.com/ec2/instance-types/t2/
+ 100. https://www.ansible.com/
+ 101. https://sqlite.org/whentouse.html
+ 102. https://litestream.io/
+ 103. https://litestream.io/blog/why-i-built-litestream/
+ 104. https://crawshaw.io/blog/one-process-programming-notes
+ 105. https://github.com/crawshaw/sqlite
+ 106. https://charlesleifer.com/blog/five-reasons-you-should-use-sqlite-in-2016/
+ 107. https://cravecookie.com/
+ 108. https://www.indiehackers.com/podcast/166-sam-eaton-of-crave-cookie
+ 109. https://jaas.ai/
+ 110. https://lobste.rs/s/d6qwff/small_web_is_beautiful
+ 111. https://news.ycombinator.com/item?id=26305585
+ 112. https://www.reddit.com/r/programming/comments/lvfdq9/the_small_web_is_beautiful/
+ 113. https://github.com/sponsors/benhoyt/
diff --git a/static/archive/macwright-com-o4dndf.txt b/static/archive/macwright-com-o4dndf.txt
new file mode 100644
index 0000000..9cb81bb
--- /dev/null
+++ b/static/archive/macwright-com-o4dndf.txt
@@ -0,0 +1,344 @@
+ #[1]macwright.com [2]macwright.com
+
+Tom MacWright
+
+ tom@macwright.com
+
+Tom MacWright
+
+ * [3]Writing
+ * [4]Reading
+ * [5]Photos
+ * [6]Projects
+ * [7]Drawings
+ * [8]About
+
+A year of Rails
+
+ Railroad
+
+ I spent most of 2020 working with [9]Ruby on Rails. I moved a project
+ from [10]Next.js + [11]Rust to… Rails, baby! Back to the future. My
+ earlier post on [12]Second-guessing the modern web was inspired by this
+ experience, that for the product we were building, a ‘modern’ stack was
+ not working as well as a traditional one.
+
+ We didn’t do competitive analysis against Laravel, Django, or Phoenix.
+ They’re similar, not radically better or worse. There are multiple
+ acceptable solutions to a problem, and this was more a matter of
+ choosing the right kind of solution than pursuing some kind of perfect
+ choice and burning hours and motivation doing the window-shopping.
+
+ What helped Rails win was that the team had a little more experience in
+ Ruby (with the exception of myself), and we found plenty of resources
+ for developing and deploying the stack. Rails fit perfectly into the
+ ideology of [13]Choosing boring technology. Another part of the product
+ would be the hard, innovative part, so it made no sense to grapple with
+ bleeding-edge web frameworks.
+
+ This was a really fun experience. There’s a lot to love about Rails.
+ Other communities could learn a bit from the Ruby & Rails culture and
+ wisdom. I won’t implement everything in Rails, but it’ll be part of the
+ toolbox.
+
+ Before this, I hadn’t touched the stuff. And I bet a lot of people are
+ like that - they came of age in the world of React and Go, and haven’t
+ tried anything even remotely similar to Rails. For their benefit, and
+ to debrief from 2020, here are some notes on the experience. Plus,
+ [14]Rails-like projects in JavaScript are ramping up quickly, and it’s
+ fun to know the origins.
+
+The good
+
+Debugging Rails apps is amazing
+
+ A while ago, I [15]wrote on Twitter
+
+ the real reason why javascript developers don’t use breakpoints and
+ use console.log is that breakpoints don’t work
+
+ After years of working in JavaScript, I’m used to bad debugging
+ experiences. The Chrome debugger’s [16]automatic pause on caught
+ exceptions is amazing, sometimes. But throwing a debugger statement in
+ some React code is dodgy as hell. Sometimes it works, mostly it
+ doesn’t. You have to deal with code that might not have the right
+ [17]sourcemap to translate from bundled & minified code to original
+ source. Subtle abstractions like React hooks and advanced transpiler
+ stuff like [18]Regenerator mean that your code’s stacktrace probably
+ looks nothing like what you expect, with lots of internal garbage.
+ Sure, you can learn better techniques for diagnosing and debugging
+ errors, but it’s not just you - the debugging story in JavaScript is
+ pretty bad. This applies even to Node.js, where one of the debugging
+ stories is to connect Chrome’s debugger to a Node.js instance: a
+ finicky solution that doesn’t consistently work.
+
+ In Rails, there is [19]byebug. You write byebug in your source code,
+ and you get an interactive REPL right there. It works in views,
+ controllers, database migrations, everywhere. It almost always works.
+ Variables are named what you expect. The whole system is paused at that
+ moment, and you can actually interact with it, using all of the Rails
+ utilities and your installed gems.
+
+ If a page crashes unexpectedly, you get a similar REPL experience, in
+ your browser, automatically. With an automatically cleaned-up
+ stacktrace that excludes Rails’s own frames. Like the byebug interface,
+ this REPL actually works and is consistently helpful in finding root
+ causes. Rarely will you need to use puts to print something to the
+ console because this debugging system is so good.
+
+The magic mostly works
+
+ Our Rails app didn’t have any require statements. You mention a
+ module’s name, and it’s automatically included, using [20]Zeitwerk, a
+ tool that comes standard with Rails.
+
+ This kind of system was terrifying to me before. What if you
+ accidentally import something just by mentioning it? What if two things
+ have the same name and you import the wrong one? How do you really know
+ what’s happening? Sure, you’re happy now, with all of that annoying
+ importing and exporting taken care of, but the sky might fall.
+
+ Or maybe it just… doesn’t. Maybe impure, vaguely risky techniques are
+ just a net positive over time, and making everything fully explicit
+ isn’t really necessary? Now when I’m using other systems, I wonder -
+ what if I could just mention one of my React components and it would
+ just… be there? Sure, the system would have to complain if there were
+ two components with the same name, and it would have to make
+ assumptions about directory structure, but overall, wouldn’t this be
+ nice?
+
+ This applies to a lot of other parts of the system too. Rails is famous
+ for doing pluralization - you name a model Post and you automatically
+ get an interface called posts. But what, you ask, of words with uneven
+ pluralization rules? Rails actually [21]does the right thing, almost
+ always. And when it fails, you can override it. It actually just saves
+ time, reliably.
+
+Testing works
+
+ I’ve tried to test front-end applications. I’ve set up [22]nightwatch,
+ [23]jest, [24]enzyme, [25]cypress, and probably 5-10 other frameworks.
+ Front-end testing is universally terrible. Projects like Cypress are
+ throwing untold hours into making it less terrible, taking on massive
+ amounts of complexity to abstract away from fickle browser behavior and
+ complex interactions.
+
+ But it still sucks. Frontend testing has no good attributes: it’s
+ unreliable, hard to automate, hard to debug when it fails, and often
+ doesn’t even assert for important behaviors, so it doesn’t actually
+ identify regressions. Running frontend tests in CI is resource-heavy,
+ requiring you to set up headless X windows environments on servers or
+ use specialized CI services that produce screencasts of test runs.
+
+ Testing fully-server-rendered applications, on the other hand, is
+ amazing. A vanilla testing setup with Rails & [26]RSpec can give you
+ fast, stable, concise, and actually-useful test coverage. You can
+ actually assert for behavior and navigate through an application like a
+ user would. These tests are solving a simpler problem - making requests
+ and parsing responses, without the need for a full browser or headless
+ browser, without multiple kinds of state to track.
+
+ Not only do the tests work better, the testing culture is a completely
+ different universe. There are entire books written about how to write
+ RSpec tests that catch bugs, allow software evolution, and aren’t
+ filled with boilerplate.
+
+Gems are so powerful
+
+ Powerful and dangerous.
+
+ I’m used to modules as they work in other systems - Python, Node, Elm,
+ and so on. They provide objects, functions, and variables that you can
+ import and combine into your code explicitly. Usually they sit on some
+ specific level of abstraction - it’s a utility for connecting to
+ servers or a React component you can use.
+
+ Gems can do so much more. You install something like [27]Devise into
+ your system and it adds views, routes, methods, utilities, you name it.
+ It’s not like “loading some functions”, it’s more like composing a
+ whole different app into your app, implicitly.
+
+ This is obviously terrifying. It means that you can’t look at your
+ directories of views and your file of routes.rb and know what exists at
+ a glance. There are other layers, lurking in the ephemeral space of
+ third-party code. They interact in serious but uncertain ways.
+
+ But it’s also pretty incredible - the idea that something like
+ [28]passport, Node’s middleware, could instead be a full-fledged
+ authentication system. It means that you have to write a lot less code,
+ and it also means that the people who use that code have a lot more
+ code in common. That gems can work on a higher level of abstraction,
+ making it possible to cobble together software faster, to write less
+ ‘glue code.’
+
+There’s so much good writing about Rails
+
+ Even if you don’t write Ruby, you should pay attention to [29]Sandi
+ Metz. She’s incredibly wise and has so many incredible ideas to share.
+
+ And then there’s [30]arkency, [31]ThoughtBot, and so many other
+ thoughtful writers with years of experience in Rails. Sometimes it’s a
+ little shocking to google for some obscure problem and see a decade of
+ discussion about it.
+
+ The best practices are also formalized into tools like [32]Code Climate
+ and [33]reek. I’ve never seen so many actually-useful suggestions come
+ out of automated systems as I did in the world of Ruby and Rails.
+
+Ruby
+
+ Ruby is a pretty pleasant language to work in. Sure, it has a lot of
+ syntax and a sprawling standard library, but you don’t have to use all
+ of that if you don’t want to. It took me a while to adjust to the
+ object-oriented way of doing things - in particular, the idea that you
+ can’t just have a free-range function floating out there, unassociated
+ with a class or module, like you can in JavaScript. And you can’t just
+ create an arbitrary one-off object - you either need to define a class
+ to create an object, or use a Hash to store data.
+
+ But Ruby’s standard library isn’t that huge. I’ve seen JavaScript’s
+ ‘standard library’ grow a lot too, and frankly it’s nice to have
+ methods like [34]String.prototype.padStart instead of having every
+ little thing in userspace. The only part that felt actively weird was
+ [35]activesupport - a gem that extends Ruby’s core objects, but is part
+ of Rails. It felt weird to have string methods that would only work if
+ your environment was Rails.
+
+ The [36]Dash app for documentation rocketed from my pile of unused
+ tools to an absolute must-have. In the world of Ruby and Rails, with
+ most gems having pretty good, semi-standard documentation, you can
+ search for, and get answers, super fast. The Ruby language
+ documentation and the Rails documentation is absolutely great. The
+ JavaScript equivalent - [37]MDN - pales in comparison.
+
+The bad
+
+The asset pipeline
+
+ Remember SASS and the YUI Compressor? These are, unfortunately,
+ defaults in the [38]asset pipeline. There’s [39]Webpacker too, which
+ has a parallel approach to CSS and images as the asset pipeline. It has
+ [40]opinionated integrations with stuff like React. Ah, and I should
+ mention that Rails’s [41]JavaScript utilities are written in…
+ CoffeeScript.
+
+ I get it - it’s hard to keep up with the latest trends in frontend. But
+ this is one area where Rails’s strong backwards compatibility feels
+ iffy. I wish that Rails was more opinionated about the frontend, and
+ that it had better opinions.
+
+Best practice churn
+
+ In Smalltalk, everything happens somewhere else. - [42]Adele
+ Goldberg
+
+ Ruby, as today’s Smalltalk, has the same issue. The community venerates
+ small - that methods should be short, files should be small, complexity
+ should be controlled. This begs the question of where it all goes -
+ certainly not in controllers, which should be skinny, and not in views,
+ which should have very little logic at all, and maybe [43]not in models
+ either. Maybe in [44]Service Objects, or policies, or decorators?
+
+ I found myself falling victim to this. I’d try to win CodeClimate’s
+ approval by moving code around, perfecting the art of making everything
+ small or at most medium-sized, extracting concerns until most files
+ looked okay. This was time well-spent on learning, but I have to admit
+ that it doesn’t actually matter for an early-stage startup’s product.
+
+ In stark contrast to the folks who say that Rails is for prototypes,
+ there’s a lot of attention paid to long-lived engineering efforts -
+ adopting patterns that let many team work on the same ‘monolith’,
+ identifying [45]shotgun surgery - a term I first heard from Sandi Metz.
+
+ActiveRecord is great, except when it isn’t
+
+ One of the hardest bugs we encountered happened with ActiveRecord. We
+ were creating a set of changes to apply to a model, using their
+ in-memory instances to do some stuff, and then finally applying them.
+ This broke because one of the ActiveRecord methods automatically
+ ‘committed’ those changes, quietly.
+
+ ActiveRecord is kind of like this - a lot of the times it’s pleasantly
+ implicit, letting you just assign a value and automatically saving that
+ to the database. But then it’ll do something implicitly that you don’t
+ want to happen, and figuring out why this happened and how to stop it
+ from happening is a real challenge.
+
+ Most of the time, to be clear - it’s a really great system. It provides
+ lots of ways to generate efficient-enough queries, knowing full well
+ that SQL performance is often the bottleneck of web applications. Most
+ of the time it’s really nice that it automatically casts and
+ deserializes query results. But when it goes bad, the diagnosis and the
+ cure can be pretty ugly.
+
+ The other issue with ActiveRecord is that it has efficient methods and
+ inefficient methods right next to each other, because it automatically
+ turns your ‘query builder’ into an array when you call array-like
+ methods. So, for example:
+Dogs.all.max_by(&:height)
+
+ Is wildly inefficient. It might fetch and deserialized a million
+ records just to sort them and give you the first. On the other hand,
+Dogs.order(height: :desc).first
+
+ Is fast - it sorts in the database and fetches a single record. Rails
+ is both offering smart and easy ways to write optimized code, but also
+ making it really easy to write inefficient code.
+ __________________________________________________________________
+
+ A Rails-like framework is a really good thing to have in your toolbox,
+ and there’s a lot to learn from the Ruby community. My hope is that we
+ see these sorts of abstractions in new languages and frameworks, and
+ see more of the Ruby community’s culture filter into the programming
+ world.
+
+ February 18, 2021 [46]@tmcw
+
+References
+
+ 1. https://macwright.com/rss.xml
+ 2. https://macwright.com/atom.xml
+ 3. file:///
+ 4. file:///reading/
+ 5. file:///photos/
+ 6. file:///projects/
+ 7. file:///drawings/
+ 8. file:///about/
+ 9. https://rubyonrails.org/
+ 10. https://nextjs.org/
+ 11. https://www.rust-lang.org/
+ 12. https://macwright.com/2020/05/10/spa-fatigue.html
+ 13. http://boringtechnology.club/
+ 14. https://macwright.com/2020/10/28/if-not-spas.html
+ 15. https://twitter.com/tmcw/status/1321133460501585922
+ 16. https://developers.google.com/web/updates/2015/05/automatically-pause-on-any-exception
+ 17. https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
+ 18. https://github.com/facebook/regenerator
+ 19. https://github.com/deivid-rodriguez/byebug
+ 20. https://github.com/fxn/zeitwerk
+ 21. https://weblog.rubyonrails.org/2005/8/25/10-reasons-rails-does-pluralization/
+ 22. https://nightwatchjs.org/
+ 23. https://jestjs.io/
+ 24. https://enzymejs.github.io/enzyme/
+ 25. https://www.cypress.io/
+ 26. https://rspec.info/
+ 27. https://github.com/heartcombo/devise
+ 28. http://www.passportjs.org/
+ 29. https://sandimetz.com/
+ 30. https://blog.arkency.com/
+ 31. https://thoughtbot.com/blog/
+ 32. https://codeclimate.com/
+ 33. https://github.com/troessner/reek
+ 34. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
+ 35. https://rubygems.org/gems/activesupport/versions/6.1.1
+ 36. https://kapeli.com/dash
+ 37. https://developer.mozilla.org/en-US/
+ 38. https://guides.rubyonrails.org/asset_pipeline.html
+ 39. https://edgeguides.rubyonrails.org/webpacker.html
+ 40. https://github.com/rails/webpacker#integrations
+ 41. https://github.com/rails/rails/tree/main/actionview/app/assets/javascripts
+ 42. https://en.wikipedia.org/wiki/Adele_Goldberg_(computer_scientist)
+ 43. https://thoughtbot.com/blog/skinny-controllers-skinny-models
+ 44. https://codeclimate.com/blog/7-ways-to-decompose-fat-activerecord-models/
+ 45. https://en.wikipedia.org/wiki/Shotgun_surgery
+ 46. https://twitter.com/intent/follow?screen_name=tmcw&user_id=1458271
diff --git a/static/archive/maggieappleton-com-7am49k.txt b/static/archive/maggieappleton-com-7am49k.txt
new file mode 100644
index 0000000..c99bfc5
--- /dev/null
+++ b/static/archive/maggieappleton-com-7am49k.txt
@@ -0,0 +1,150 @@
+ #[1]Main RSS Feed
+
+ [2]Home
+ The Garden (BUTTON)
+ [3]Now
+ [4]About
+ (BUTTON)
+
+ notes
+
+ evergreen
+
+What App is That?
+
+ A guide to the apps and tools I use to create illustrations
+ * [5]How to Illustrate
+
+ Planted about 3 years agoLast tended about 2 years ago
+
+ (BUTTON) Back To Top
+
+ "What app is that?"
+
+ [6]
+
+I'm a Promiscuous Polytooler
+
+ I use wide variety of different tools and apps for different kinds of
+ visual creations. I'm not wedded to any one tool in particular – they
+ all have their strengths and weaknesses. I'll use whatever fits the
+ task at hand and move work between them liberally.
+
+ Here's all the apps and hardware that might be involved in a particular
+ creation...
+
+ None of these are affiliate links - I'm just pointing you to official
+ sites for more context
+ [7]
+
+Workflows
+
+ And here's a couple of my common workflows for different styles of
+ illustrations and visuals...
+
+1. Illustrated notes
+
+ Anything I make that has a painterly and loose hand-drawn feel was made
+ in Procreate on the iPad or Photoshop on the Wacom Cintiq. Or probably
+ a combination – it's easy to move files back and forth between the two
+ and the tools they offer are very similar.
+
+ Illustrations like these...
+
+ Both of these applications allow you to draw in “raster” graphics,
+ meaning you paint pixels onto a canvas. They require a decent level of
+ hand-skills to make sure your lines aren't wobbly, although both
+ applications have smoothing features to help with that.
+
+ When I'm in Procreate I use a small selection of brushes I've gathered
+ over the years. It's hard for me to remember where they're all from,
+ and I've customised the majority of them to suit my personal prefs.
+ Most of them were originally from Max Ulichney's brushes. I have the
+ essentials set ($2), the painters set ($8), and the comics set ($15),
+ and can vouch they're all great.
+
+ I move these pieces to Photoshop if I want to work on a larger screen,
+ or have accidentally enlarged the canvas to a 14000px wide sprawling
+ set of sketches that Procreate can't open without crashing.
+
+2. Polished vector illustrations
+
+ Illustrations that look more “polished” are made primarily in Adobe
+ Illustrator, with a touch of Photoshop at the end for lighting effects
+ and texture.
+
+ Pieces like these...
+
+ These illustrations are all vector-based, meaning we use mathematical
+ curves to define their shapes, rather than painted pixels. Vectors are
+ great for create hard, crisp edges and working with perfect geometric
+ forms.
+
+ While I love vectors for laying down the foundation shapes of these,
+ I'll move them over the Photoshop once they're 90% done to adjust the
+ colors, add more subtlety to the lighting and shadows, and chuck a bit
+ of texture on the top so they feel more tangible.
+
+ Want to share? (BUTTON) Tell Twitter About It
+
+3 Backlinks
+
+Why You Own an iPad and Still Can't Draw
+
+ The failure of drawing materials without mediums and meat
+
+Frequently Asked Questions
+
+ Questions I am often asked to answer
+
+The Best Illustration Books and Courses
+
+ My favourite resources for learning to draw and developing your visual
+ thinking skills
+
+Mentions around the web
+
+ Tomiwa 😃
+ Maggie Appleton - indieweb.social/@maggie
+ 2 Likes and Retweets
+
+Want to stay up to date?
+
+ (BUTTON) Subscribe via RSS Feed
+ © 2023 Maggie Appleton
+ * [8]The Garden
+ * [9]Essays
+ * [10]About
+ * [11]Notes
+ * [12]Now
+ * [13]Patterns
+ * [14]Library
+ * [15]Projects
+ * [16]Colophon
+
+References
+
+ Visible links:
+ 1. file:///rss.xml
+ 2. file:///
+ 3. file:///now
+ 4. file:///about
+ 5. file:///topics/how-to-illustrate
+ 6. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71674-9587TMP.html#im-a-promiscuous-polytooler
+ 7. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71674-9587TMP.html#workflows
+ 8. file:///garden
+ 9. file:///essays
+ 10. file:///about
+ 11. file:///notes
+ 12. file:///now
+ 13. file:///patterns
+ 14. file:///library
+ 15. file:///projects
+ 16. file:///colophon
+
+ Hidden links:
+ 18. https://github.com/MaggieAppleton
+ 19. https://uk.linkedin.com/in/maggieappleton
+ 20. https://dribbble.com/mappleton
+ 21. https://twitter.com/Mappletons
+ 22. https://indieweb.social/@maggie
diff --git a/static/archive/maggieappleton-com-fube9k.txt b/static/archive/maggieappleton-com-fube9k.txt
new file mode 100644
index 0000000..98f5697
--- /dev/null
+++ b/static/archive/maggieappleton-com-fube9k.txt
@@ -0,0 +1,135 @@
+ #[1]Main RSS Feed
+
+ [2]Home
+ The Garden (BUTTON)
+ [3]Now
+ [4]About
+ (BUTTON)
+
+ Essays
+
+ budding
+
+Why You Own an iPad and Still Can't Draw
+
+ The failure of drawing materials without mediums and meat
+ * [5]How to Illustrate
+
+ Planted almost 3 years agoLast tended almost 3 years ago
+
+ (BUTTON) Back To Top
+
+ Assumed Audience
+
+ Anyone who thinks they can't draw, but would like to learn
+
+ They message me a lot.
+
+ Which iPad should I buy? What app do you use? What brush is that?
+ What size should my canvas be?
+
+ These questions aren't wrong. In fact they're perfectly reasonable.
+
+ I'm vocal about the fact many of my illustrations are made on in an app
+ called . I have a full post about my drawing equipment and workflows
+ over at
+ [6]What App is That?
+
+ How are you supposed to draw if you don't also have these fancy tools?
+
+ This is the tricky bit.
+
+ If you go out and buy yourself these same things, you'll have all the
+ right materials to draw. But that's only the dressing on the drawing
+ dish.
+ [7]
+
+What you have is Material without the Medium or the Meat
+
+ What on earth do I mean by material, medium, and meat?
+ __________________________________________________________________
+
+ [8]
+
+Moving past materials
+
+ Worrying about the materials should take up - at most - 10% of your
+ attention and concern. Focus 70% of your attention on learning the
+ medium while you're just starting out.
+
+ You can keep 20% of your focus on the Meat. But I wouldn't worry too
+ much about communicating original, profound ideas at first. Doing so in
+ addition to learning a whole new language is going to be overwhelming.
+
+ In the same way it's a bad idea to learn Spanish while simultaneously
+ trying to write a philosophy dissertation in it.
+
+ Once you get more comfortable “speaking" in visual language, you'll be
+ able to shift a much higher percentage of your attention onto the Meat.
+ You'll get to focus on The Thing You Want to Say, and know enough
+ visual language to say it well.
+
+ That's the ideal I'm currently striving for. To reach a point where the
+ Material is irrelevant, the Medium is a baked into my subconscious, and
+ I'm all about the Meat.
+
+ That's the goal. Don't let the shiny iPad reflection blind you.
+
+ Get past picking the Material. Focus on the Medium. Aim for the Meat.
+
+ Want to share? (BUTTON) Tell Twitter About It
+
+1 Backlinks
+
+The Best Illustration Books and Courses
+
+ My favourite resources for learning to draw and developing your visual
+ thinking skills
+
+Mentions around the web
+
+ Tomiwa 😃
+ Maggie Appleton - indieweb.social/@maggie
+ 2 Likes and Retweets
+
+Want to stay up to date?
+
+ (BUTTON) Subscribe via RSS Feed
+ © 2023 Maggie Appleton
+ * [9]The Garden
+ * [10]Essays
+ * [11]About
+ * [12]Notes
+ * [13]Now
+ * [14]Patterns
+ * [15]Library
+ * [16]Projects
+ * [17]Colophon
+
+References
+
+ Visible links:
+ 1. file:///rss.xml
+ 2. file:///
+ 3. file:///now
+ 4. file:///about
+ 5. file:///topics/how-to-illustrate
+ 6. file:///apps
+ 7. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L84552-9249TMP.html#what-you-have-is-material-without-the-medium-or-the-meat
+ 8. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L84552-9249TMP.html#moving-past-materials
+ 9. file:///garden
+ 10. file:///essays
+ 11. file:///about
+ 12. file:///notes
+ 13. file:///now
+ 14. file:///patterns
+ 15. file:///library
+ 16. file:///projects
+ 17. file:///colophon
+
+ Hidden links:
+ 19. https://github.com/MaggieAppleton
+ 20. https://uk.linkedin.com/in/maggieappleton
+ 21. https://dribbble.com/mappleton
+ 22. https://twitter.com/Mappletons
+ 23. https://indieweb.social/@maggie
diff --git a/static/archive/softwarecrisis-dev-7c7z9g.txt b/static/archive/softwarecrisis-dev-7c7z9g.txt
new file mode 100644
index 0000000..33c48d4
--- /dev/null
+++ b/static/archive/softwarecrisis-dev-7c7z9g.txt
@@ -0,0 +1,1069 @@
+ #[1]Out of the Software Crisis (Newsletter) [2]Out of the Software
+ Crisis (Newsletter)
+
+ [3]Out of the Software Crisis
+
+ Bird flying logo [4]Newsletter [5]Book [6]AI Book [7]Archive [8]Author
+
+Modern software quality, or why I think using language models for programming is
+ a bad idea
+
+ By Baldur Bjarnason
+
+ This essay is based on a talk I gave at [9]Hakkavélin, a hackerspace in
+ Reykjavík. I had a wonderful time presenting to a lovely crowd, full of
+ inquisitive and critically-minded people. Their questions and the
+ discussion afterwards led to a number of improvements and
+ clarifications as I turned my notes into this letter. This resulted in
+ a substantial expansion of this essay. Many of the expanded points,
+ such as the ones surrounding language model security, come directly
+ from these discussions.
+
+ Many thanks to all of those who attended. The references for the
+ presentation are also the references for this essay, which you can find
+ all the way down in the footnotes section.
+
+ The best way to support this newsletter or my blog is to buy one of my
+ books, [10]The Intelligence Illusion: a practical guide to the business
+ risks of Generative AI or [11]Out of the Software Crisis. Or, you can
+ buy them both [12]as a bundle.
+
+The software industry is very bad at software
+
+ Here’s a true story. Names withheld to protect the innocent.
+
+ A chain of stores here in Iceland recently upgraded their point-of-sale
+ terminals to use new software.
+
+ Disaster, obviously, ensued. The barcode scanner stopped working
+ properly, leading customer to be either overcharged or undercharged.
+ Everything was extremely slow. The terminals started to lock up
+ regularly. The new invoice printer sucked. A process that had been
+ working smoothly was now harder and took more time.
+
+ The store, where my “informant” is a manager, deals with a lot of
+ businesses, many of them stores. When they explain to their customers
+ why everything is taking so long, their answer is generally the same:
+
+ Ah, software upgrade. The same happened to us when we upgraded our
+ terminals.
+
+ This is the norm.
+
+ The new software is worse in every way than what it’s replacing.
+ Despite having a more cluttered UI, it seems to have omitted a bunch of
+ important features. Despite being new and “optimised”, it’s
+ considerably slower than what it’s replacing.
+
+ This is also the norm.
+
+ Switching costs are, more often than not, massive for business
+ software, and purchases are not decided by anybody who actually uses
+ it. The quality of the software disconnects from sales performance very
+ quickly in a growing software company. The company ends up “owning” the
+ customer and no longer has any incentive to improve the software. In
+ fact, because adding features is a key marketing and sales tactic, the
+ software development cycle becomes an act of intentional, controlled
+ deterioration.
+
+ Enormous engineering resources go into finding new ways to minimise the
+ deterioration—witness Microsoft’s “ribbon menu”, a widget invented
+ entirely to manage the feature escalation mandated by marketing.
+
+ This is the norm.
+
+ This has always been the norm, from the early days of software.
+
+ The software industry is bad at software. Great at shipping features
+ and selling software. Bad at the software itself.
+
+Why I started researching “AI” for programming
+
+ In most sectors of the software industry, sales performance and product
+ quality are disconnected.
+
+ By its nature software has enormous margins which further cushion it
+ from the effect of delivering bad products.
+
+ The objective impact of poor software quality on the bottom lines of
+ companies like Microsoft, Google, Apple, Facebook, or the retail side
+ of Amazon is a rounding error. The rest only need to deliver usable
+ early versions, but once you have an established customer base and an
+ experienced sales team, you can coast for a long, long time without
+ improving your product in any meaningful way.
+
+ You only need to show change. Improvements don’t sell, it’s freshness
+ that moves product. It’s like store tomatoes. Needs to look good and be
+ fresh. They’re only going to taste it after they’ve paid, so who cares
+ about the actual quality.
+
+ Uptime reliability is the only quality measurement with a real impact
+ on ad revenue or the success of enterprise contracts, so that’s the
+ only quality measurement that ultimately matters to them.
+
+ Bugs, shoddy UX, poor accessibility—even when accessibility is required
+ by law—are non-factors in modern software management, especially at
+ larger software companies.
+
+ The rest of us in the industry then copy their practices, and we mostly
+ get away with it. Our margins may not be as enormous as Google’s, but
+ they are still quite good compared to non-software industries.
+
+ We have an industry that’s largely disconnected from the consequences
+ of making bad products, which means that we have a lot of successful
+ but bad products.
+
+ The software crisis
+
+ Research bears this out. I pointed out in my 2021 essay [13]Software
+ Crisis 2.0 that very few non-trivial software projects are successful,
+ even when your benchmarks are fundamentally conservative and short
+ term.
+
+ For example, the following table is from [14]a 2015 report by the
+ Standish Group on their long term study in software project success:
+
+ SUCCESSFUL CHALLENGED FAILED TOTAL
+ Grand 6% 51% 43% 100%
+ Large 11% 59% 30% 100%
+ Medium 12% 62% 26% 100%
+ Moderate 24% 64% 12% 100%
+ Small 61% 32% 7% 100%
+
+ The Chaos Report 2015 resolution by project size
+
+ This is based on data that’s collected and anonymised from a number of
+ organisations in a variety of industries. You’ll note that very few
+ projects outright succeed. Most of them go over budget or don’t deliver
+ the functionality they were supposed to. A frightening number of large
+ projects outright fail to ship anything usable.
+
+ In my book [15]Out of the Software Crisis, I expanded on this by
+ pointing out that there are many classes and types of bugs and defects
+ that we don’t measure at all, many of them catastrophic, which means
+ that these estimates are conservative. Software project failure is
+ substantially higher than commonly estimated, and success if much rarer
+ than the numbers would indicate.
+
+ The true percentage of large software projects that are genuinely
+ successful in the long term—that don’t have any catastrophic bugs,
+ don’t suffer from UX deterioration, don’t end up having core issues
+ that degrade their business value—is probably closer to 1–3%.
+
+ The management crisis
+
+ We also have a management crisis.
+
+ The methods of top-down-control taught to managers are
+ counterproductive for software development.
+ * Managers think design is about decoration when it’s the key to
+ making software that generates value.
+ * Trying to prevent projects that are likely to fail is harmful for
+ your career, even if the potential failure is wide-ranging and
+ potentially catastrophic.
+ * When projects fail, it’s the critics who tried to prevent disaster
+ who are blamed, not the people who ran it into the ground.
+ * Supporting a project that is guaranteed to fail is likely to
+ benefit your career, establish you as a “team player”, and protects
+ you from harmful consequences when the project crashes.
+ * Teams and staff management in the software industry commonly
+ ignores every innovation and discovery in organisational
+ psychology, management, and systems-thinking since the early
+ sixties and operate mostly on management ideas that Henry Ford
+ considered outdated in the 1920s.
+
+ We are a mismanaged industry that habitually fails to deliver usable
+ software that actually solves the problems it’s supposed to.
+
+ Thus, [16]Weinberg’s Law:
+
+ If builders built buildings the way programmers wrote programs, then
+ the first woodpecker that came along would destroy civilization.
+
+ It’s into this environment that “AI” software development tools appear.
+
+ The punditry presented it as a revolutionary improvement in how we make
+ software. It’s supposed to fix everything.
+
+ —This time the silver bullet will work!
+
+ Because, of course, we have had such a great track record with
+ [17]silver bullets.
+
+ So, I had to dive into it, research it, and figure out how it really
+ worked. I needed to understand how generative AI works, as a system. I
+ haven’t researched any single topic to this degree since I finished my
+ PhD in 2006.
+
+ This research led me to write my book [18]The Intelligence Illusion: a
+ practical guide to the business risks of Generative AI. In it, I take a
+ broader view and go over the risks I discovered that come with business
+ use of generative AI.
+
+ But, ultimately, all that work was to answer the one question that I
+ was ultimately interested in:
+
+ Is generative AI good or bad for software development?
+
+ To even have a hope of answering this, we first need to define our
+ terms, because the conclusion is likely to vary a lot depending on how
+ you define “AI” or even "software development.
+
+ A theory of software development as an inclusive system
+
+ Software development is the entire system of creating, delivering, and
+ using a software project, from idea to end-user.
+
+ That includes the entire process on the development side—the idea,
+ planning, management, design, collaboration, programming, testing,
+ prototyping—as well as the value created by the system when it has been
+ shipped and is being used.
+
+ My model is that of [19]theory-building. From my essay on
+ theory-building, which itself is an excerpt from [20]Out of the
+ Software Crisis:
+
+ Beyond that, software is a theory. It’s a theory about a particular
+ solution to a problem. Like the proverbial garden, it is composed of
+ a microscopic ecosystem of artefacts, each of whom has to be treated
+ like a living thing. The gardener develops a sense of how the parts
+ connect and affect each other, what makes them thrive, what kills
+ them off, and how you prompt them to grow. The software project and
+ its programmers are an indivisible and organic entity that our
+ industry treats like a toy model made of easily replaceable lego
+ blocks. They believe a software project and its developers can be
+ broken apart and reassembled without dying.
+
+ What keeps the software alive are the programmers who have an
+ accurate mental model (theory) of how it is built and works. That
+ mental model can only be learned by having worked on the project
+ while it grew or by working alongside somebody who did, who can help
+ you absorb the theory. Replace enough of the programmers, and their
+ mental models become disconnected from the reality of the code, and
+ the code dies. That dead code can only be replaced by new code that
+ has been ‘grown’ by the current programmers.
+
+ Design and user research is an integral part of the mental model the
+ programmer needs to build, because none of the software components
+ ultimately make sense without the end-user.
+
+ But, design is also vital because it is, to reuse Donald G.
+ Reinertsen’s definition from Managing the Design Factory (p. 11),
+ design is economically useful information that generally only becomes
+ useful information through validation of some sort. Otherwise it’s just
+ a guess.
+
+ The economic part usually comes from the end-user in some way.
+
+ This systemic view is inclusive by design as you can’t accurately
+ measure the productivity or quality of a software project unless you
+ look at it end to end, from idea to end-user.
+ * If it doesn’t work for the end-user, then it’s a failure.
+ * If the management is dysfunctional, then the entire system is
+ dysfunctional.
+ * If you keep starting projects based on unworkable ideas, then your
+ programmer productivity doesn’t matter.
+
+ Lines of code isn’t software development. Working software,
+ productively used, understood by the developers, is software
+ development.
+
+A high-level crash course in language models
+
+ Language models, small or large, are today either used as autocomplete
+ copilots or as chatbots. Some of these language model tools would be
+ used by the developer, some by the manager or other staff.
+
+ I’m treating generative media and image models as a separate topic,
+ even when they’re used by people in the software industry to generate
+ icons, graphics, or even UIs. They matter as well, but don’t have the
+ same direct impact on software quality.
+
+ To understand the role these systems could play in software
+ development, we need a little bit more detail on what language models
+ are, how they are made, and how they work.
+
+ Most modern machine learning models are layered networks of parameters,
+ each representing its connection to its neighbouring parameters. In a
+ modern transformer-based language model most of these parameters are
+ floating point numbers—weights—that describe the connection. Positive
+ numbers are an excitatory connection. Negative numbers are inhibitory.
+
+ These models are built by feeding data through a tokeniser that breaks
+ text into tokens—often one word per token—that are ultimately fed into
+ an algorithm. That algorithm constructs the network, node by node,
+ layer by layer, based on the relationships it calculates between the
+ tokens/words. This is done in several runs and, usually, the developer
+ of the model will evaluate after each run that the model is progressing
+ in the right direction, with some doing more thorough evaluation at
+ specific checkpoints.
+
+ The network is, in a very fundamental way, a mathematical derivation of
+ the language in the data.
+
+ A language model is constructed from the data. The transformer code
+ regulates and guides the process, but the distributions within the data
+ set are what defines the network.
+
+ This process takes time—both collecting and managing the data set and
+ the build process itself—which inevitably introduces a cut-off point
+ for the data set. For OpenAI and Anthropic, that cut-off point is in
+ 2021. For Google’s PaLM2 it’s early 2023.
+ __________________________________________________________________
+
+ Aside: not a brain
+
+ This is very, very different from how a biological neural network
+ interacts with data. A biological brain is modified by input and
+ data—its environment—but its construction is derived from nutrition,
+ its chemical environment, and genetics.
+
+ The data set, conversely, is a deep and fundamental part of the
+ language model. The algorithm’s code provides the process while the
+ weights themselves are derived from the data, and the model itself is
+ dead and static during input and output.
+
+ The construction process of a neural network is called “training”,
+ which is yet another incredibly inaccurate term used by the industry.
+ * A pregnant mother isn’t “training” the fetus.
+ * A language model isn’t “trained” from the data, but constructed.
+
+ This is nonsense.
+
+ But this is the term that the AI industry uses, so we’re stuck with it.
+
+ A language model is a mathematical model built as a derivation of its
+ training data. There is no actual training, only construction.
+
+ This is also why it’s inaccurate to say that these systems are inspired
+ by their training data. Even though genes and nutrition make an
+ artist’s mind they are not in what any reasonable person would call
+ “their inspiration”. Even when they are sought out for study and
+ genuine inspiration, it’s our representations of our understanding of
+ the genes that are the true source of inspiration. Nobody sticks their
+ hand in a gelatinous puddle of DNA and spontaneously gets inspired by
+ the data it encodes.
+
+ Training data are construction materials for a language models. A
+ language model can never be inspired. It is itself a cultural artefact
+ derived from other cultural artefacts.
+
+ The machine learning process is loosely based on decades-old grossly
+ simplified models of how brains work.
+
+ A biological neuron is a complex system in its own right—one of the
+ more complex cells in an animal’s body. In a living brain, a biological
+ neuron will use electricity, multiple different classes of
+ neurotransmitters, and timing to accomplish its function in ways that
+ we still don’t fully understand. It even has its own [21]built-in
+ engine for chemical energy.
+
+ The brain as a whole is composed of not just a massive neural network,
+ but also layers of hormonal chemical networks that dynamically modify
+ its function, both granularly and as a whole.
+
+ The digital neuron—a single signed floating point number—is to a
+ biological neuron what a flat-head screwdriver is to a Tesla.
+
+ They both contain metal and that’s about the extent of their
+ similarity.
+
+ The human brain contains roughly 100 billion neuron cells, a layered
+ chemical network, and a cerebrovascular system that all integrate as a
+ whole to create a functioning, self-aware system capable of general
+ reasoning and autonomous behaviour. This system is multiple orders of
+ magnitude more complex than even the largest language model to date,
+ both in terms of individual neuron structure, and taken as a whole.
+
+ It’s important to remember this so that we don’t fall for marketing
+ claims that constantly imply that these tools are fully functioning
+ assistants.
+ __________________________________________________________________
+
+ The prompt
+
+ After all of this, we have a data set which can be used to generate
+ text in response to prompts.
+
+ Prompts such as:
+
+ Who was the first man on the moon?
+
+ The input phrase, or prompt, has no structure beyond the linguistic.
+ It’s just a blob of text. You can’t give the model commands or
+ parameters separately from other input. Because of this, if your model
+ lets a third party enter text, an attacker will always be able to
+ bypass whatever restrictions you put on it. Control prompts or prefixes
+ will be discovered and countermanded. Delimiters don’t work.
+ Fine-tuning the model only limits the harm, but doesn’t prevent it.
+
+ This is called a prompt injection and what it means is that model input
+ can’t be secured. You have to assume that anybody that can send text to
+ the model has full access to it.
+
+ Language models need to be treated like an unsecured client and only
+ very carefully integrated into other systems.
+
+ The response
+
+ What you’re likely to get back from that prompt would be something
+ like:
+
+ On July 20, 1969, Neil Armstrong became the first human to step on
+ the moon.
+
+ This is NASA’s own phrasing. Most answers on the web are likely to be
+ variations on this, so the answer from a language model is likely to be
+ so too.
+ * The moon landing happens to be a fact, but the language model only
+ knows it as a text.
+
+ The prompt we provided is strongly associated in the training data set
+ with other sentences that are all variations of NASA’s phrasing of the
+ answer. The model won’t answer with just “Neil Armstrong” because it
+ isn’t actually answering the question, it’s responding with the text
+ that correlates with the question. It doesn’t “know” anything.
+ * The language model is fabricating a mathematically plausible
+ response, based on word distributions in the training data.
+ * There are no facts in a language model or its output. Only
+ memorised text.
+
+ It only fabricates. It’s all “hallucinations” all the way down.
+
+ Occasionally those fabrications correlate with facts, but that is a
+ mathematical quirk resulting from the fact that, on average, what
+ people write roughly correlates with their understanding of a factual
+ reality, which in turn roughly correlates with a factual reality.
+
+ A knowledge system?
+
+ To be able to answer that question and pass as a knowledge system, the
+ model needs to memorise the answer, or at least parts of the phrase.
+
+ Because “AI” vendors are performing a sleight-of-hand here and
+ presenting statistical language synthesis engines as knowledge
+ retrieval systems, their focus in training and testing is on “facts”
+ and minimising “falsehoods”. The model has no notion of either, as it’s
+ entirely a language model, so the only way to square this circle is for
+ the model to memorise it all.
+ * To be able to answer a question factually, not “hallucinate”, and
+ pass as a knowledge system, the model needs to memorise the answer.
+ * The model doesn’t know facts, only text.
+ * If you want a fact from it, the model will need to memorise text
+ that correlates with that fact.
+
+ “Dr. AI”?
+
+ Vendors then compound this by using human exams as benchmarks for
+ reasoning performance. The problem is that bar exams, medical exams,
+ and diagnosis tests are specifically designed to mostly test rote
+ memorisation. That’s what they’re for.
+
+ The human brain is bad at rote memorisation and generally it only
+ happens with intensive work and practice. If you want to design a test
+ that’s specifically intended to verify that somebody has spent a large
+ amount of time studying a subject, you test for rote memorisation.
+
+ Many other benchmarks they use, such as those related to programming
+ languages also require memorisation, otherwise the systems would just
+ constantly make up APIs.
+ * Vendors use human exams as benchmarks.
+ * These are specifically designed to test rote memorisation, because
+ that’s hard for humans.
+ * Programming benchmarks also require memorisation. Otherwise, you’d
+ only get pseudocode.
+
+ Between the tailoring of these systems for knowledge retrieval, and the
+ use of rote memorisation exams and code generation as benchmarks, the
+ tech industry has created systems where memorisation is a core part of
+ how they function. In all research to date, memorisation has been key
+ to language model performance in a range of benchmarks.^[22][1]
+
+ If you’re familiar with storytelling devices, this here would be a
+ [23]Chekhov’s gun. Observe! The gun is above the mantelpiece:
+
+ 👉🏻👉🏻 memorisation!
+
+ Make a note of it, because those finger guns are going to be fired
+ later.
+
+ Biases
+
+ Beyond question and answer, these systems are great at generating the
+ averagely plausible text for a given prompt. In prose, current system
+ output smells vaguely of sweaty-but-quiet LinkedIn desperation and
+ over-enthusiastic social media. The general style will vary, but it’s
+ always going to be the most plausible style and response based on the
+ training data.
+
+ One consequence of how these systems are made is that they are
+ constantly backwards-facing. Where brains are focused on the present,
+ often to their detriment, “AI” models are built using historical data.
+
+ The training data encompasses thousands of diverse voices, styles,
+ structures, and tones, but some word distributions will be more common
+ in the set than others and those will end up dominating the output. As
+ a result, language models tend to lean towards the “racist grandpa who
+ has learned to speak fluent LinkedIn” end of the spectrum.^[24][2]
+
+ This has implications for a whole host of use cases:
+ * Generated text is going to skew conservative in content and
+ marketing copy in structure and vocabulary. (Bigoted, prejudiced,
+ but polite and inoffensively phrased.)
+ * Even when the cut-off date for the data set is recent, it’s still
+ going to skew historical because what’s new is also comparatively
+ smaller than the old.
+ * Language models will always skew towards the more common, middling,
+ mediocre, and predictable.
+ * Because most of these models are trained on the web, much of which
+ is unhinged, violent, pornographic, and abusive, some of that
+ language will be represented in the output.
+
+ Modify, summarise, and “reason”
+
+ The superpower that these systems provide is conversion or
+ modification. They can, generally, take text and convert it to another
+ style or structure. Take this note and turn it into a formal prose, and
+ it will! That’s amazing. I don’t think that’s a trillion-dollar
+ industry, but it’s a neat feature that will definitely be useful.
+
+ They can summarise text too, but that’s much less reliable than you’d
+ expect. It unsurprisingly works best with text that already provides
+ its own summary, such as a newspaper article (first paragraphs always
+ summarise the story), academic paper (the abstract), or corporate
+ writing (executive summary). Anything that’s a mix of styles, voices,
+ or has an unusual structure won’t work as well.
+
+ What little reasoning they do is entirely based on finding through
+ correlation and re-enacting prior textual descriptions of reasoning.
+ They fail utterly when confronted with adversarial or novel examples.
+ They also fail if you rephrase the question so that it no longer
+ correlates with the phrasing in the data set.^[25][3]
+
+ So, not actual reasoning. “Reasoning”, if you will. In other “AI” model
+ genres these correlations are often called “shortcuts”, which feels
+ apt.
+
+ To summarise:
+ * Language models are a mathematical expression of the training data
+ set.
+ * Have very little in common with human brains.
+ * Rely on inputs that can’t be secured.
+ * Lie. Everything they output is a fabrication.
+ * Memorise heavily.
+ * Great for modifying text. No sarcasm. Genuinely good at this.
+ * Occasionally useful for summarisation if you don’t mind being lied
+ to regularly.
+ * Don’t actually reason.
+
+Why I believe “AI” for programming is a bad idea
+
+ If you recall from the start of this essay, I began my research into
+ machine learning and language models because I was curious to see if
+ they could help fix or improve the mess that is modern software
+ development.
+
+ There was reason to be hopeful. Programming languages are more uniform
+ and structured than prose, so it’s not too unreasonable to expect that
+ they might lend themselves to language models. Programming language
+ output can often be tested directly, which might help with the
+ evaluation of each training run.
+
+ Training a language model on code also seems to benefit the model.
+ Models that include substantial code in their data set tend to be
+ better at correlative “reasoning” (to a point, still not actual
+ reasoning), which makes sense since code is all about representing
+ structured logic in text.
+
+ But, there is an inherent [26]Catch 22 to any attempt at fixing
+ software industry dysfunction with more software. The structure of the
+ industry depends entirely on variables that everybody pretends are
+ proxies for end user value, but generally aren’t. This will always tend
+ to sabotage our efforts at industrial self-improvement.
+
+ The more I studied language models as a technology the more flaws I
+ found until it became clear to me that odds are that the overall effect
+ on software development will be harmful. The problem starts with the
+ models themselves.
+
+ 1. Language models can’t be secured
+
+ This first issue has less to do with the use of language models for
+ software development and more to do with their use in software
+ products, which is likely to be a priority for many software companies
+ over the next few years.
+
+ Prompt injections are not a solved problem. OpenAI has come up with a
+ few “solutions” in the past, but none of them actually worked.
+ Everybody expects this to be fixed, but nobody has a clue how.
+
+ Language models are fundamentally based on the idea that you give it
+ text as input and get text as output. It’s entirely possible that the
+ only way to completely fix this is to invent a completely new kind of
+ language model and spend a few years training it from scratch.
+ * A language model needs to be treated like an unsecured client. It’s
+ about as secure as a web page form. It’s vulnerable to a new
+ generation of injection vulnerabilities, both direct and indirect,
+ that we still don’t quite understand.^[27][4]
+
+ The training data set itself is also a security hazard. I’ve gone into
+ this in more detail elsewhere^[28][5], but the short version is that
+ training data set is vulnerable to keyword manipulation, both in terms
+ of altering sentiment and censorship.
+
+ Again, fully defending against this kind of attack would seem to
+ require inventing a completely new kind of language model.
+
+ Neither of these issues affect the use of language models for software
+ development, but it does affect our work because we’re the ones who
+ will be expected to integrate these systems into existing websites and
+ products.
+
+ 2. It encourages the worst of our management and development practices
+
+ A language model will never question, push back, doubt, hesitate, or
+ waver.
+
+ Your managers are going to use it to flesh out and describe unworkable
+ ideas, and it won’t complain. The resulting spec won’t have any bearing
+ with reality.
+
+ People on your team will do “user research” by asking a language model,
+ which it will do even though the resulting research will be fiction and
+ entirely useless.
+
+ It’ll let you implement the worst ideas ever in your code without
+ protest. Ask a copilot “how can I roll my own cryptography?” and it’ll
+ regurgitate a half-baked expression of sha1 in PHP for you.
+
+ Think of all the times you’ve had an idea for an approach, looked up
+ how to do it on the web, and found out that, no, this was a really bad
+ idea? I have a couple of those every week when I’m in the middle of a
+ project.
+
+ Language models don’t deliver productivity improvements. They increase
+ the volume, unchecked by reason.
+
+ A core aspect of the theory-building model of software development is
+ code that developers don’t understand is a liability. It means your
+ mental model of the software is inaccurate which will lead you to
+ create bugs as you modify it or add other components that interact with
+ pieces you don’t understand.
+
+ Language model tools for software development are specifically designed
+ to create large volumes of code that the programmer doesn’t understand.
+ They are liability engines for all but the most experienced developer.
+ You can’t solve this problem by having the “AI” understand the codebase
+ and how its various components interact with each other because a
+ language model isn’t a mind. It can’t have a mental model of anything.
+ It only works through correlation.
+
+ These tools will indeed make you go faster, but it’s going to be
+ accelerating in the wrong direction. That is objectively worse than
+ just standing still.
+
+ 3. Its User Interfaces do not work, and we haven’t found interfaces that do
+ work
+
+ Human factors studies, the field responsible for designing cockpits and
+ the like, discovered that humans suffer from an automation bias.
+
+ What it means is that when you have cognitive automation—something that
+ helps you think less—you inevitably think less. That means that you are
+ less critical of the output than if you were doing it yourself. That’s
+ potentially catastrophic when the output is code, especially since the
+ quality of the generated code is, understandably considering how the
+ system works, broadly on the level of a novice developer.^[29][6]
+
+ Copilots and chatbots—exacerbated by anthropomorphism—seem to trigger
+ our automation biases.
+
+ Microsoft themselves have said that 40% of GitHub Copilot’s output is
+ committed unchanged.^[30][7]
+
+ Let’s not get into the question of how we, as an industry, put
+ ourselves in the position where Microsoft can follow a line of code
+ from their language model, through your text editor, and into your
+ supposedly decentralised version control system.
+
+ People overwhelmingly seem to trust the output of a language model.
+
+ If it runs without errors, it must be fine.
+
+ But that’s never the case. We all know this. We’ve all seen running
+ code turn out to be buggy as hell. But something in our mind switches
+ off when we use tools for cognitive automation.
+
+ 4. It’s biased towards the stale and popular
+
+ The biases inherent in these language models are bad enough when it
+ comes to prose, but they become a functional problem in code.
+ * Its JS code will lean towards React and node, most of it several
+ versions old, and away from the less popular corners of the JS
+ ecosystem.
+ * The code is, inevitably, more likely to be built around CommonJS
+ modules instead of the modern ESM modules.
+ * It won’t know much about Deno or Cloudflare Workers.
+ * It’ll always prefer older APIs over new. Most of these models won’t
+ know about any API or module released after 2021. This is going to
+ be an issue for languages such as Swift.
+ * New platforms and languages don’t exist to it.
+ * Existing data will outweigh deprecations and security issues.
+ * Popular but obsolete or outdated open source projects will always
+ win out over the up-to-date equivalent.
+
+ These systems live in the popular past, like the middle-aged man who
+ doesn’t realise he isn’t the popular kid at school any more. Everything
+ he thinks is cool is actually very much not cool. More the other thing.
+
+ This is an issue for software because our industry is entirely
+ structured around constant change. Software security hinges on it. All
+ of our practices are based on constant march towards the new and fancy.
+ We go from framework to framework to try and find the magic solution
+ that will solve everything. In some cases language models might help
+ push back against that, but it’ll also push back against all the very
+ many changes that are necessary because the old stuff turned out to be
+ broken.
+ * The software industry is built on change.
+ * Language models are built on a static past.
+
+ 5. No matter how the lawsuits go, this threatens the existence of free and
+ open source software
+
+ Many AI vendors are mired in lawsuits.^[31][8]
+
+ These lawsuits all concentrate on the relationship between the training
+ data set and the model and they do so from a variety of angles. Some
+ are based on contract and licensing law. Others are claiming that the
+ models violate fair use. It’s hard to predict how they will go. They
+ might not all go the same way, as laws will vary across industries and
+ jurisdictions.
+
+ No matter the result, we’re likely to be facing a major decline in the
+ free and open source ecosystem.
+ 1. All of these models are trained on open source code without payment
+ or even acknowledgement, which is a major disincentive for
+ contributors and maintainers. That large corporations might benefit
+ from your code is a fixture of open source, but they do
+ occasionally give back to the community.
+ 2. Language models—built on open source code—commonly replace that
+ code. Instead of importing a module to do a thing, you prompt your
+ Copilot. The code generated is almost certainly based on the open
+ source module, at least partially, but it has been laundered
+ through the language model, disconnecting the programmer from the
+ community, recognition, and what little reward there was.
+
+ Language models demotivate maintainers and drain away both resources
+ and users. What you’re likely to be left with are those who are
+ building core infrastructure or end-user software out of principle. The
+ “free software” side of the community is more likely to survive than
+ the rest. The Linux kernel, Gnome, KDE—that sort of thing.
+
+ The “open source” ecosystem, especially that surrounding the web and
+ node, is likely to be hit the hardest. The more driven the open source
+ project was by its proximity to either an employed contributor or
+ actively dependent business, the bigger the impact from a shift to
+ language models will be.
+
+ This is a serious problem for the software industry as arguably much of
+ the economic value the industry has provided over the past decade comes
+ from strip-mining open source and free software.
+
+ 6. Licence contamination
+
+ Microsoft and Google don’t train their language models on their own
+ code. GitHub’s Copilot isn’t trained on code from Microsoft’s office
+ suite, even though many of its products are likely to be some of the
+ largest React Native projects in existence. There aren’t many C++ code
+ bases as big as Windows. Google’s repository is probably one of the
+ biggest collection of python and java code you can find.
+
+ They don’t seem to use it for training, but instead train on
+ collections of open source code that contain both permissive and
+ copyleft licences.
+
+ Copyleft licences, if used, force you to release your own project under
+ their licence. Many of them, even non-copyleft, have patent clauses,
+ which is poison for quite a few employers. Even permissive licences
+ require attribution, and you can absolutely get sued if you’re caught
+ copying open source code without attribution.
+
+ Remember our Chekhov’s gun?
+
+ 👉🏻👉🏻 memorisation!
+
+ Well, 👉🏻👉🏻 pewpew!!!
+
+ Turns out blindly copying open source code is problematic.
+ Whodathunkit?
+
+ These models all memorise a lot, and they tend to copy what they
+ memorise into their output. [32]GitHub’s own numbers peg verbatim
+ copies of code that’s at least 150 characters at 1%^[33][9], which is
+ roughly the same, in terms of verbatim copying, as what you seem to get
+ in other language models.
+
+ For context, that means that if you use a language model for
+ development, a copilot or chatbot, three or four times a day, you’re
+ going to get a verbatim copy of open source code injected into your
+ project about once a month. If every team member uses one, then
+ multiply that by the size of the team.
+
+ GitHub’s Copilot has a feature that lets you block verbatim copies.
+ This obviously requires both a check, which slows the result down, and
+ it will throw out a bunch of useful results, making the language model
+ less useful. It’s already not as useful as it’s made out to be and
+ pretty darn slow so many people are going to turn off the “please don’t
+ plagiarise” checkbox.
+
+ But even GitHub’s checks are insufficient. The keyword there is
+ “verbatim”, because language models have a tendency to rephrase their
+ output. If GitHub Copilot copies a GPLed implementation of an algorithm
+ into your project but changes all the variable names, Copilot won’t
+ detect it, it’ll still be plagiarism and the copied code is still under
+ the GPL. This isn’t unlikely as this is how language models work.
+ Memorisation and then copying with light rephrasing is what they do.
+
+ Training the system only on permissively licensed code doesn’t solve
+ the problem. It won’t force your project to adopt an MIT licence or
+ anything like that, but you can still be sued if it’s discovered.
+
+ This would seem to give Microsoft and GitHub a good reason not to train
+ on the Office code base, for example. If they did, there’s a good
+ chance that a prompt to generate DOCX parsing code might “generate” a
+ verbatim copy of the DOCX parsing code from Microsoft Word.
+
+ And they can’t have that, can they? This would both undercut their own
+ strategic advantage, and it would break the illusion that these systems
+ are generating novel code from scratch.
+
+ This should make it clear that what they’re actually doing is
+ strip-mine the free and open source software ecosystem.
+
+ How much of a problem is this?
+
+ —It won’t matter. I won’t get caught.
+
+ You personally won’t get caught, but your employer might, and
+ Intellectual Property scans or similar code audits tend to come up at
+ the absolute worst moments in the history of any given organisation:
+ * During due diligence for an acquisition. Could cost the company and
+ managers a fortune.
+ * In discovery for an unrelated lawsuit. Again, could cost the
+ company a fortune.
+ * During hacks and other security incidents. Could. Cost. A. Fortune.
+
+ “AI” vendors won’t take any responsibility for this risk. I doubt your
+ business insurance covers “automated language model plagiarism”
+ lawsuits.
+
+ Language models for software development are a lawsuit waiting to
+ happen.
+
+ Unless they are completely reinvented from scratch, language model code
+ generators are, in my opinion, unsuitable for anything except for
+ prototypes and throwaway projects.
+
+So, obviously, everybody’s going to use them
+
+ * All the potentially bad stuff happens later. Unlikely to affect
+ your bonuses or employment.
+ * It’ll be years before the first licence contamination lawsuits
+ happen.
+ * Most employees will be long gone before anybody realises just how
+ much of a bad idea it was.
+ * But you’ll still get that nice “AI” bump in the stock market.
+
+ What all of these problems have in common is that their impact is
+ delayed and most of them will only appear in the form of increased
+ frequency of bugs and other defects and general project chaos.
+
+ The biggest issue, licence contamination, will likely take years before
+ it starts to hit the industry, and is likely to be mitigated by virtue
+ of the fact that many of the heaviest users of “AI”-generated code will
+ have folded due to general mismanagement long before anybody cares
+ enough to check their code.
+
+ If you were ever wondering if we, as an industry, were capable of
+ coming up with a systemic issue to rival the Y2K bug in scale and
+ stupidity? Well, here you go.
+
+ You can start using a language model, get the stock market bump,
+ present the short term increase in volume as productivity, and be long
+ gone before anybody connects the dots between language model use and
+ the jump in defects.
+
+ Even if you purposefully tried to come up with a technology that played
+ directly into and magnified the software industry’s dysfunctions you
+ wouldn’t be able to come up with anything as perfectly imperfect as
+ these language models.
+
+ It’s nonsense without consequence.
+
+ Counterproductive novelty that you can indulge in without harming your
+ career.
+
+ It might even do your career some good. Show that you’re embracing the
+ future.
+
+ But…
+
+ The best is yet to come
+
+ In a few years’ time, once the effects of the “AI” bubble finally
+ dissipates…
+
+ Somebody’s going to get paid to fix the crap it left behind.
+
+ The best way to support this newsletter or my blog is to buy one of my
+ books, [34]The Intelligence Illusion: a practical guide to the business
+ risks of Generative AI or [35]Out of the Software Crisis. Or, you can
+ buy them both [36]as a bundle.
+ __________________________________________________________________
+
+ 1. There’s quite a bit of papers that either highlight the tendency to
+ memorise or demonstrate a strong relationship between that tendency
+ and eventual performance.
+ + [37]An Empirical Study of Memorization in NLP (Zheng & Jiang,
+ ACL 2022)
+ + [38]Does learning require memorization? a short tale about a
+ long tail. (Feldman, 2020)
+ + [39]When is memorization of irrelevant training data necessary
+ for high-accuracy learning? (Brown et al. 2021)
+ + [40]What Neural Networks Memorize and Why: Discovering the
+ Long Tail via Influence Estimation (Feldman & Zhang, 2020)
+ + [41]Question and Answer Test-Train Overlap in Open-Domain
+ Question Answering Datasets (Lewis et al., EACL 2021)
+ + [42]Quantifying Memorization Across Neural Language Models
+ (Carlini et al. 2022)
+ + [43]On Training Sample Memorization: Lessons from Benchmarking
+ Generative Modeling with a Large-scale Competition (Bai et al.
+ 2021)
+ [44]↩︎
+ 2. See the [45]Bias & Safety card at [46]needtoknow.fyi for
+ references. [47]↩︎
+ 3. See the [48]Shortcut “Reasoning” card at [49]needtoknow.fyi for
+ references. [50]↩︎
+ 4. Simon Willison has been covering this issue [51]in a series of blog
+ posts. [52]↩︎
+ 5.
+ + [53]The poisoning of ChatGPT
+ + [54]Google Bard is a glorious reinvention of black-hat SEO
+ spam and keyword-stuffing
+ [55]↩︎
+ 6. See, for example:
+ + [56]Asleep at the Keyboard? Assessing the Security of GitHub
+ Copilot’s Code Contributions (Hammond Pearce et al., December
+ 2021)
+ + [57]Do Users Write More Insecure Code with AI Assistants?
+ (Neil Perry et al., December 2022)
+ [58]↩︎
+ 7. This came out [59]during an investor event and was presented as
+ evidence of the high quality of Copilot’s output. [60]↩︎
+ 8.
+ + [61]Getty Images v. Stability AI - Complaint
+ + [62]Getty Images is suing the creators of AI art tool Stable
+ Diffusion for scraping its content
+ + [63]The Wave of AI Lawsuits Have Begun
+ + [64]Copyright lawsuits pose a serious threat to generative AI
+ + [65]GitHub Copilot litigation
+ + [66]Stable Diffusion litigation
+ [67]↩︎
+ 9. Archived link of the [68]GitHub Copilot feature page. [69]↩︎
+
+ Baldur Bjarnason May 30th, 2023
+
+Join the Newsletter
+
+ Subscribe to the Out of the Software Crisis newsletter to get my weekly
+ (at least) essays on how to avoid or get out of software development
+ crises.
+
+ Join now and get a free PDF of three bonus essays from Out of the
+ Software Crisis.
+
+ ____________________
+ (BUTTON)
+ Subscribe
+
+ We respect your privacy.
+
+ Unsubscribe at any time.
+
+ [70]Mastodon [71]Twitter [72]GitHub [73]Feed
+
+References
+
+ 1. file:///index.xml
+ 2. file:///feed.json
+ 3. file:///
+ 4. file:///
+ 5. https://softwarecrisis.baldurbjarnason.com/
+ 6. https://illusion.baldurbjarnason.com/
+ 7. file:///archive/
+ 8. file:///author/
+ 9. https://www.hakkavelin.is/
+ 10. https://illusion.baldurbjarnason.com/
+ 11. https://softwarecrisis.baldurbjarnason.com/
+ 12. https://baldurbjarnason.lemonsqueezy.com/checkout/buy/cfc2f2c6-34af-436f-91c1-cb2e47283c40
+ 13. https://www.baldurbjarnason.com/2021/software-crisis-2/
+ 14. https://standishgroup.com/sample_research_files/CHAOSReport2015-Final.pdf
+ 15. https://softwarecrisis.baldurbjarnason.com/
+ 16. https://quoteinvestigator.com/2019/09/19/woodpecker/
+ 17. http://worrydream.com/refs/Brooks-NoSilverBullet.pdf
+ 18. https://illusion.baldurbjarnason.com/
+ 19. https://www.baldurbjarnason.com/2022/theory-building/
+ 20. https://softwarecrisis.baldurbjarnason.com/
+ 21. https://en.wikipedia.org/wiki/Mitochondrion
+ 22. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn1
+ 23. https://en.wikipedia.org/wiki/Chekhov's_gun
+ 24. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn2
+ 25. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn3
+ 26. https://en.wikipedia.org/wiki/Catch-22_(logic)
+ 27. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn4
+ 28. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn5
+ 29. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn6
+ 30. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn7
+ 31. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn8
+ 32. https://archive.ph/2023.01.11-224507/https://github.com/features/copilot#selection-19063.298-19063.462:~:text=Our latest internal research shows that about 1% of the time, a suggestion may contain some code snippets longer than ~150 characters that matches the training set.
+ 33. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fn9
+ 34. https://illusion.baldurbjarnason.com/
+ 35. https://softwarecrisis.baldurbjarnason.com/
+ 36. https://baldurbjarnason.lemonsqueezy.com/checkout/buy/cfc2f2c6-34af-436f-91c1-cb2e47283c40
+ 37. https://aclanthology.org/2022.acl-long.434
+ 38. https://doi.org/10.1145/3357713.3384290
+ 39. https://doi.org/10.1145/3406325.3451131
+ 40. https://papers.nips.cc/paper/2020/hash/1e14bfe2714193e7af5abc64ecbd6b46-Abstract.html
+ 41. https://aclanthology.org/2021.eacl-main.86
+ 42. https://arxiv.org/abs/2202.07646
+ 43. https://dl.acm.org/doi/10.1145/3447548.3467198
+ 44. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref1
+ 45. https://needtoknow.fyi/card/bias/
+ 46. https://needtoknow.fyi/
+ 47. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref2
+ 48. https://needtoknow.fyi/card/shortcut-reasoning/
+ 49. https://needtoknow.fyi/
+ 50. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref3
+ 51. https://simonwillison.net/series/prompt-injection/
+ 52. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref4
+ 53. https://softwarecrisis.dev/letters/the-poisoning-of-chatgpt/
+ 54. https://softwarecrisis.dev/letters/google-bard-seo/
+ 55. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref5
+ 56. https://doi.org/10.48550/arXiv.2108.09293
+ 57. https://doi.org/10.48550/arXiv.2211.03622
+ 58. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref6
+ 59. https://www.microsoft.com/en-us/Investor/events/FY-2023/Morgan-Stanley-TMT-Conference#:~:text=Scott Guthrie: I think you're,is now AI-generated and unmodified
+ 60. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref7
+ 61. https://copyrightlately.com/pdfviewer/getty-images-v-stability-ai-complaint/?auto_viewer=true#page=&zoom=auto&pagemode=none
+ 62. https://www.theverge.com/2023/1/17/23558516/ai-art-copyright-stable-diffusion-getty-images-lawsuit
+ 63. https://www.plagiarismtoday.com/2023/01/17/the-wave-of-ai-lawsuits-have-begun/
+ 64. https://www.understandingai.org/p/copyright-lawsuits-pose-a-serious
+ 65. https://githubcopilotlitigation.com/
+ 66. https://stablediffusionlitigation.com/
+ 67. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref8
+ 68. https://archive.ph/2023.01.11-224507/https://github.com/features/copilot#selection-19063.298-19063.462:~:text=Our latest internal research shows that about 1% of the time, a suggestion may contain some code snippets longer than ~150 characters that matches the training set.
+ 69. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L83622-2637TMP.html#fnref9
+ 70. https://toot.cafe/@baldur
+ 71. https://twitter.com/fakebaldur
+ 72. https://github.com/baldurbjarnason
+ 73. file:///feed.xml
diff --git a/static/archive/taylor-town-5siv9a.txt b/static/archive/taylor-town-5siv9a.txt
new file mode 100644
index 0000000..e68a91f
--- /dev/null
+++ b/static/archive/taylor-town-5siv9a.txt
@@ -0,0 +1,191 @@
+ [1]taylor.town
+
+ [2]about [3]now [4]hire [5]rss [6]spam
+
+ cloaca maxima
+
+ When to Build Millennia Sewers
+
+ In the mid-1800s, [7]every building in central Chicago was raised 10ft
+ (30m). Yes, they literally used [8]jackscrews to lift entire city
+ blocks up one-by-one.
+
+ Chicago had to [9]hotfix production because they built the city on the
+ shoreline of Lake Michigan, where filth accumulated without natural
+ drainage. They lifted the entire city after it was built so they could
+ add sewers and prevent flooding.
+
+ For comparison, Rome’s [10]Cloaca Maxima (“Greatest Sewer”) is still
+ in-use after 2,400 years.
+
+ So why didn’t Chicago just build it right the first time?
+ * [11]Irreversible Decisions
+ * [12]Unintended vs. Unforeseen
+ * [13]Always Scale Down
+ * [14]Labor & Materials
+ * [15]Awful Architecture
+
+Irreversible Decisions
+
+ Some decisions are consequential and irreversible or nearly
+ irreversible – one-way doors – and these decisions must be made
+ methodically, carefully, slowly, with great deliberation and
+ consultation. If you walk through and don’t like what you see on the
+ other side, you can’t get back to where you were before. We can call
+ these Type 1 decisions. But most decisions aren’t like that – they
+ are changeable, reversible – they’re two-way doors. If you’ve made a
+ suboptimal Type 2 decision, you don’t have to live with the
+ consequences for that long. You can reopen the door and go back
+ through. Type 2 decisions can and should be made quickly by high
+ judgment individuals or small groups.
+
+ As organizations get larger, there seems to be a tendency to use the
+ heavy-weight Type 1 decision-making process on most decisions,
+ including many Type 2 decisions. The end result of this is slowness,
+ unthoughtful risk aversion, failure to experiment sufficiently, and
+ consequently diminished invention. We’ll have to figure out how to
+ fight that tendency.
+
+ – [16]Jeff Bezos
+
+ The Cloaca Maxima didn’t magically start out as the Greatest Sewer. It
+ began as an open-air canal, then was modified and renovated and
+ connected to the aqueducts.
+
+ The Romans probably made mistakes, but they didn’t make any wrong
+ irreversible decisions. To build something that lasts, make sure the
+ architecture is correct where it counts.
+
+ The Chicago sewage disaster was technically reversible, but extremely
+ expensive and painful.
+
+ Put “wiggle-room” in your architecture. Plan for repairs. Add
+ backdoors, engine-hoods, seams, and spaces. Emergency plans are
+ generally cheap to include in early phases of design.
+
+Unintented vs. Unforeseen
+
+ [17]Exxon executives knew that CO₂ emissions would harm Earth.
+
+ Exxon willfully ignored its own research. Climate change was unintended
+ but not unforeseen.
+
+ Prophets are silenced when apocalypses seem bad for business.
+
+ But remember – all apocalypses are opportunities for entrepeneurship.
+ Exxon could’ve made billions by diversifying themselves with renewable
+ energy. They acted against their own self-interest by ignoring their
+ facts.
+
+ To prevent long-term disaster, solve the hard problem of aligning
+ incentives. Build systems so that all constituents predict and prevent
+ impending doom.
+
+ Transparency thwarts [18]own goals. It’s difficult to do stupid things
+ when you do stupid things publicly.
+
+Always Scale Down
+
+ There’s really two ways to design things. You can either sort of
+ start with small things and scale them up or you could start with
+ big things and scale them down…
+
+ So suppose you want to build a system for like 10,000 people to use
+ simultaneously. One way of doing it would be to start with the
+ system, design it for 10 people and test it like that and scale it
+ up 10,000. The other way would be to design it for like 100,000,000
+ people – I mean do the design for that – and then scale it down to
+ tens of thousands. You might not get the same architecture. You
+ might get a completely different architecture. In fact, you would
+ get a different architecture.
+
+ And I think it’s a really bad idea to start at a design for 10 or
+ 100 things and scale it up. It’s better to start with an
+ architecture that you know will work for a few trillion things and
+ scale it down. It will actually be less efficient when you’ve got
+ your 10,000 things than when you scaled up, but you’ll know that
+ you’ll be able to scale it up later. So it’s good.
+
+ So rather than ask, “how do we get to five nines?”, let’s make it
+ more interesting! Let’s start at 9,999 nines reliability and scale
+ it down.
+
+ – Joe Armstrong from [19]Systems that run forever and self-heal and
+ scale
+
+ If you can afford it, throw a few extra zeroes on your designs.
+
+Labor & Materials
+
+ Carefully compare lifetime, labor, and materials.
+
+ lifetime repair labor materials
+ asphalt 20 years moderate $ $
+ concrete 30 years difficult $ $$
+ stone 100+ years easy $$$$ $$$
+
+ Pay particular attention to labor – 9 women can’t make a baby in 1
+ month.
+
+ Exercise for the reader: Which is cheaper, a Nespresso machine or a
+ [20]percolator?
+
+Awful Architecture
+
+ Sometimes there are no tradeoffs.
+
+ Some decisions are awful in every dimension.
+
+ [21]Dvorak keyboards reduce finger fatigue using the same materials as
+ QWERTY keyboards.
+
+ [22]Juicero famously launched a high-tech product that was inferior to
+ traditional juicers [23]in every comparable way:
+
+ After taking apart the device, venture capitalist Ben Einstein
+ considered the press to be “an incredibly complicated piece of
+ engineering”, but that the complexity was unnecessary and likely
+ arose from a lack of cost constraints during the design process. A
+ simpler and cheaper implementation, suggested Einstein, would likely
+ have produced much the same quality of juice at a price several
+ hundred dollars cheaper.
+
+ If you want to create lasting sewers, study sewer architecture and its
+ impacts. What do good sewers have in common? What do bad sewers look
+ like? What tradeoffs exist with sewage systems? Are there any
+ promising-yet-untested sewer designs? Why do sewers go into disrepair?
+ What societal factors prevent sewers from being made in the first
+ place? Who truly controls the sewers?
+
+ Great architects think ahead, but don’t let ambitions run amok. They
+ anticipate irreversible changes and second-order effects. They consider
+ all the costs – labor and materials and maintenance and environmental
+ impact. They always stay ahead-of-schedule and within their budget. And
+ despite the overwhelming constraints, great architects build millennia
+ sewers whenever and wherever they can.
+
+References
+
+ 1. file:///
+ 2. file:///about
+ 3. file:///now
+ 4. file:///hire-me
+ 5. file:///feed.xml
+ 6. https://newsletter.taylor.town/
+ 7. https://en.wikipedia.org/wiki/Raising_of_Chicago
+ 8. https://en.wikipedia.org/wiki/Jack_(device)#House_jack
+ 9. https://www.reddit.com/r/ProgrammerHumor/comments/blhec6/fixing_bugs_in_production/
+ 10. https://en.wikipedia.org/wiki/Cloaca_Maxima
+ 11. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L81887-9224TMP.html#irreversible
+ 12. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L81887-9224TMP.html#unintended
+ 13. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L81887-9224TMP.html#scale-down
+ 14. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L81887-9224TMP.html#labor-materials
+ 15. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L81887-9224TMP.html#awful
+ 16. https://www.sec.gov/Archives/edgar/data/1018724/000119312516530910/d168744dex991.htm
+ 17. https://en.wikipedia.org/wiki/ExxonMobil_climate_change_denial
+ 18. https://en.wikipedia.org/wiki/Own_goal
+ 19. https://www.youtube-nocookie.com/embed/cNICGEwmXLU?start=433
+ 20. https://en.wikipedia.org/wiki/Coffee_percolator
+ 21. https://en.wikipedia.org/wiki/Dvorak_keyboard_layout
+ 22. https://en.wikipedia.org/wiki/Juicero
+ 23. https://en.wikipedia.org/wiki/Juicero#Criticism
diff --git a/static/archive/timharek-no-ah7ilz.txt b/static/archive/timharek-no-ah7ilz.txt
new file mode 100644
index 0000000..69266be
--- /dev/null
+++ b/static/archive/timharek-no-ah7ilz.txt
@@ -0,0 +1,142 @@
+ [1]Skip to content
+ * [2]Blog
+ * [3]Connect
+ * [4]About
+
+ * [5]Index
+ * [6]Blog
+ * My thoughts on Helix after 6 months
+
+My thoughts on Helix after 6 months
+
+ Published June 19, 2023 — 3 minute read
+ Photo of Tim Hårek Andreassen Tim Hårek Andreassen
+
+ Back in [7]January I decided to try out Helix as my primary editor and
+ today I have almost been using it for 6 months and these are my
+ thoughts.
+
+[8]# What I like
+
+[9]# Keystrokes
+
+ Helix lives in the opposite land when it comes to keystrokes in
+ comparison to Vim, and it was only difficult for the first couple of
+ days. I’ve become fond of the way to navigate around.
+
+[10]# Minor modes
+
+ I really like that there are more modes, called [11]“Minor modes”, and
+ the reason why I like them are that whenever I initate a mode there is
+ a subtle pop-up in the lower-right corner with the available actions
+ with the activated mode. This is super helpful when you are first
+ learning Helix and when you are doing something you don’t do on a
+ regular basis. It lowers the chance of having to switch context in
+ order to do something. For instance, I know that m activates “Match
+ mode”, but sometimes I may forget how to select around specific
+ selector like (), but with Helix I will have a little helper that tells
+ me that the next key is a and then the next helper will help me select
+ just ().
+
+[12]# Moving around
+
+ I’ve become really fond of the idea that every move-action is also a
+ selection/highlight, I find that I miss that feature whenever I edit
+ server-configs via SSH or somewhere else when I’m not in Helix. It
+ feels natural after a while because you get used to moving around
+ text/code with w and e.
+
+[13]# Configuration
+
+ No more Vimscript and Lua, just plaintext TOML! The documentation for
+ how to configure the editor is great and most of the defaults are also
+ great! My editor-config is just 23 lines in contrast to my
+ Neovim-config which is 209 lines long.
+
+[14]# Language server protocol (LSP) support
+
+ I had some experience with this from Neovim, but it felt cumbersome
+ having to configure everything. With Helix I can simply run hx --health
+ markdown and see what LSP is required for Markdown.
+$ hx --health markdown
+Configured language server: marksman
+Binary for language server: /opt/homebrew/bin/marksman
+Configured debug adapter: None
+Highlight queries: ✓
+Textobject queries: ✘
+Indent queries: ✘
+
+ I even managed to get it working with Deno thanks to its documentation
+ on how to use custom LSPs for specific languages.
+
+[15]# What I don’t like
+
+ There really isn’t anything in particualr that I don’t like about
+ Helix. I really miss having it installed on servers by default, but I
+ completely understand that that is a big ask 😅 It’s not too difficult
+ to swap between Vim-bindings and Helix-bindings for short sessions.
+
+[16]# Conclusion
+
+ Helix is fun and easy! I highly recommend Helix if you:
+ * want to try a new editor,
+ * tired of configuring {Neo}vim with Vimscript/Lua,
+ * or been thinking about trying out Vim, but been hesitant because of
+ the modes.
+
+ I will continue to use Helix for the forseeable future, I’m looking
+ forward to what future updates will bring!
+
+ Remember to check out Helix’s tutor, hx --tutor for quick introduction
+ to its keystrokes and interactions.
+
+ Tagged with [17]100 days to
+ offload[18]helix[19]software[20]thoughts[21]tools
+ 540 words
+ [22]Reply via e-mail
+
+Also mentioned in
+
+ * [23]June 2023
+
+ Last deploy: 2023-07-02 11:14 UTC
+
+ * [24]Stats
+ * [25]Privacy
+ * [26]Sitemap
+ * [27]RSS
+
+References
+
+ Visible links:
+ 1. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#main
+ 2. https://timharek.no/blog/
+ 3. https://timharek.no/connect/
+ 4. https://timharek.no/about/
+ 5. https://timharek.no/
+ 6. https://timharek.no/blog/
+ 7. https://timharek.no/blog/trying-helix/
+ 8. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#what-i-like
+ 9. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#keystrokes
+ 10. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#minor-modes
+ 11. https://docs.helix-editor.com/keymap.html#normal-mode
+ 12. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#moving-around
+ 13. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#configuration
+ 14. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#language-server-protocol-lsp-support
+ 15. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#what-i-don-t-like
+ 16. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L71669-427TMP.html#conclusion
+ 17. https://timharek.no/tags/100-days-to-offload/
+ 18. https://timharek.no/tags/helix/
+ 19. https://timharek.no/tags/software/
+ 20. https://timharek.no/tags/thoughts/
+ 21. https://timharek.no/tags/tools/
+ 22. mailto:tim@harek.no?subject=RE: My thoughts on Helix after 6 months
+ 23. https://timharek.no/blog/2023-june-recently/
+ 24. https://timharek.no/stats/
+ 25. https://timharek.no/privacy/
+ 26. https://timharek.no/sitemap/
+ 27. https://timharek.no/rss.xml
+
+ Hidden links:
+ 29. https://timharek.no/
+ 30. https://timharek.no/blog/my-thoughts-on-helix-after-6-months/
diff --git a/themes/v2/assets/css/style.scss b/themes/v2/assets/css/style.scss
index 3df8c62..59ba576 100644
--- a/themes/v2/assets/css/style.scss
+++ b/themes/v2/assets/css/style.scss
@@ -49,6 +49,12 @@ ul {
}
}
+ol {
+ margin-left: 3ch;
+ padding: 0;
+}
+
+
blockquote {
border-left: 1ch solid #ddd;
font-style: italic;
@@ -70,6 +76,7 @@ footer {
sup {
line-height: 0;
+ font-size: 0.8em;
}
figure {
@@ -90,7 +97,7 @@ figure {
}
}
-.references {
+.references, .footnotes {
font-size: 0.8em;
h3 {