Last updated: April 21, 2021 01:22 PM (All times are UTC.)

April 21, 2021

April 20, 2021

We are uncovering better ways of developing
software by doing it and helping others do it.

It’s been 20 years since those words were published in the manifesto for agile software development, and capital-A Agile methods haven’t really been supplanted. Despite another two decades of doing it and helping others do it.

That seems problematic.

April 19, 2021

April 16, 2021

I’ve spent about a year working on an app for a group in the University where I work, that needed to be available on both Android and iOS. I’ve got a bit of experience working with the Apple-supplied SDKs on iOS, and a teensy amount of experience working with the Google-supplied SDKs on Android. Writing two apps is obviously an option, but not one I took very seriously. The other thing I’ve reached for before in this situation is React Native, where I’ve got a little experience but quite a bit of understanding having worked with React some.

Anyway, this project was a mobile companion for a desktop app written in C# and Windows Forms, and the client was going to have to pick up development at the end of my engagement. So I decided that the best approach for the client was to learn how to do it in Xamarin.Forms, and give them a C# project they could understand at the end. I also hoped there’d be an opportunity to share some code from the desktop software in the mobile project, though this didn’t pan out in the end.

It took a while to understand the centrality of the Model-View-ViewModel idea and how to get it to work with the code I was writing, rather than bludgeoning it in to what I was trying to do. Ultimately lots of X.F works with data bindings, where you say “this thing and that thing are connected” and so your view needs a that thing so it can display this thing. If the that thing isn’t in the right shape, is derived somehow, or shouldn’t be committed to the model until some other things are done, the ViewModel sits in the middle and separates the two.

I’m used to this model in a couple of contexts, and I’ll give Objective-C examples of each because that’s how old I am. In web applications, you can use data bindings to fill in parts of an HTML document based on values from a server-side object. WebObjects works this way (Rails doesn’t, it uses code to fill in parts of etc). The difference between web app data bindings and mobile app data bindings is one of lifecycle. Your value needs to be read once when the page (or XHR) is rendered, and stored once when the user posts the changes. This is so simple that you can use straightforward accessor methods for it. It also happens at a time when loading new content is happening, so any timing constraints are likely to come from elsewhere.

You can also do it in what, because I’m that old, I’ll call rich client applications, like Xamarin.Forms mobile apps or Cocoa Bindings desktop apps. Here, anything could be happening at any time: a worker thread could be updating the model, and the user could interact with the UI, all at the same time, potentially multiple times while a UI element is live. So you can’t just wait until the Submit button is pressed to update everything, you need to track and reflect updates when they happen.

Given a dynamic language like Objective-C, you can say “bind this thing to that thing with these options” and the binding library can rewrite your accessors for this thing and that thing to update the other when changes happen, and avoid circular updates. You can’t do that in C# because apparently more typing is easier to reason about, so you end up replicating the below pattern rather a lot.

public class MyThingViewModel : INotifyPropertyChanged
  public event PropertyChangedEventHandler PropertyChanged;
  // ...
  private string _value;
  public string Value
    get => _value;
      _value = value;
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));

And when I say “rather a lot”, I mean in this one app that boilerplate appears at least 126 times, this undercounts because despite being public, the PropertyChanged event can only be invoked by instances of the declaring class so if a subclass adds any properties or any change points, you’re going to write protected helper methods to be able to invoke the event from the subclass.

Let’s pivot to investigating another question: why is Cocoa Bindings a desktop-only thing from Apple? I’ve encountered two problems in using it on Xamarin: thread confinement and performance. Thread confinement is a problem anywhere but the performance things are more sensitive on mobile, particularly on 2007-era mobile when this decision was made, and I can imagine a choice was made between “give developers the tools to identify and fix this issue” and “don’t give developers the chance to encounter this issue” back when UIKit was designed. Neither X.F nor UIKit is wrong in their particular choice, they’ve just chosen differently.

UI updates have to happen on the UI thread, probably because UIKit is Cocoa, Cocoa is appkit, and appkit ran on an OS that didn’t give you an easy way to do multiple threads per task. But this has to happen on Android too. And also performance. Anyway, theoretically any of those 126 invocations of PropertyChanged that could be bound to a view (so all of them, because separation of concerns) should be MainThread.BeginInvokeOnMainThread(() => {PropertyChanged?.Invoke(...)}); because what if the value is updated in an async method or a Task. Otherwise, something between a crash and unexpected behaviour will happen.

The performance problem is this: any change to a property can easily cause an unknown amount of code to run, quite often on the UI thread. For example, my app has a data grid (i.e. spreadsheet-like table view) with a “selection” column containing switches. There’s a “select all” button, and a report of the number of selected objects, outside the grid. Pressing “select all” selects all of the objects. Each one notifies observers that its IsSelected property has changed, which is watched by the list view model to update the selection count, and by the data grid to update the switches. So if there’s one row in the grid, selecting all causes two main-thread UI updates. If there are 500 rows, then 1000 updates need to run on the main thread in response to that one button action.

That can get slow :). Before I understood how to fix this, some UI actions would block the UI for tens of seconds as they computed the update. I asked about this in some forums and was told the answer is “your users shouldn’t have that much data in a mobile app, design an app with less data” which is not that helpful. But luckily the folks over at SyncFusion were much more empathetic, and told me the real solution is to design your views and view models such that you can turn off updates while you’re doing some big change, then turn them back on and recalculate the state at the end.

Like I say, it’s likely that someone at Apple already knew this from the Cocoa Bindings times and decided “here’s a great technology, and here’s how to turn it off because it will get in your way” wasn’t a cool story.

April 15, 2021

April 13, 2021

April 12, 2021

A statement from our CEO and Founder, Bruc:

At Facebruce, we strongly disapprove of the recent data leak of 50 million account details. There’s nothing more important to us than your data. Really, nothing. Have you any idea of how much we could have charged people for the information about you that is now out there, available for free, on Torrent sites and on Russian servers?

We had a deal almost signed to show messages to all people who fast during Ramadan, saying “Want some free money? Just send us your home address!”, paid for by “Patriots for the Second Amendment and Jesus”. Of course, it isn’t the money that drives us, it’s that Facebruce is facilitating community by introducing two groups. At Facebruc, we love spreading love and connection, so need to raise a little money to run the service.

So, please, trust us with your data, and click ‘Like’ to keep our engagement figures riding high as our share price!

Next on feed: LGBT+ folks! Send us your address to get a free Rainbow Pride t-shirt! (sponsored by Westboro Baptists)

April 07, 2021

When not confined to my house during a pandemic I am usually out and about. This. can be anything from just. wandering about with friends, to galleries/museums (V& A and Hayward are my faves). I amlucky in my job that I get to see a lot of theatre and my favourite. thing to do on […]

April 06, 2021

April 01, 2021

I’d like to start by recapping the three distinct categories of interest in software freedom. This is definitely my categorisation, though only the third is novel and the first two have long histories of common recognition so this is hardly Humpty-Dumptyism on my part.

Free Software
The extension of freedoms of expression and engagement into the digital space. Free Software, sometimes “Libre Software” because of the confusion over the word “Free”‘s multiple definitions, is based on the ideas that a computer is property like any other artefact and that working with, playing with, and socialising via computers are personal pursuits like any other pursuits, and that the freedom from external interference with those enjoyments should be the same as in non-computer interests.
Open Source
The rephrasing of the ideas of Free Software to improve acceptance in (particularly American) business circles. Open Source as described is almost identical to the Debian project’s ideas of Free Software, but with the words “Open Source” instead of “Free Software” and the words “Debian software component” removed. The first reason for the rename is that Freedom implies either zero cost, which mid-1990s American business didn’t like, or social good, same. The second reason is that mid-1990s American businesses had come around to ideas of interoperability under the banner Open Systems, and Open Source sounds sort of like that a bit.
Open Sores
The co-opting of the technical aspects of Open Source (or, nearly equivalently, Free Software) without any of the freedom benefits, typically with the goal of providing zero-cost software development and associated professional services to for-profit companies. When a company CTO says “we love open source”, they typically mean that they love open sores: that they love how skilled developers from across the world will gladly sign CLAs transferring rights to exploit their creations to the company in return for a lighter green square on the proprietary software-as-a-service platform Github.

This is all pre-amble to a discussion of #uninstallman, the internet pressure mob removing the leadership of the Free Software Foundation over objectionable statements made by its founder, former president, and recently-surprise-reinstated board member, Richard M. Stallman (rms).

Let’s start with the obvious: the Free Software Foundation has not demonstrated good leadership over this matter. Clearly rms’s statements have distracted the conversation away from software freedom, and the FSF have not taken enough steps with enough publicity to resolve this issue and to get people talking about software freedom again[*]. The FSF has not even given clear enough separation between their policy and rms’s personal views for it to be obvious that anyone else on their board has any views, or control over policy.

It is right that the FSF take a critical look at their management, and ask whether the people who are leading the Foundation are the best people to promote the idea of software freedom.

Unfortunately, we are now at the point where whatever the outcome, software freedom has lost and Open Sores will fill the ideological vacuum. Because if software freedom is about the extension of existing freedoms into the online space, and the baying mob are calling for the blood of someone who said a thing questioning the definitions of words related to the actions of someone who was associated with someone who did known bad things, and for the blood of any other people who are associated with that person, it is easy to argue that the whole software freedom movement is hypocritical. You claim to support freedom of expression, and yet you actually deny the right for anyone to express views that disagree with your own? Where’s the unity of purpose?

Bradley Kuhn, policy fellow at the Software Freedom Conservancy, has talked about the damaging impact of rms’s personal views on the software freedom movement back in 2019, when this controversy was fresh; and in 2018 which is arguably where it started (to become public). He has also talked about the need to maintain a big tent; that being principled on your core issue gives you the legitimacy to take principled stands on other issues.

Taking an authoritarian, only-say-what-I-permit line on expression doesn’t leave any legitimacy to support freedom of expression in the software field. Unfortunately, if the FSF and more generally the software freedom community is unable to maintain principle on this argument, it will lose the right to be taken seriously on matters of software freedom. And then, the organisations who take the Open Sores line on software licensing will step up to fill the leadership vacuum. The business interest “Foundations” who think that software freedom means the freedom for big businesses to control the revenue stream while everybody gets to build their products for free. And then it may be decades before there is another software freedom movement with any legitimacy, and they may have to start from scratch.

[*] Arguably the software freedom movement was already in a difficult state, because the freedoms proposed were only really adopted by a small community with a technical interest in the details relating to those freedoms: a few tens of thousands of technologists, some intellectual property lawyers, and a small number of others. But that’s more about the difficulty of developing a mass movement and of translating the theory into activism, and doesn’t necessarily reflect badly on the characters or actions of any of the leaders in the movement.

Reading List 274 by Bruce Lawson (@brucel)

March 26, 2021

March 25, 2021

One person per task by Graham Lee

One of the least teamy things I see with software teams is limiting the maximum and minimum number of items of work in process – tasks, stories, whatever you call them – both to the number of developers on the team. For some reason it’s always the number of devs, never the number of product owners, customers, QAs, or deployment people. Got four devs? Then there should be four tasks in process!

This approach is surprisingly backward given that we’re all supposed to have come so far as the leaders of the Agile Fourth Industrial Revolution 2.0 that we’ve internalised and transcended Goldratt’s theory of constraints. It’s the last holdout of the old Taylorian school of management. Everybody is working full-tilt, so if anyone runs into any trouble then everybody else is too busy to help them. If what they’re doing is upstream of anybody else’s work, then they are going to be blocked too, but rather than fix the blockage they’ll pull another task because one-person-per-task at all times!

So much is this at the core of software team thinking that when I’ve suggested in informal discussions that maybe we should do something else, people are confused. Are you saying that we should have a developer who isn’t assigned to a task, just in case? What does that person do the rest of the time, play Minesweeper? As if the only alternative to “one person per task” is “one person per task but perhaps there is another person”.

One person per task has the “nobody can help” disadvantage already mentioned. In fact, people are disincentivised from helping, because their task has their name on it and your task has your name on it. Did issue #1348 miss the release train? Bob is such a drag on the team, at least Karen managed to ace her ticket. Maybe we should reevaluate who leads on the next project.

You’ll see other effects of one person per task. Code reviews fall into one of two categories: “LGTM” and “axe to grind”. Only the people who are really invested in making sure that nobody ever misses off a const keyword, or uses function() where => would suffice, will take the time to commit to code reviews. Everybody else will skim-read, look at the CI output to see if the tests pass, and get back to their own task with their own name on it as quickly as possible. This loses both the review benefit of code review, and the shared-understanding-of-the-code benefit too. Everyone only really understands the features they worked on individually, there just happens to be a big ball of those features in one repo.

Code quality suffers. Each individual is too busy chopping down trees to sharpen the saw, because there’s always a next task for each developer to do.

Everybody else has been under-resourced. We need one developer per task, because what I can see is features in a UI and the only people shovelling features are the devs. QA is a cost centre, so if we can get one QA (or at most, one per team) then let’s do that. Same with ops. Infosec, coaching, UX, and other nice-to-haves can be consultants as needed. Weird how our devs are ticking off tasks like billy-O, and nothing’s getting through to release!

The alternative to “one person per task” is not “one person per task and some change”. It’s “one objective per team”. Set the goal, and let people work out what to do about it and how everyone contributes. As they used to say, “give them the environment and support they need, and trust them to get the job done”.

March 24, 2021

March 21, 2021

A statement from our CEO and Founder, Bruc.

“Look, I”m fed up at people complaining about Facebruce allegedly “facilitating” genocide. Since we began, we’ve always been about connecting people–initially some nerds to chicks we rated as hot, but now it’s about connecting everybody. We’d like to teach the world to sing, in perfect harmony.

Unfortunately, not everyone wants to sing in perfect harmony. Some people, we are shocked to learn, aren’t actually very nice people. How were we at Facebruce to know what would happen when our algorithms repeatedly recommended members of The Hutu Machete Enthusiasts Club also join the Death To Tutsi Cockroaches group?

We’re not in the content policing business. There’s simply too much of it. And anyway, we’re just a platform. We already have thousands of servers running 24/7 to weed out pictures of nipples (women’s nipples, to be precise) so your Auntie Martha doesn’t clutch her pearls, because offending people in high ARPU markets leads to a drop in engagement.

So there was literally no way for us to know that the Death To Tutsi Cockroaches group was not simply a pest control company. I even went so far as to attempt to verify this, by walking around the HQ trying to find an African person to ask whether cockroaches are a problem, but there was no-one matching that description in the boardroom.

Facebruce is about building communities. We are very active in the GraphQHell community and the Reactionary community. In fact, only last week, we offered free afterhours use of a meeting room in our fifty storey gold-plated HQ to host a meeting of GraphQHell Engineers Against Killing Rohingyas, and even sponsored $100 of pizza for attendees. This shows that we’re taking real action and putting real resources into counteracting Hate Speech on the Facebruce platform.

So that’s cleared up then. Be sure to press “Like!” to demonstrate engagement.”

Next on Timeline: Why Covid is a hoax – evidence from the Protocols of the Elders of Zion!

March 19, 2021

March 18, 2021

March 16, 2021

March 12, 2021

Reading List 273 by Bruce Lawson (@brucel)

March 08, 2021

March 07, 2021

The Vizzini Effect by Graham Lee

A bunch of the topics I wanted to discuss all turned out to have a common basis, so I’m going to write the post about the commonality using a couple of examples from the specific topics for illumination. Maybe I’ll come back to those topics in more depth later, each one is itself interesting and valuable.

The common thing is the Vizzini Effect, named after the Sicilian in the Princess Bride. In the movie/book, Vizzini often describes events as “inconceivable,” to which Inigo Montoya replies “you keep using that word. I do not think it means what you think it means”. The Vizzini Effect in software engineering (and undoubtedly in other fields of endeavour too, I doubt we’re special) is when the same thing happens: a word or phrase seems to adopt a different meaning such that two different people, or two different groups of people, can mean it to use different things without either seeming malicious or disingenuous. In the examples I’m going to explore here, those groups are separated by time rather than space. But unlike with Vizzini, it’s not that one person is using a word in a weird way, but that collectively software engineers seem to have decided it takes a different meaning.

Examples of Vizzini Phrases

Object-Oriented Programming

OOP is perhaps the ur-example here, and definitely the one with the most obvious dog-whistle. “I invented the term Object-Oriented Programming,” says Alan Kay, “and I can tell you I did not have C++ in mind”. To Alan and that early group of Smalltalk programmers at Xerox, ParcPlace, Tektronix etc., object-oriented programming was extreme late binding and decoupling through message sending. These days, it is often programming in any language that has a “class” keyword, or a straw man meaning any form of mutable state.


In the discussion do you think Agile/Scrum is beneficial for software delivery?, the first answer (at time of writing) says “The whole thing was designed to give non-technical people more power over the ones who spent a lifetime honing their craftmanship.” The question asks about the surprising rituals and the extra layers of bureaucracy. That’s the opposite impression than the one I have, where pre-existing software engineering methods tried to minimise or even automate away the programmer contributions. The lightweight methods, promoted by (among others) the agile alliance, sought to build projects around motivated individuals, giving the support they needed but leaving them alone to get the job done. The alliance members thought that the best architectures and designs were created by self-organising teams: a far cry from imposing methodologies to remove power from technical contributors.

Design Patterns

Design Patterns in software used to refer to the Christopher Alexander idea of identifying repeating problems in architecture and building a shared language that succinctly communicates understanding of the problem, solutions selected, and trade-offs in those solutions. These days it seems to mean any of the examples of design patterns in the Gang of Four book on early-OOP implementation patterns, and no others.

Free Software

The Free Software Foundation and the GNU project were created with the goal of extending desirable human rights and liberties to the world of computing. These days it seems to mean “open source, but said by a person who uses the word actually a lot”.

Open Source

The Open Source Initiative was created to generalise the Debian Free Software Guidelines out from the Debian project to general business rules for software, based on the prior successful Open Systems movement and the liberties identified in the Free Software Movement. These days it pretty much means making the components needed to build SaaS subscription products available at zero cost.

Software Engineering

In 1967, software engineering was a provocative term, meant to imply that the art of creating software would be somewhat improved if it had a socio-scientific basis. These days software engineering is two words anyone who gets or wants to get paid for programming uses on their CV/résumé.

What happened?

My impression is that three things changed, and that two of them are almost the same. The origins of all of these phrases are in particular times in history, made by particular people, talking in specific contexts. Time has changed, which has changed the context (or at least the relevance of the original context), the people who said the things have changed, and so many new people have entered the field that a majority of practitioners no longer know who the original people were, nor have experienced the context in which they spoke.

It’s entirely possible, for example, that the agile methodologies which were lightweight reactions to software engineering around 2000 are oppressively bureaucratic in 2021. We expect to be able to release software multiple times per day now, using analytics and telemetry to understand in real time how it’s being used. The agile folks wanted us to release up to every two weeks and to talk to someone before doing it, ugh!

Some people talk about an Agile-Indu$trial Complex, suggesting that there’s some shady cabal of consultants and certification bodies conspiring to make us all agile so they can profit from it. Again, maybe true. Others talk of companies who “talk the talk without walking the walk”: they got the consultant in, decided which parts of this whole Agile thing sounded nice or relevant, and adopted those things then trumpeted their “fully agile workflow” on their websitesfax banners.

And, of course, there’s the telephone game. Even those of us who heard about it from the horse’s mouth—maybe worked on an XP team, or read “Free Software, Free Society”—will have learned a slightly different thing than what the originators were trying to teach us, or thought they were teaching us. When telling others, we’ll have misremembered, and adapted, and extemporised. And so will the people who learned from us, and so on.

The telephone game is subject not only to slow evolution, but to a Byzantine Generals attack. If someone wants, for example, OOP to die so that their preferred paradigm get used instead, they can inject a false message into the call graph. This is where Vizzini meets Lewis Carroll’s Humpty-Dumpty: I keep using this word, and I do not think it means what you think it means.

Take into account the fact that most people who work in software now didn’t work in software five years ago, and that this was true five years ago and so on, and you realise that the vast majority of people will have learned about any “classic” idea in software from a telephone conversation.

What to do?

Well, the first question to answer is, does anything particularly need to be done? Maybe these are ideas that have had their time, and can just fizzle out. But evidently for all of the examples above enough people want the ideas to continue that they (well, we obviously) keep trying to dredge the original discussions out of the history books and put them back into contemporary discourse. To do this, they need recontextualising. For example, nobody cares that Richard Stallman couldn’t get a printer driver in the 1970s, but maybe they do care that there are things that they aren’t allowed to do with the smartphones they think they paid for. That’s how ideas of software freedom could be reintroduced.

Maybe the original phrase has become toxic and needs to be retired, without the original meaning being lost too. That is, whether you like it or not, the reason that “Open Source” was created as a term: to remove deliberate and accidental confusion over the word “freedom” in a business context, and to provide familiarity to people who had already adopted Open Systems ideas. It’s why Devops exists: to tell the stories of Agile again, but to those who didn’t listen the first time, or who listened and heard the wrong thing.

The telephone game can’t be avoided. You have to keep telling the stories if you want new people to hear them, and that means accepting alterations in their re-telling. And you need there to be more than one raconteur, even if they’re telling slightly different versions of the story. Don’t count messiahs, count prophets. Only don’t count prophets, count gospels. Only don’t count gospels, count churches. Only don’t count churches, count preachers.

You’re never going to get every programmer or software professional in the world to agree with your interpretation of some phrase. But you can use contextually-relevant stories to tell people things that might help them make better software, and you can follow up “I do not think that means what you think it means” with a conversation in which you both learn something. Maybe it’s your understanding that’s wrong?



I do a lot of writing, podcasting, presenting, and streaming about how to make software. Most of it has been free, still is free, and I don’t intend to change that. It’d be great if you are able and willing, for you to support that free work by becoming a patron. No obligation!

March 04, 2021

February 28, 2021

February 2021 by James Nutt (@zerosumjames)

Why isn’t my site serving assets via HTTP/2?

Status: unresolved

The front-end chapter of The Ruby on Rails Performance Apocrypha urges us to enable HTTP/2 in our Cloudfront distributions. It turns out HTTP/2 is enabled by default on Cloudfront distributions since around September 2007. Which is neat, we should be taking advantage of it already. So I check that it’s ticked in our distribution (it is) and then load some assets via Firefox. And it says in the header that they’re being served with HTTP/1.1. What the heck. Chrome seems to be happily fetching assets from our Cloudfront distribution over HTTP/2. Why isn’t Firefox?

So I check the CanIUse page on HTTP/2, and it suggests that many browsers (except prominently Safari) only support HTTP/2 when the server is capable of negotiating via ALPN.

It’s not that, since Chrome is working. And it turns out, so is Firefox, if I use an incognito window.

Not storing secrets in your ENV


Things I Read

February 26, 2021

Reading List 272 by Bruce Lawson (@brucel)

February 22, 2021

From Idea to Fruition by Daniel Hollands (@limeblast)

With my review of the Ooznest WorkBee CNC being published in Hackspace Magazine last week, I figured this would be a good time to run though the general process I follow when designing for, and running jobs on, the CNC.

I have to admit, I’m not entirely sure where the idea for the eventual design came from, I just know I wanted something personal, which could act as a portfolio piece for Monumental Me.

It didn’t start life as a fully formed concept, rather a vague idea of two sets of footprints to represent Lucy and I.

I’m no artist, but I’m slowly getting better at pulling third party assets into (hopefully) cohesive designs. More often than not I find myself browsing VectorStock, which I’ve come to rely on as an indispensable resource, and a further source of inspiration.

This is where the idea of the cat prints going off on their own came from, as the asset already existed, and perfectly represented the head-strong nature of Apricat – so all I needed to do was import the asset and incorporate it into the design.

Affinity Designer is my tool of choice for producing the bulk of my designs. I’m barely scratching the surface of what it can do, but each time I boot it up, I learn something new.

For this particular design, I had an asset which featured something like 10 different pairs of feet, from which I chose the ones I liked the best, being sure to choose different shaped feet for the each of us, and then set about positioning each foot print individually.

The design gets exported from Affinity Designer as an SVG, which I import into Vectric VCarve. This powerful, yet really simple to use tool, makes it really easy to calculate the gcode toolpaths required by the CNC, all while providing a really accurate 3D representation of what the final design will look like.

It’s not a cheap piece of software, but it does a hell of a lot of heavy lifting, meaning that even a complete novice such as myself can produce excellent results.

Back in the real world, after applying a layer of vinyl, I’ll secure the stock I’m using to the spoilerboard on the CNC using some screws (I need a better camping method, but this will do for now), then will run the job via my workshop laptop.

Ear and eye protection are of paramount importance, as is my attention to the job as it runs, to ensure nothing goes wrong. On more than one occasion I’ve had a small miscalculation cause the job to go askew, forcing me to perform an emergency stop. Thankfully, these are becoming more and more rare, as I learn from my mistakes.

This is where the layer of vinyl applied in the previous step helps by providing a mask over any parts of the display we don’t want paint on.

A healthy coat of sanding sealer is applied to the surface to help prevent the paint bleeding into the grain, then I let lose with the spray paint, being sure to apply it from all angles to ensure the whole of the carved section is covered.

Once the paint is dry and the vinyl removed, and I do a light sanding. I don’t want to be too aggressive at this point or I’ll sand away some of the more intricate details of the carving.

This is followed by a coat of Danish Oil, which helps the natural beauty of the wood to show through, while providing a small amount of protection. You can apply up to three or four coats, but I typically leave it at one for anything which is designed for display purposes, rather than active use or handling.

No display is complete without the ability to hang it. I’ve tried using Command strips for mounting displays on the wall in the past, but the Danish oil stopped them from sticking very well, so I’ve started to use these sawtooth picture frame hangers.

Bang a nail in the wall, hang the display on it, step back, and enjoy your work.

February 14, 2021

Cap in Hand by Graham Lee

You’re probably aware that between this blog, De Programmatica Ipsum, and various books, I write a lot about software engineering and software engineers.

You may know that I also present a podcast on software engineering topics, and co-host two live streams on Amiga programming and Objective-C programming.

I do all of this because I want to. I want to engage in conversations about software engineering; I want to help my colleagues and peers; I want to pass on my experience to others. Of course, this all takes rather a lot of time, and a not-insignificant amount of money. Mostly in hosting fees, but also a surprising chunk on library memberships, purchase of out-of-print materials on software engineering, and event attendance. More than my academic (i.e. not-for-profit) salary was designed to withstand. None of these projects is ad-supported, and that’s not about to change.

I’ve launched a Patreon page, where if you enjoy anything I write, say, or show, you can drop me a little bit of cash to say thanks. There’s no obligation: nothing I currently make freely available is going behind a paywall, and I’m not planning any “subscriber-only content” in the future. All I’m saying is if you’ve enjoyed what I’ve been producing, and having my voice in the software engineering fray, here’s another way in which you can say thank you.

Yesterday, I received my first Covid vaccine. I was expecting to be in the next group of people invited, as I have multiple sclerosis, which is a disease in which my own immune system tries to kill me, and many Covid deaths are caused by the body’s own immune system. My good chum Stuart Langridge wrote up his vaccination experience; here’s mine.

Out of the blue I received an SMS on Friday morning:

Our records show that you are eligible for your COVID vaccination. Appointments are now available at Villa Park and Millennium Point. Book here:

Your GP Surgery.

The website is on a legit domain, and linked to a booking system run by, which was a pretty crap experience (which I reported to them); top tip: you need to have your NHS number to book, and if you don’t, you might lose your chosen slot and have to start all over again. And that was that; a confirmation SMS came through:

Confirmation of your appointment: Sat 13 Feb at 4:10pm at Villa Park, B6 6HE. You appointment at Villa Park COVID Vaccination Clinic is confirmed at Villa Park, Holte Suite, Trinity Road, Birmingham, B6 6HE.

Villa Park is the stadium for the worst Birmingham football team, so it was nice that something positive was going to happen there. As I approached in the car, there were plenty of temporary signposts to the Covid Vaccination Centre to help people find it.

Signpost: Villa park Covid 19 vaccination centre

I arrived 20 minutes early (I’m paranoid about missing appointments) and although the site had told me not to enter more than 10 minutes before my slot, it didn’t appear to be crowded so I went in. It was basically a big room with check-in desks around the perimeter and at least 20 vaccination stations in the centre. The bloke at the door told me to go up to checkin desk 12; the lady asked me for my reference number (I hadn’t been sent one), my NHS number (I hadn’t been told to bring it) and then my name and address.

After verifying that I had an appointment, she asked me to sit on one of the chairs placed 2 metres apart, facing her (so we weren’t all staring at people having their jabs while we waited, which was a thoughtful touch for those nervous of needles, like me).

me sitting in the waiting area

A friend had been vaccinated the day before at an alternate vaccination hub and there had been a clerical error which meant too many people had showed up, so it took her 3 hours from entering to leaving, so I’d bought a book. But I only had time to take the selfie above before a man came up and asked me to follow him to a vaccination station where an assistant was finishing cleaning the chair. I sat down, confirmed my name, and rolled up my sleeve.

The syringe was bigger than a flu jab and while I honestly felt no pain at all as the needle went in, it was in my arm for a few seconds as there was presumably more vaccine in there than the flu jab, which is pretty much instantaneous. Then the syringe-wielder told me that I had to wait in another area for 15 minutes before driving, laughed when I asked if I could have a sticker, but gave me the best sticker I’ve ever received:

sticker: I've had my Covid vaccination

I asked which vaccine I’d received; it was the Oxford one. She gave me an info leaflet, a card with a URL and a phone number for booking the second jab and graciously accepted my gratitude. By 16:06, four minutes before my appointment, I was sitting in the waiting area, reading my book for 15 minutes.

The whole thing was brilliant; calm, professional, well-organised and reassuring. Today my arm has a slight soreness (just like my annual flu jab) but I feel fine. Actually, I feel better than fine. I feel optimistic, for the first time in a year.

Doubtless, the government will try to claim this as their triumph. It isn’t. It’s a triumph of science and socialised public sector medicine. The government gave billions to private sector cronies for a test-and-trace fiasco and for the last ten years have underfunded the National Health Service. Many leading Conservatives have openly called for its privatisation. Remember that when the next election comes around.

Thank you, Science; thank you, social health care.

February 12, 2021

Reading List 271 by Bruce Lawson (@brucel)

February 11, 2021

Like every other thought-leader, I follow Mike Taylr on social media. Ever since Shingy left AOL, “Mikey” has moved to the top spot of everyone’s Twitter “Futurist Gurus” Twitter list. This morning I awoke to read Twitter abuzz with exictement over Mike’s latest Nolidge Bom:

Of course, like anyone who’s ever sat a maths exam and been told to “show your working out”, you know that the widely diverse interview panel of white 20-ish year old men is as interested in how you arrived at your answer as in the answer itself. Given Mikey’s standing in the industry and the efficiency of his personal branding consultants, this question will soon be common for those interviewing in Big Tech, as it’s an industry that prides itself on innovative disruption by blindly copying each other. So let’s analyse it.

It’s obvious that the real test is your choice of marker colour. So, how would you go about making the right decision? Obviously, that depends where you’re interviewing.

If you’re interviewing for Google or one of its wannabes, simply set up a series of focus groups to choose the correct shade of blue.

If you’re interviewing for Apple or its acolytes, sadly, white ink won’t work on a whiteboard, no matter how aesthetically satisfying that would be. So choose a boring metallic colour and confidently assert any answer you give with “I KNOW BEST”.

If you’re interviewing for Microsoft, the colour doesn’t matter; just chain the marker to the whiteboard and say “you can’t change the marker, it’s an integral part of the whiteboard”, even after it stops working.

If you’re interviewing for Facebook or one of its wannabes, trawl through previous posts by the panellists, cross reference it with those of their spouses, friends and their friends to find their favourite colours, factor in their Instagram posts, give a weighting to anything they’ve ever bought on a site they’ve signed in using Facebook, and use that colour while whispering “Earth is flat. Vaccines cause cancer. Trump is the saviour. Muslims are evil. Hire me” subliminally over and over again.

Good luck in the new job! May your stocks vest well.

February 09, 2021

(Last Updated on )

The other day I was tearing my hair out wondering why an HTML form I was debugging wouldn’t focus on the form field when I was tapping on the associated label. The HTML was fine:

<label for="squonk">What's your name, ugly?</label>
<input id="squonk">

I asked my good chum Pat “Pattypoo” Lauke for help, and without even looking at the form or the code, he asked “Does it turn off pointer events in the CSS?”

Lo and FFS, there it was! label {pointer-events:none;}! This daft bit of CSS breaks the browser default behaviour of an associated label, and makes the hit target smaller than it would otherwise be. Try clicking in the “What’s your name, ugly?” text:

Try me, I’m good

Try me, I’m crap

I’m jolly lucky to have the editor of the Pointer Events spec as my chum. But why would anyone ever do this? (That line of CSS, I mean, not edit a W3C spec; you do the editing for the sex and the glory.)

Once again, Pat whipped out his code ouija board:

And, yes—the presentation had originally been Material Design floating labels, and this line of CSS had been cargo-culted into the new design. So don’t disable pointer events on forms—and, while you’re at it, Stop using Material Design text fields!

The clown in Steven King's IT down a storm drain, saying 'We all float labels down here Georgie"

February 06, 2021

(Last Updated on )

That nice Marcy Sutton asked me to test and give feedback about a new product she’s involved with called Evinced, which describes itself as an “Enterprise grade digital accessibility platform for modern software development teams”. Quite what “enterprise grade” means is beyond me, but it’s basically software that can crawl a website from a root domain and check its code against some rules and report back. There are similar tools on the market, and I’ve recently been working with a Client to integrate Tenon into their workflow, so wanted to compare them.

“Now hang on!”, I hear you say. “automated tools are terrible!”. Well, yes and no. Certainly, overlays etc that claim to automatically fix the problems are terrible, but tools that help you identify potential problems can be very useful.

It’s also true that automated tools can’t spot every single accessibility error; they can tell you if an image is missing alternate text, but not that <img src=dog.png alt=”a cat”> has useless alt text. Only a human can find all the errors.

However, many errors are machine-findable. The most-common errors on WebAIM’s survey of the top million homepages are low contrast text, missing alternative text, empty links, missing form input labels, empty buttons and missing document language, all of which were found by running automated tests on them (which, presumably, the developers never did before they were pushed to production).

I personally feel that a good automated scanner is a worthwhile investment for any large site to catch the “lowest hanging fruit”. While some things can’t be automatically tested, other things can, and other aspects live in a grey area depending on the rigour of the test.

For example, a naive colour contrast test might compare CSS color with background-color, and give a pass or fail; a less naive test will factor in any CSS opacity set on the text and ignore off-screen/ hidden text. A sophisticated contrast test could take a screenshot of text over an image or gradient and do a pixel-by-pixel analysis. To do a test on a screenshot would require actually rendering a page. Like Tenon, Evinced doesn’t just scan the HTML, but renders the pages in a headless browser, which allows the DOM to be tested (although I don’t believe it tests colour contrast in this way).

Evinced uses Axe Core, and open-source library also used by Google Lighthouse. It also contains other (presumably proprietary secret-source) tests so that “if interactable components are built with divs, spans, or images – Evinced will detect if they are broken”.


The proof of the pudding with automated site scanners is how well they report errors they’ve found. It’s all very well reporting umpty-squllion errors, but if it’s not reported in any actionable way, it’s not helpful.

Like all the automated scanners I’ve tried, errors are grouped according to severity. However, if those categories correspond with WCAG A, AA and AAA violations, that’s not made clear anywhere.

Graph showing number of errors by type

It’s a fact of corporate life that most organisations will attempt to claim AA compliance, so need to know the errors by WCAG compliance.

One innovative and useful reporting method is by what Evinced calls component grouping: “Consolidates hundreds of issues to a handful of broken code components”.

With other scanners, it takes a trained eye to look through thousands of site-wide errors and realise that a good percentage of them are because of one dodgy piece of code that is repeated on every page. Evinced analyses pages and identifies these repeated components for you, so you know where to concentrate your efforts to get gross numbers down. (We all know that in the corporate world, a quick fix that reduces 10,000 errors to 5,000 errors buys you time to concentrate on the really gnarly remaining problems.)

graph showing 32% of all issues are grouped into 38 components; 1 component accounts for 81% of critical issues

There’s a vague suggestion that this grouping is done by Artificial Intelligence/ Machine Learning. The algorithm obviously has quite clever rules, and shows me a screenshot of areas on my pages it has identified as components. It’s unclear whether this is real Machine Learning, eg whether it will improve as its corpus of naughty pages gets larger.

list of components automatically identified on my site with screenshots and the relevant areas highlighted

I don’t recall signing anything to allow my data to be used to improve the corpus; perhaps a discount for not-for-profits/ time-limited demos could be offered to organisations allowing their data to be added to the training data, if indeed that’s how it “learns”.

User Interface

Many of these site scanners are made by engineers for engineers and have the similar high levels of UX one would expect from JavaScripters.

Tenon has some clunkers in its web interface (for example, it’s hard to re-run a previously defined scan) because it’s most commonly accessed via its API rather than web back-end.

Evinced makes it easy to re-run a scan from the web interface, and also promises an API (pricing is not announced yet) but also suffers from its UI. For example, one of my pet peeves is pages telling me I have errors but not letting me easily click to see them, requiring me to hunt. The only link in this error page, for example, goes to the “knowledge base” that describes the generic error, but not to a list of scanned pages containing the error.

Page showing how many errors I have but not linking to them

(After I gave feedback to the developers, they told me the info is there if you go to the components view. But that requires me to learn and remember that. Don’t make me think!)

There’s also terminology oddities. When setting up a new site for testing, the web interface requires a seed URL and to press a button marked “start mapping”, after which the term “mapping” is no longer used, and I’m told the system is “crawling”. Once the crawl was complete, I couldn’t see any results. It took a while for me to realise that “crawling” and “mapping” are the same thing (getting a list of candidate URLs) and after the mapping/ crawling stage, I need to then do a “scan”.

A major flaw is the ability to customise tests. In Tenon I can turn off tests on an adhoc basis if, for example, one particular test is giving me false positives, or I only want to test for level A failures. This is unavailable in Evinced’s web interface.

Another important but often-overlooked UI aspect of these “Enterprise” site scanners is the need to share results across the enterprise. While it’s common to sell “per-seat” licenses, it’s also necessary for the licensee to able to share information with managers, bean-counters, legal eagles and the like. Downloading a CSV doesn’t really help; it’s much more useful to be able to share a link to the results of a run and let the recipient investigate the reports and issues, but not let them change any configuration or kick off any new scans. This is missing in both Evinced and Tenon.


The system is currently in Beta and definitely needs some proper usability testing with real target users and UI love. One niggle is the inaccuracy of its knowledge base (linked from the error reports). For example, about the footer element, Evinced says

Since the <footer> element includes information about the entire document, it should be at the document level (e.g., it should not be a child element of another landmark element). There should be no more than one ><footer> element on the same document

This is directly contradicted by the HTML specification, which says

The footer element represents a footer for its nearest ancestor sectioning content or sectioning root element… Here is a page with two footers, one at the top and one at the bottom… Here is an example which shows the footer element being used both for a site-wide footer and for a section footer.

I saw no evidence of this incorrect assumption about the footer element in the tests, however.

All in all, the ability of Evinced to identify repeated ‘components’ and understand the intended use of some splodge of JavaScriptted labyrinth of divs is a welcome feature and its main selling point. It’s definitely one to watch when the UX is sleeker (presumably when it comes out of Beta).

February 05, 2021

Another day, another developer explaining that they don’t follow some popular practice. And their reason? Nothing more than because other people do the thing. “Best practices don’t exist,” they airily intone. “They’re really mediocre practices”.

In one sense, they’re correct. Best practices need to be evidence-based, and there’s precious little evidence in software engineering. In a regulated profession, you could avoid using accepted best practice, but if something went wrong and you ended up on the receiving end of a malpractice suit, you would lose.

So best practice as an argument in software engineering has two weaknesses: the first is that there’s no basis in evaluation of practice; and the second is that being a monetised hobby rather than a profession there’s no incentive to discover and adopt best practice anyway.

But those arguments mean that best practices are indistinguishable from alternative practices, not inherently worse. If a programmer discards a practice because they claim it’s considered best practice, they’re really just stamping their foot and shouting “I don’t wanna!”

They’re rejecting the remaining evidence in favour of the practice—that it’s survived scrutiny by a large cohort of their peers—in favour of making their monetised hobby look more like their headcanonical version of the hobby. “We are uncovering better ways of making software by doing it and by helping others to do it” be damned: I want to use this thing I read a substack post about yesterday!

Dig deeper, and you’ll find only platitudinous justification based on thought-terminating cliche: I’ve already covered “Reasoning about code”, and maybe some time I’ll cover “Right tool for the job”. This time, let’s look at “things won’t advance unless some of us try new ways of doing it”.

People tried new ways of making new steam engines all the time, during the industrial revolution. People tried new ways of making chimneys all the time, during the 15th and 16th centuries. A lot of factories and trains exploded, and a lot of buildings burnt down. If you live in a house with a chimney now, or you have ever taken a train, it’s significantly less likely to have self-immolated than at earlier times in history.

It’s not, for the most part, due to misunderstood lone geniuses rejecting what everybody else was doing, but a small amount of incremental development and a large amount of theoretical advance. It’s no coincidence that the field of thermodynamics advanced leaps and bounds during the steam age. Brad Cox makes this point about software too, in almost everything he wrote on the topic: you don’t get as much advance from random walks in the cottage industry as you do from standardisation, mass production, the division of labour, and interchangeable parts that can be evaluated on merit with reference to a strong theoretical underpinning.

Of course, the “reason about code” crowd try to stop this from happening, because if that advance happened then the code-reasoning would quickly disappear to be replaced with the problem-domain-reasoning that’s significantly harder and less of a hobby. Hence the sabotage of best practice: let’s put a stop to this before anybody realises it’s more than sufficient to the task at hand.

Alan Kay once referred to a LISP evaluator written in LISP as “the Maxwell’s Equations of software”. But what software needs before a James Clerk Maxwell are the Gibbs, Boltzmanns, Joules and Lavoisiers, the people who can stop us from blowing things up in production.

February 03, 2021

[objc retain] stream by Graham Lee

Starting next week: [objc retain]; in which Steven Baker and I live-code Objective-C on a modern free software platform. Wednesday, February 10th, 1900UTC. More info at

Saperlipopette by Bruce Lawson (@brucel)

Saperlipopette song

In these difficult times, Lawrence Vagner and I felt a solemn duty to heal the world with a hopeful message of love and cross-cultural unity to a disco beat. So here is our Eurovision entry: Saperlipopette!

Get your hotpants on & boogie for a better tomorrow.


“Saperlipopette” is a very dated French “swear word” translating to “goodness me” or “fiddlesticks”, the kind of thing you’d say if a child were in earshot. My chum Lawrence Vagner taught it to me when they invited me to speak at ParisWeb. I got a daft tune in my head and “Saperlipopette” fitted the melody. (The rest of the lyrics practically wrote themselves, and make a damed sight more sense than the 1968 song with the same title. In fact, I had to discard a couple of verses.) I invited Lawrence to duet with me, which was fun as they’d never sung before, and we had to do it remotely due to lockdown.

It’s made with Reason Studio, using the Reason Disco and Norman Cook refills as well as built-in instruments, and a French accordion sample I found. My chum Shez twiddled the knobs, Lawrence made the website, which is hosted by Netlify.

January 31, 2021

January 2021 by James Nutt (@zerosumjames)

What are default and bundled gems in Ruby?

With Ruby 3.0 the standard library is going to become default gems.

A Ruby installation has three parts. The standard library, default gems, and bundled gems.

The standard library is the core language and utilities. Default gems are gems that cannot be removed, but need not be required. Bundled gems are gems that come along with a Ruby installation, but must be explicitly required as a dependency and can be removed.

There is an ongoing effort to extract parts of the Ruby standard library to default gems. By keeping the standard library itself lean, you free its component parts from being unnecessarily tied to a larger development and release cycle, as well as making bits easier to remove or deprecate as time goes on.

Things I Read

In Progress

  • Continuing to read A Promised Land by Barack Obama. Maybe 70% of the way through this.

January 30, 2021

forty-five by Stuart Langridge (@sil)

It’s my birthday!

This year, in the midst of a coronavirus lockdown, it’s been something of a quiet one. I got lots of nice best wishes from a bunch of people, which is terribly pleasing, and I had a nice conversation with the family over zoom. Plus, a really good Chinese takeaway delivered as a surprise from my mum and dad, and I suspect that if there were a video of them signing up for a Deliveroo account to do so it would probably be in the running for the Best Comedy BAFTA award.

Also I spent some time afternoon doing the present from my daughter, which is the Enigmagram, an envelope of puzzles which unlock a secret message (which is how I discovered it was from my daughter). I like this sort of thing a lot; I’ve bought a couple of the Mysterious Package Company‘s experiences as presents and they’re great too. Must be a fun job to make these things; it’s like an ARG or something, which I’d also love to run at some point if I had loads of time.

I’ve just looked back at last year’s birthday post, and I should note that Gaby has excelled herself again with birthday card envelope drawing this year, but nothing will ever, ever exceed the amazing genius that is the bookshelf portal that her and Andy got me for Christmas. It is amazing. Go and watch the video immediately.

Time for bed. I have an electric blanket now, which I was mocked for, but hey; I’m allowed. It’s really cosy and warm. Shut up.

January 29, 2021

Reading List 270 by Bruce Lawson (@brucel)

January 28, 2021

Another day, another post telling me to do something, or not do something, or adopt some technology, or not adopt some technology, or whatever it is that they want me to do, because it makes it easier to “reason about the code”.

It’s a scam.

More precisely, it’s a thought-terminating cliche. Ironic, as the phrase “reason about” is used as a highfalutin synonym for “think about”. The idea is that there’s nowhere to go from here. I want to do things one way, some random on medium dot com wants me to do things another way, their way makes it easier to reason about the code, therefore that’s the better approach.

It’s a scam.

Let’s start with the fact that people don’t think—sorry, reason—about things the same way. If we did, then there’d be little point to things like film review sites, code style guides, or democracy. We don’t know precisely what influences different people to think in different ways about different things, but we have some ideas. Some of the ideas just raise other questions: like if you say “it’s a cultural difference” then we have to ask “well, why is it normal for all of the people in that culture to think this way, and all of the people in this culture to think that way?”

This difference between modes of thought arises in computing. We know, for example, that you can basically use any programming language for basically any purpose, because back in the days when there were intellectual giants in computering they demonstrated that all of these languages are interchangeable. They did so before we’d designed the languages. So choice of programming language is arbitrary, unless motivated by external circumstances like which vendor your CTO plays squash with or whether you are by nature populist or contrarian.

Such differences arise elsewhere than in choice of language. Comprehension of paradigms, for example: the Smalltalk folks noticed it was easier to teach object-oriented programming to children than to professional programmers, because the professional programmers already had mental toolkits for comprehending programming that didn’t integrate with the object model. It’s easier for them to “reason about” imperative code than objects.

OK, so when someone says that something makes it easier to “reason about” the code, what they mean is that that person find it easier to think about code in the presence of this property. I mean, assuming they do, and are not disingenuously proposing a suggestion that you do something when they’ve run out of reasons you should do it but still think it’d be a good idea. But wait.

It’s a scam.

Code is a particular representation of, at best, yesterday’s understanding of the problem you’re trying to solve. “Reasoning about code” is by necessity accidental complexity: it’s reflecting on and trying to understand a historical solution of the problem as you once thought it was. That’s effort that could better be focussed on checking whether your understanding of the problem is indeed correct, or needs updating. Or on capturing a solution to an up-to-the-minute model of the problem in executable form.

This points to a need for code to be deletable way faster than it needs to be thought about.

Reasoning about code is a scam.

Today I was vaccinated for Covid.

It occurred to me that people might have a question or two about the process, what it’s like, and what happens, and I think that’s reasonable.

A roadsign in Birmingham reading 'Stay Home, Essential Travel Only, Covid'

Hang on, why did you get vaccinated? You’re not 70, you’re, what, thirty-six or something?
[bad Southern damsel accent] “Why, Mr Vorce in my Haird, I do declare, I’ve come over all a-flutter!” [bats eyelashes].
Nah, it’s ‘cos I’m considered clinically extremely vulnerable.
What’s vulnerable?
According to Google if you’re strong and vulnerable then it’s recommended to open with a no-Trump bid. That sounds like a good thing to me.
What’s it like?
It’s like the flu jab.
Like what?
Fair enough. If you’re reading this to learn about vaccination around the time that I’m posting it, January 2021, then maybe you’re someone like me who has had a bunch of injections and vaccinations, such as the flu jab every year. But if you’re reading it later, you may not be, and the idea of being vaccinated against something for the first time since school might be vaguely worrying to you because it’s an unknown sort of experience. This is fair. So, here’s the short form of what happens: you walk into a room and roll up your sleeve, they give you an injection into your arm that you hardly even feel, you sit in the foyer for 15 minutes, and then you go home. It’s like buying a kebab, except with fewer sheep eyebrows.
That’s a pretty short form. Some more detail than that would be nice.
True. OK, well, the first tip I can give you is: don’t put your big heavy coat and a scarf on in the mistaken belief that it must be cold because it’s January and then walk for 45 minutes to get to the hospital, because you’ll be boiling hot when you get there and aggravated.
Just the coat was the problem?
Well, it also turns out that if you stay indoors “shielding” for a year and then go on a long walk, you may discover that your formerly-Olympic-level of fitness has decayed somewhat. Might have to do a sit-up or two.
Or two hundred and two maybe, fatso.
Shut up, Imaginary Voice in my Head.
What next?
I was told to go to the hospital for the vaccination. Other people may be told to go to their GP’s office instead; it seems to vary quite a lot depending on where you live and what’s most accessible to you, and it’s possible that I am very lucky that I was sent to City Hospital, somewhere within walking distance. I’ve heard of others being sent to hospitals twenty miles away, which would have been a disaster for me because I don’t have a car. So, either Sandwell and West Birmingham NHS Trust are particularly good, or others are particularly bad, or I happened to roll double-sixes this time, not sure which.
How were you told?
I got a phone call, yesterday, from my GP. They asked when I was available, and suggested 12.55pm today, less than twenty-four hours later; I said I was available; that was it.
And at the hospital?
Finding the specific building was annoying. SWBH: put up some signs or something, will you? I mean, for goodness sake, I’ve been to the hospital about twenty times and I still had no idea where it was.
No more griping!
I haven’t got anything else to gripe about. It was a marvellously smooth process, once I found the building. This is what happened:
I walked up to the door at 12.45 for my appointment at 12.55. A masked woman asked for my name and appointment time; I gave them; she checked on a list and directed me inside, where I was met by a masked man. He gave me some hand sanitiser (I like hospital hand sanitiser. Seems better than the stuff I have) and directed me to a sort of booth thing, behind which was sat another man.
The booth seemed like a quite temporary thing; a rectangular box, like a ticket booth but probably made of thick cardboard, and with a transparent plastic screen dividing me from him; one of two or three of them in a line, I think. He asked me to confirm my details — name, appointment time, address — and then asked four or five very basic questions such as “do you have the symptoms of coronavirus?” Then he handed me two leaflets and directed me to two women, one of whom led me directly to an examination room in which were a man and a woman.
The man confirmed my details again, and asked if I’d been injected with anything else in the previous month; the woman asked me to roll up my sleeve (I ended up half taking my shirt off because it’s long-sleeved and rolling it all the way up to the shoulder is hard), and then gave me the injection in the upper part of my arm. Took about two seconds, and I hardly felt anything.
Wait, that’s it?
Yup. That whole process, from walking up to the door to being done, took maybe ten minutes maximum.
And then you left?
Not quite: they ask you to sit in the waiting room for fifteen minutes before leaving, just in case you have some sort of a reaction to the injection. People who have had the flu jab will recognise that they do the same thing there, too. This gave me a chance to read the two leaflets, both of which were fairly boring but important descriptions of what the vaccine is, what vaccines are in general, and any risks.
They also stuck a big label on my shirt showing when my fifteen minutes was up, which I think is a really good idea — they don’t do this for the flu jab, in my experience, but it’s a good idea for a vaccination where you have to put basically everybody through the process. I also got a little card which I’m meant to show at the second vaccination, which is now safely in my wallet and will probably still be there in twenty years unless they take it off me, along with the receipts for everything I’ve bought since about 2007.
So then you left?
Yes. Another of the staff confirmed I’d been there for long enough, asked if I was feeling OK (which I was), and asked if I had any questions. I didn’t, but I did ask if I had to go back to work now or if I could just hang out there for a while longer — I’m sure she’d heard variations on that eighty times already that day, but she laughed anyway, and I like trying to chat to hospital staff as human beings. God alone knows what a dreadful year they’ve had; they deserve courtesy and smiles from me at least.
Were they smiling?
Indeed they were. Even though you can’t tell because of the masks. Everyone I spoke to and everyone there was cheery, upbeat, courteous, and competent, without being dismissive or slick. I can’t speak to other NHS trusts, or other hospitals, or even other days in my hospital, but every time I’ve been there the staff have been helpful and nice and ready to share a joke or a chat or to answer a question, and this time was no exception.
What, you didn’t ask any questions at all? What about whether you’re being microchipped by Bill Gates? And the risks of 5G with the vaccine? And…
No, of course I didn’t. Vaccination is safe, and it’s one of the greatest inventions humanity has ever come up with. The NHS guidance on vaccinations is a nice summary here. If I’d walked in the door and someone in scrubs had said to me, “the best way to make web pages is to require 500KB of JavaScript to load before you put any text on screen”, or “Ubuntu has secret motives to undermine free software”, I would have said to them “no, you’re wrong about that” and argued. But me and the medical profession have an agreement: they don’t tell me how to build software, and I don’t tell them how to save millions of lives. This agreement is working out fine for both of us so far.
What’s that about risks and side-effects, though?
Apparently I may feel tired, or an ache in my arm, for the next couple of days. I’ll keep an eye out. They said that if it aches a bit, taking paracetamol is OK, but I am not a medical professional and you should ask the question yourself when you get vaccinated.
Which vaccine did you have?
Remember the two leaflets? One of them is a generic NHS leaflet about Covid vaccines; the other is specific to the one I had and is from BioNTech, which means it’s the Pfizer one. The little wallet card also says it’s Pfizer. I didn’t ask the staff because I could work it out myself and I’m not going to change anything based on their answer anyway; it’d be pure curiosity on my part. Also, see previous point about how I don’t tell them how to do their jobs. I assume that which vaccine I got was decided at some sort of higher-up area level rather than tailored for me specifically, but hey, maybe I got a specific one chosen for me. Dunno; that’s for medical people to know about and for me to follow.
What now?
The vaccine doesn’t properly kick in for a few weeks, plus you need the second injection to be properly vaccinated. That should be 9-12 weeks from now, I’m told, so I’ll be staying inside just as I was before. Might empty all the litter out of my wallet, too.
But I have more questions!
Well, I’m on twitter, if they’re sensible ones. Conspiracy stuff will just get you blocked and possibly reported with no interaction, so don’t do that. But this has been a delightfully simple process, made very easy by a bunch of people in the NHS who deserve more than having people clap a bit for them and then ignore the problems. So if I can help by answering a question or two to alleviate the load, I’m happy to do that. And thank you to them.
Are you really thirty-six?
Ha! As if. It is my birthday on Saturday, though.
You know that thing you said about bridge bids is nonsense, right?
Ah, a correction: also do not ask me questions about bridge. Please.

January 25, 2021

Ubiquitous computing by Graham Lee

I, along with many others, have written about the influence of Xerox PARC on Apple. The NeXT workstation was a great example of getting an approximation to the Smalltalk concept out using off-the-shelf parts, and Jobs often presaged iCloud with his discussion of NetInfo, NFS, and even the magneto-optical drive. He’d clearly been paying attention to PARC’s Ubiquitous Computing model. And of course the iPad with Siri is what you get if you marry the concept of the DynaBook with a desire to control the entire widget, not ceding that control to some sap who’s only claim to fame is that they bought the thing.

Sorry, they licensed the thing.

There are some good signs that Apple are still following the ubicomp playbook, and that’s encouraging because it will make a lot of their products better integrated, and more useful. Particularly, the Apple Watch is clearly the most “me” of any of my things (it’s strapped to my arm, while everything else is potentially on a desk in a different room, stuck to my wall, or in my pocket or bag) so it makes sense that that’s the thing I identify with to everything else. Unlocking a Mac with my watch is great, and using my watch to tell my TV that I’m the one plugging away at a fitness workout is similarly helpful.

To continue along this route, the bigger screen devices (the “boards”, “pads”, and “tabs” of ubicomp; the TVs, Macs, iPads, and iPhones of Apple’s parlance) need to give up their identities as “mine”. This is tricky for the iPhone, because it’s got an attachment to a phone number and billing account that is certainly someone’s, but in general the idea should be that my watch tells a nearby screen that it’s me using it, and that it should have access to my documents and storage. And, by extension, not to somebody else’s.

A scene. A company is giving a presentation, with a small number of people in the room and more dialled in over FaceTime (work with me, here). It’s time for the CTO to present the architecture, so she uses the Keynote app on her watch to request control of the Apple TV on the wall. It offers a list of her presentations in iCloud, she picks the relevant one by scrolling the digital crown, and now has a slide remote on her wrist, and her slides on the screen.

This works well if the Apple TV isn’t “logged in” to an iCloud account or Apple ID, but instead “borrows” access from the watch. Because the watch is on my wrist, so it’s the thing that is most definably “mine”, unlike the Apple TV and the FaceTime call which are “my employer’s”.

January 20, 2021

LIVEstep is a GNUstep desktop on a FreeBSD live CD, and it comes with the GNUstep developer tools including ProjectCenter. This video is a “Hello, World” walkthrough using ProjectCenter on LIVEstep. PC is much more influenced by the NeXT Project Builder than by Xcode, so it might look a little weird to younger eyes.

January 18, 2021

If I could string a thread through my childhood, the pins that hold the thread in place would be all the times I hit my head.

Me and my best friend (at the time) used to play a game called Dizzy Egg. It was a simple game. The object was to spin around as many times as we could and then try not to fall over. I usually fell over, and this usually meant hitting my head on the unforgiving concrete.

In the same playground, I ran—for no particular reason—head first into the white painted wall of one of the school buildings. Luckily, it stayed white.

I was part of a weekend football club. Football Fun. A better name for it might have been “Football Keeps Hitting Me In The Face.” I’m not sure what it was about that football or my face, but the two were inseparable. You couldn’t keep them apart.

I remember one final and dramatic incident. On running through a metal gate, the gate swung closed and tried to run through me. One minute we were running and chasing and laughing. The next I was on the floor, bleeding a lot and saying some words that weren’t suitable for the playground.

That one needed a trip to the hospital and I still have the scar.

January 15, 2021

Reading List 269 by Bruce Lawson (@brucel)

January 14, 2021

Here’s what I’ve been working on (with others, of course) since February.

January 12, 2021

I used to write my assertions like this:

refute user.inactive?

Then I joined a team where I was encouraged to write this:

assert_equal true,
assert_equal false, user.inactive?

What? That doesn’t look very nice. That’s doesn’t feel very Ruby. It’s less elegant!

Here’s the thing, though: your unit tests aren’t about being elegant. They’re about guaranteeing correctness. You open the door to some insidious bugs when you test truthiness instead of truth.

  • You might perform an assignment rather than comparing equality.
def active?
  # Should be status == :active
  status = :active
  • You might check the presence of an array, rather than its length.
def has_users?
  # Should be user_list.any?

def user_list

Over time, I’ve gotten used to it. This style still chafes, but not as bugs caused by returning the wrong value from a predicate method.

January 10, 2021

OpenUK Honours by Stuart Langridge (@sil)

So, I was awarded a medal.

OpenUK, who are a non-profit organisation supporting open source software, hardware, and data, and are run by Amanda Brock, have published the honours list for 2021 of what they call “100 top influencers across the UK’s open technology communities”. One of them is me, which is rather nice. One’s not supposed to blow one’s own trumpet at a time like this, but to borrow a line from Edmund Blackadder it’s nice to let people know that you have a trumpet.

There are a bunch of names on this list that I suspect anyone in a position to read this might recognise. Andrew Wafaa at ARM, Neil McGovern of GNOME, Ben Everard the journalist and Chris Lamb the DPL and Jonathan Riddell at KDE. Jeni Tennison and Jimmy Wales and Simon Wardley. There are people I’ve worked with or spoken alongside or had a pint with or all of those things — Mark Shuttleworth, Rob McQueen, Simon Phipps, Michael Meeks. And those I know as friends, which makes them doubly worthy: Alan Pope, Laura Czajkowski, Dave Walker, Joe Ressington, Martin Wimpress. And down near the bottom of the alphabetical list, there’s me, slotted in between Terence Eden and Sir Tim Berners-Lee. I’ll take that position and those neighbours, thank you very much, that’s lovely.

I like working on open source things. It’s been a strange quarter-of-a-century, and my views have changed a lot in that time, but I’m typing this right now on an open source desktop and you’re probably viewing it in an open source web rendering engine. Earlier this very week Alan Pope suggested an app idea to me and two days later we’d made Hushboard. It’s a trivial app, but the process of having made it is sorta emblematic in my head — I really like that we can go from idea to published Ubuntu app in a couple of days, and it’s all open-source while I’m doing it. I like that I got to go and have a curry with Colin Watson a little while ago, the bloke who introduced me to and inspired me with free software all those years ago, and he’s still doing it and inspiring me and I’m still doing it too. I crossed over some sort of Rubicon relatively recently where I’ve been doing open source for more of my life than I haven’t been doing it. I like that as well.

There are a lot of problems with the open source community. I spoke about divisiveness over “distros” in Linux a while back. It’s still not clear how to make open source software financially sustainable for developers of it. The open source development community is distinctly unwelcoming at best and actively harassing and toxic at worst to a lot of people who don’t look like me, because they don’t look like me. There’s way too much of a culture of opposing popularity because it is popularity and we don’t know how to not be underdogs who reflexively bite at the cool kids. Startups take venture capital and make a billion dollars when the bottom 90% of their stack is open source that they didn’t write, and then give none of it back. Products built with open source, especially on the web, assume (to use Bruce Lawson’s excellent phrasing) that you’re on the Wealthy Western Web. The list goes on and on and on and these are only the first few things on it. To the extent that I have any influence as one of the one hundred top influencers in open source in the UK, those are the sort of things I’d like to see change. I don’t know whether having a medal helps with that, but last year, 2020, was an extremely tough year for almost everyone. 2021 has started even worse: we’ve still got a pandemic, the fascism has gone from ten to eleven, and none of the problems I mentioned are close to being fixed. But I’m on a list with Tim Berners-Lee, so I feel a little bit warmer than I did. Thank you for that, OpenUK. I’ll try to share the warmth with others.

Yr hmbl crspndnt, wearing his medal

January 07, 2021

  1. Seeing in the new year in Barcelona
  2. This gift from my parents: a book telling the story we were told as kids, written by my dad and illustruated by my mum
  3. This gift from my wife: a watercolour painting that hangs in the home office
  4. Veganuary and Dry January
  5. Getting a puppy
  6. Finally getting a full nights sleep after getting said puppy
  7. Zoom quizzes with family and friends
  8. Having a year theme (mine was the year of calm)
  9. The Waking Up meditation app
  10. Making carrot cake for the wife’s lockdown birthday
  11. My mastermind buddies Andy and Blair
  12. The Bosh cookbooks
  13. Celebrating my sister’s 30th with family
  14. Formula 1 putting on a fantastic season despite everything
  15. Not doomscrolling
  16. The inline-block community
  17. Playing Overcooked 2 with the wife
  18. Making jalapeno poppers with fresh allotment chillies
  19. The Mandalorian
  20. Hot summer days
  21. Cutting my own hair for the first time
  22. Islay whisky masterclass at HTFW with Tommy and Jonny
  23. Discovering Beck’s back catalogue
  24. The wife’s new Alfa Romeo Giulietta
  25. Listening to nerdy discussions on Accidental Tech Podcast
  26. Tommy Bank’s Food Box
  27. Switching to Nova, Panic’s new code editor
  28. The Economist’s Daily Espresso
  29. Upgrading to a Kindle Oasis
  30. Reading Search For A Whisky Bothie with a dram
  31. Watching James Acaster: Cold Lasagne Hate Myself 1999
  32. Rediscovering Metallica’s S&M
  33. Receiving an email from Derek Sivers about his new book and insta-buying
  34. Watching Formula 1 Esports
  35. Journalling in the Theme System Journal
  36. Spontaneous trips to our local bakery to buy bagels and donuts
  37. Long walks without headphones
  38. Book club calls with Andy, Matthew and Eddie
  39. The Off Menu Podcast
  40. Making a video of birthday messages from friends and family for the wife’s lockdown birthday
  41. Messing around on this website
  42. Dave Grohl and Nandi’s drum battle
  43. Eating fish and chips by the sea
  44. Watching SpaceX launch astronauts into space
  45. Using good quality tools
  46. Cotswold Cream Liqueur
  47. Last of Us 2
  48. Watching Great British Menu
  49. Working on my 16by9 rebrand with Jordan
  50. iOS 14’s widgets
  51. Long phone calls with family and friends
  52. Devin Townsend
  53. Putting up new wall art in the office
  54. Learning about zettlekasten
  55. Making great coffee with a V60
  56. Sapiens by Yuval Noah Harari
  57. Reading Monevator’s weekly commentary over a cuppa every Saturday morning
  58. Getting a dishwasher for the first time
  59. Playing online chess with Dad
  60. Michael McIntyre’s Netflix special
  61. Making and eating a Friday night curry
  62. Boris Johnson memes
  63. Lazy weekends
  64. Getting into rum
  65. Holidaying in St. Ives
  66. Dogs walk on the beach
  67. Dining at the Oyster Club
  68. Watching the Silverstone Grand Prix at Caffeine and Machine
  69. Being offered a well paid full-time position and turning it down due being happy where I am
  70. Reading How to be an Antiracist and trying to be more antiracist
  71. Afterlife Season 2
  72. Playing Firewatch for the first time
  73. The wife’s apple crumble made with apples from the garden
  74. Not doing much DIY
  75. Taking photos on my iPhone
  76. Making home-made pizza
  77. Lockdown beer box from local brewery Purity
  78. CGP Grey’s Spaceship You video
  79. Sum by David Eagleman
  80. Boarding the Tesla investing train
  81. Coconut milk chai latte’s
  82. Working from my home office
  83. Matt Berninger’s Serpentine Prison
  84. Watching modern F1 cars race on old circuits such as Mugello and Imola
  85. Philps cornish pasties
  86. Sam Harris’ voice of reason in an often unreasonable world
  87. MKBHD’s tech reviews
  88. Making my mum’s potato and leek soup recipe that was my favourite as a kid
  89. Nailing this years vegetarian christmas dinner
  90. My carrot and orange birthday cake
  91. Dog cuddles
  92. The Dithering podcast
  93. Biffy Clyro’s live performance of ‘A Celebration Of Endings’
  94. Binge watching Ben Fogle: New Lives In The Wild
  95. Weekend morning’s spent drinking coffee and reading RSS feeds
  96. Dog walks in the woods
  97. The sound of paired HomePods in the home office
  98. Mum’s curry
  99. Watching birds on the newly installed bird feeder in the garden
  100. Seeing the back of 2020

gets is seen is basically every introductory Ruby tutorial, but they rarely tell the whole story.

You’ll be told to write something like this:

#!/usr/bin/env ruby

puts "What is your name?"
your_name = gets.chomp
puts "Hi, #{your_name}!"

Confusingly, if this is in a script that takes additional command line arguments, you may not see “Hi, Janet!”

If you execute ./gets.rb 123 you will pretty quickly be greeted by the following error:

./gets.rb:4:in `gets': No such file or directory @ rb_sysopen - 123 (Errno::ENOENT)

The tutorial didn’t warn you about this. The tutorial is giving you a reduced view of things that may, if you’re like me, leave you scratching your head several years later.

gets doesn’t just read user input from $stdin. gets refers to Kernel#gets, and it behaves like so:

Returns (and assigns to $_) the next line from the list of files in ARGV (or $*), or from standard input if no files are present on the command line.

If you really, truly want to prompt the user for their input, you can call gets on $stdin directly. And who wouldn’t, with a user like you?

your_name = $stdin.gets.chomp

January 04, 2021

My coworker showed me something cool today. Like a lot of developers, there are certain machines that I find myself SSHing into repeatedly. Not all of them are directly accessible from the network I’m on. Some of them require me to connect via a jump host.

Ordinarily, I manually create a tunnel between a port on my local machine to my final destination via this tunnel. This is cool, but it’s a bunch of steps to remember, especially if you’re manually creating your SSH tunnels via the command line. Especially if you’re trying to remember a bunch of IP addresses.

Apparently, you can just add hosts to your ~/.ssh/config.

Host jump-host
    Hostname x.x.x.x
    IdentityFile /path/to/key/proxy.pem
    User ubuntu

Host destination
    Hostname y.y.y.y
    IdentityFile /path/to/key/destination.pem
    User ubuntu
    ProxyJump jump-host

With this in place, ssh destination gets you there with zero fuss.

January 03, 2021

I’ve been reading On Writing Well by William Zinsser. One of the early instructions he gives is to cut out filler words.

Well, I have a confession to make. I’m particularly guilty of one particular habit that I just can’t seem to shake.

I start a lot of sentences with “well,” and, well, it’s something I’ve been trying to cut down on.

Out of interest, I just ran the following search in my employer’s Slack:

from:@james Well,

The results were not pleasing. I don’t want to say how many times I’ve done it within Slack’s recent memory, but I didn’t dare venture past page 1 of 36.

Well, that just won’t do.

I don’t even know why I do it. It’s not a hedging word, designed to protect me from any criticism I might incur from taking a firm position, as it does nothing to minimise the strength of the statement that follows it. It’s just a noise I make, involuntarily, like um or ah.

It’s five characters (and a space) I can do without.

January 02, 2021

Novel bean incoming by Graham Lee

You may remember in July I updated the open source Bean word processor to work with then-latest Xcode and macOS. Over the last couple of days I’ve added iCloud Drive support (obviously only if the app is associated with an App Store ID, but everyone gets the autosave changes), and made sure it works on Big Sur and Apple Silicon.

Alongside this, a few little internal housekeeping changes: there’s now a unit test target, the app uses base localisation, and for each file I had to edit, I cleaned up some warnings.

Developers can try this new version out from source. I haven’t created a new build yet, because I’m still in the process of removing James Hoover’s update-checking code which would replace Bean with the proprietary version from his website. I’ll create and host a Sparkle appcast for automatic updates before doing a binary release, which will support macOS 10.6-11.1.

Back to Top