|How can we use computers more freely and safely?
the punchlinePrefer software:
These are my suggestions.
The most important step is the first one. Humanity didn't get good at building houses by building the same house a million times. We built lots of different houses and learned from each other's failures. Gravitating away from monopolies is a way everyone can help improve software, regardless of our abilities or needs.
|That's the whole argument in a nutshell. In the rest of this talk I want to show how to apply these principles in small ways in your day-to-day decision-making, making the world a little better in the process. I'll show this by drawing on my own journey over the past year for examples. I'll first back up to some problems I was responding to at the start, then show how I responded fairly directly to these problems and ended up with the above suggestions.
|So, problems. The first problem is: software is expensive. We like to think the incremental cost of software is 0. You build it once, lots of people use it. The additional cost for any new user is negligible. This is just not borne out by multiple decades of experience. Apps and services require constant maintenance. And they grow complex over time, so their costs grow over time.
|Also, software today is just not very trustworthy.
Data breaches impact millions of people every year.
If you manage data for others it's extremely difficult to secure. Efforts to secure it add to your costs.
Beyond incompetence, services engage in rampant misbehavior.
This is a headline
from a couple of years ago. Just about every single major phone app was
snooping on your clipboard. And this was going on for years before these
Since they noticed, Apple plugged this loophole. But what else are apps up to, and what current misbehavior will we find out about this year or the next?
|Ok, so software providers fail to keep us secure and also do shady stuff. What do we get for this? Are they at least effective at providing the service they advertise? Here is a talk about how inefficient just about every single mainstream website is. Our computers pay a tax on every page we read.
|But maybe that's just websites that have to go out over the internet. What about native apps? Here is a study showing that a computer from 2015 is 2-5 times slower than an Apple 2e from 1986 just at reading a keystroke and displaying it on screen.
all is not well with computers
|These are the fairly fundamental problems I see. They're not new or insightful, lots of people have said all this. What do we do about it?
depend less on software
|My first resolution is just to bring less software into my life. It is still early days, we don't really understand computers yet. It's important to be clear-eyed about the risks they bring with them, and to think about computers primarily as a liability rather than an asset.
depend on services with dozens of users
But, unfortunately, I came to this realization too late. Computers have
already eaten the world. Today I need to use computers to conduct
commerce, interact with my government, and to talk to my family and
friends. What to do about this?
One coping mechanism is an idea from almost 20 years ago called situated software. This is software with a few users who know each other and share a social context or situation. The idea is analogous to local government: services with few stakeholders are often better able to meet the needs of their stakeholders, particularly when everyone knows everyone and there's a certain level of social accountability.
This isn't always possible. Sometimes we have to use software with millions of users. But I think it helps to rely on small-scale tools as much as possible, and to question tools for large crowds of people at every opportunity.
depend on the right tools
The idea of situated software has been seeing a renaissance recently,
and there is growing awareness of the value it brings. However, I think
we don't yet appreciate the implications of this idea at all levels of
activity around computers.
As a programmer, I've tried multiple times in the past decade to create services just for myself and a few friends. Each of them has fallen away after a year or two. And a big reason for that was the burden of keeping up with updates for all the tools they depend on.
It took me a while to realize the underlying issue: I was using tools that themselves are catering to non-situated software. They assume that it's worth someone's time to keep up with updates every month or two. But situated software doesn't have those kinds of surpluses. It requires programs to just work once built, with little maintenance.
Another thing I love about it: there's a widespread culture of using old
versions. Lua is often embedded in games. Games are a hits-driven
business like movies. Hits are short-lived. As a result, it's less common
for released games to receive updates. Old games running old versions of
Lua are common.
I use version 5.1 which came out in 2006.
This is the LÖVE game engine. It's
based on Lua, it's easy to build, it changes infrequently, and it's
surprisingly versatile while providing a tiny set of APIs.
LÖVE allows me to send a zip file with inspectable source code to my friends. All they need to run it is a single, reputable 5MB binary.
What can I do with this platform? A language that doesn't try to be all
things to all people and tends to leave copies of itself embedded in
older games is fertile soil for forking. Every new game is an
opportunity to rethink old ideas, to shed some complexity. This culture
has had an effect on me even though I don't build games. I build little
apps for my own life, and when I need something new, some of the time I
now copy an existing program and permit the two copies to diverge.
This picture shows a family tree of sorts for the apps I built over the past year. I organized the tree roughly by complexity from left to right. And the lines trace heredity from top to bottom. Look for this image over the rest of the talk as I focus on individual apps to illustrate values I care about and concerns I can jettison entirely.
The app that started it all was
a plain-text editor that lets
me draw little line drawings in the middle of text. I find it very
useful. Definitely talk to me if it or any of my other programs sounds
interesting. I want to support anyone interested in using it or hacking
When I show it to other programmers, often the first question I get is about what the file format for drawings is, and how to get other editors to support that file format. But does it make sense to so privilege interoperability? You have a tool to draw pictures as you write. There are situations where it can be useful, even if nobody else can read it. Trying to stay close to other people and tools makes things more complex and less supple. A tiny, open-source tool that is easy to run and works with a simple file format allows me (and you) to focus on the writing experience without precluding others from taking on additional concerns.
This is an example of keeping requirements negotiable. We programmers have a tendency to start with a germ of a neat idea and, in a microsecond, often so fast we're not even conscious of the transition, pile on a bunch of requirements to it, just because other things like it satisfy those requirements.
Requirements often stem from unconscious acculturation, so it's worth
coming up with strategies to question assumptions. One hack I've found
useful is to stop trying to seem “professional”.
I remember when I started out programming, I wanted my programs to look “professional,” like the programs other “real” programmers made. This desire is the devil. It's taken me 20 years as a professional programmer to realize what matters is what it does, for your specific situation. In practice, seeming professional is often a way to end up with a pile of stuff you don't need. All it does is slow you down.
One particularly egregious requirement we unthinkingly take on is
backwards compatibility. Backwards compatibility is of huge strategic
importance if you're Intel and trying to sell a lot of chips. But it's
also easy to end up depending on a million lines of code just to avoid
writing a thousand.
Deciding when and how an organization should break compatibility is a thorny problem. But fortunately we're not concerned with organizations here. When we're just individuals creating for other individuals, asking each other to make small changes just isn't that big a deal.
|Here's another of my forks. This one's not an editor, just a viewer. Its only reason for existence is to use all available width to display text in a readable way. That's it. It's a very simple thing to build, just 100 lines once you have an editor, and yet it's something I've never seen other programs do. I'm sick of overly wide lines of text and oceans of wasted whitespace. Now I can have dense but readable text on screen.
|We programmers have long had an ideal of building programs that do one thing and do it well. But we have a really hard time keeping such programs from accreting features and complexity over time. I think one essential requirement for programs that do a single thing well is to not tie yourself too tightly with what other people want. It's easy for two people to want slightly different things, and a program that tries to cover both is no longer doing one thing. Rinse and repeat, and you end up with programs with hundreds of commandline flags or preferences. Or worse, someone deciding for everyone, whose preferred settings should get taken out. Just say no. Build simple things, and if others want to do something slightly different, well we already have a solution: fork!
|Here's how I draw pictures in my text editor. One thing to notice is that there are no menus, dialogs or conventional UI elements. I've been trying to mimic the feel of paper and pen. I want to be able to draw at a moment's notice, but I don't want any reminders that I could draw. I don't want any widgets constantly on screen just for the moment when I might start drawing.
Now, I likely don't know what I'm doing. I've only been drawing pixels
for a year now, I'm not a UX designer. But I notice that menus grow over
time, and the trend doesn't often come with great UX.
Our conventional UI idioms were created in the context of organizations. Menus and toolbars are at least partly scalable ways to pack lots of features in, to be all things to all people. Situated software doesn't need menus and toolbars.
|Let's set aside app features and look at how we might make changes to these apps. It's distressingly common to need complicated tools to modify an app. We'd like to avoid requiring any such setup.
To modify any of my LÖVE apps you need just a second LÖVE app. Run the
same 5MB LÖVE binary, just on a different 5k lines of Lua, mostly the
same as my editor, just tweaked in a few ways, and now you can make
changes to any of my apps as they run, without having to restart them.
Teaching a new LÖVE app to listen for commands from the editor takes 250 LoC.
|It's not enough that the sources are available. “Open” is a spectrum, and most open software today is too hard to build, so we leave the build process to a priest class, and the priests accumulate power over time. What if there was zero accidental complexity to modifying a app, and all you had to focus on was understanding how it worked?
My editing environment doesn't have find-and-replace yet. I haven't felt
much need for it, which is surprising because I used to use it all the
time. I recently realized why: small programs just tend to need less
There are many features like this that my environment lacks at the moment. Some of them I'll get to, some I may never add.
There will absolutely be programs that are difficult to create this way, but that's ok.
|I've surprised myself a couple of times when a seemingly complex program turns out to have a simple core. This is a simple DOM model I wrote in 50 lines of code. It doesn't support 99.9% of CSS. It's just a simple way to specify grid layouts. Throw in an infinite 2D surface with support for panning and zooming, and it requires 350 LoC.
|Once I built it, it was easy to include in my editing app. Here you can see my programming environment with the ability to view multiple definitions at once. This is something I've wanted for a long time, to view not just arbitrary files but arbitrary definitions side by side.
|When I first started working on this environment I had a hazy desire for multiple views. However, I found myself gravitating towards a style where I positioned definitions once and never moved them thereafter. It was valuable to give all the code for my apps a place, so I always have a sense of space when I make changes to it. The computer contains my memory palace.
|I'm a little surprised at this point, by how far I've been able to take what I initially considered just a coping strategy. My initial plan had been to create clones of apps for myself and take out lots of features. It felt like eating my vegetables. I didn't expect to find myself wondering what a web browser for memory palaces might look like. Small apps leave more headroom for design exploration. What new types of experience might you create if you undertook such a journey? Focus on keeping software easy to try out, easy to modify and easy to share.
avoid crowdsPrefer software:
The final message I want to leave you with is: avoid crowds. We can each
have huge quantities of freedom inside our own devices on this crowded
planet. Our freedoms only run into frictions when we leave our devices.
The less often we need to do that, the happier we'll be. It doesn't
solve everything, but it helps. A lot.
There isn't a whole lot of software out there that follows these principles. I expect I have a lot more to learn on this journey. If you're interested in joining me, I'd love to help ease your way along however you need. My freewheeling apps are freely available and designed for the long term, and I'm always looking for ways to make them useful to others.
Moar demo: Hands-on with Freewheeling Apps (mirror, mirror)
Links to all the apps/forks I showed above. Click on any node in this image to see its repo and Readme. (Unfortunately HTML doesn't support resizing such an image.)
(image map generated using image-map.net)