Computer
A telling comment
According to conventional wisdom comments in program code are invariably a good thing, and most programmers write far too few; but programmers tend to resent writing comments. Until recently I thought of this as a classic example of finding it hard to accept good practice, rather like the need for code review and testing, but recently I realised that I was repeatedly finding myself writing a comment, then deleting it and rewriting the code instead.
In fact, I suggest that conventional wisdom is strictly wrong, although many comments are in fact justified by weaknesses of the programming languages we use. My reasoning is as follows: almost all the comments I consider "good" are in fact contractual: either they document a function's inputs, outputs and side-conditions, or explain how some crucial or possibly doubtful code respectively ensures or does not prevent the contract being fulfilled. The problem with such comments is that they are not amenable to automatic checking. Some languages allow at least some level of "programming by contract"; using them, the contractual comments can be at least partly written as code.
Bad comments, on the other hand, tend to fall into one of two categories. The first is that which explains or justifies odd or out-and-out wrong incorrect code or design. Clearly in this case the code should be fixed, although economics may prevent it, unless it must be kept the way it is for compatibility. (Even then, careful redesign can often maintain compatibility while fixing problems.) The second class of bad comment is that which explains "cute" code, by which I mean code whose operation is unclear. Such code is typically brief, using language or mathematical tricks, or is written in APL. I hesitate to condemn cute code out of hand, because it is usually satisfying to write, often executes efficiently, and when properly commented can be satisfying to read and understand, and hence be neatly didactic.
There's one other class of comments that theory would condemn but good practice encourages: narrative comments, which describe what a long stretch of code is doing step by step. Of course, long stretches of code are usually a bad thing, and should be split into smaller units, but occasionally, typically in the initialisation phase of an application, a large number of housekeeping tasks need to be performed, like a recipe; splitting the code up is largely pointless, and comments take the place of unnecessary functions. As with contract comments, this is arguably a problem with typically-used languages; object-orientation advocates would presumably expect such code to be distributed amongst constructors.
Finally, comments can simply be too long: if the comments are much longer than the code, it's often a sign that conditions mentioned in the comments aren't being enforced or checked in the code. Or it might just be a sign of bad writing. Programmers need to be able to write prose just as well, if not better, than code.
Reuben Thomas, Summer 2007
Overdue Lightweight Portable Computer
Why on earth it takes a bunch of naive techno-utopian academics designing a computer for third world children to come up with the closest thing yet to my ideal portable is a mystery to me. I don't know whether to cry, or just shrug and be grateful I got it eventually.
Shock update: in fact, it's just a hoax, I won't be able to buy one after all, according to The Register.
Killing applications, not killer applications
One of the problems with commercial software is that it still largely sets the benchmarks for what all software developers want to produce. Hence, apart from a few mavericks most developers are following the established GUI metaphor, which encourages (though it is not by any means originally responsible for) the tendency to think in terms of "applications". This suits companies wishing to sell software, because applications can be arbitrarily large and complex, and have arbitrarily many features added; they are never complete. Even the modern versions of the classic UNIX command-line "tool chest" programs, which are often cited as examples of "software tools" designed to perform tasks in combination rather than as individual applications, suffer from the application mentality: grep and sed, for example, include their own subtly different regular expression engines.
What should we be doing instead? Simply, making programs work better together. Some of the problems are not even with the "application" mentality, but because programs are often hard to combine flexibly. For example, grep needs extra code and options in order to use Perl-compatible regular expressions, and either a wrapper script or yet more code in order automatically to decompress compressed files. "Libraries" usually require code to bind to them, and in the second case although you can achieve something close to the desired result by "preloading" a compression library that overrides the standard file-reading routines, the approach lacks fine control (e.g. what happens when you really do want to grep through a compressed file) and opens potential security holes (by overriding system libraries).
There are undoubtedly technical problems to be solved: programs have a wealth of ways to interact (pipes, sockets, temporary files, forking, dynamic linking, scripting) and they need fewer and more flexible ways, but this brief rant does not attempt to address this problem.
Instead, I want to return to the problem of the "killer application". The UNIX tool-chest may not be ideal, but it achieves much more with much less (code, programmer time, computing resources and hence user expenditure on hardware and software, and arguably user frustration) than bloated, bug-ridden (because large, complex and hard-to-test) killer apps. Much can already be achieved without any new technical solutions.
I suddenly realise that I'm at a loss to give examples, as most of my work in this area has been in the less dramatic and more subtle region of programs that are already lightweight, whether it is simplifying and removing bloat from a console editor, working on grep (sadly by adding code) to simplify its use and (even more remote from users) its distribution as part of complete systems, or working on a sound converter to reduce its internal complexity and allow it to support new sound formats without writing code (by making its various readers, writers and filters into standalone programs, rather than, as at present, reimplementing the pipe system inside SoX). Most of my simplification over the last ten years has consisted not of programming, but simply of choosing programs more amenable to toolkit, compositional use: rather than Windows Explorer or its free software equivalents, I use the bash shell, which for all its shortcomings (and they are legion) remains one of the most comfortable readily-available ways to interact with a computer; for editing I use Emacs, arguably a classic piece of bloatware, but also an environment for building editing applications that has attracted thousands of programmers to add routines for performing particular tasks, so that it works remarkably closely with a wide range of other software. I use only six applications daily: editor, shell, email client, web browser and two messaging programs, and that is five too many (one application is the same as zero), but I haven't yet managed to combine them further. It is the desire to do so that started to make me think about this sort of reductive programming.
Well, that was a ramble. Most of the value was probably in the headline. I suspect there are some tangled ideas that need untangling. Comments, as usual, welcome.
Reuben Thomas, Battersea, 14th November 2006
Opening up free software development through mandatory contracts
Free software development is already, at its bazaar best, an open process in which the barriers to entry are low, and in which anyone with a modicum of politeness and technical competence can get bugs affecting them fixed and new features implemented.
However, there are many projects on which for various reasons this doesn't happen. Either the maintainers are overworked or have lost interest and development is slow, or the programs are large, complex and relied on by many people, so development is strictly controlled (as in the case of Firefox, OpenOffice, Linux and the core command-line utilities).
If all these programs had comprehensive contract suites, where contracts covers unit tests, system tests, and other metrics such as performance, memory consumption, code size, and even age of changes (for example time without bugs being filed against them) then a lot of these programs could be opened up to more participants: the tests would automatically provide a large part of the oversight that currently absorbs much of the time of project leaders, who are often also the most productive programmers.
This is not a silver bullet, nor is it the only option: version control systems that allow decentralised operation and easy branching, for example allow the spectrum between mainline releases and personal hacks to be populated more easily and fully; but for the greatest number of users to benefit from the widest array of programming talent, changes must, except where a fork is justified, go upstream as far as possible.
Now I just have to persuade myself to adopt a test-led programming style. Or even to write some tests. Sigh...
Reuben Thomas, London, 8th November 2006
Ideas about UI design
Some ideas that uniformly applied would vastly increase the power and usability of a computer UI.
- Finding things should be like doing a web search. Structured on-line help, menus &c. can just be supplementary views; underlying multi-format information (text, HTML, man pages) can be searched and the results displayed uniformly. This combines web search, online help, Emacs's apropos command &c.
- The only UI is the web browser. This means it can be dynamically created, there's no distinction between local and remote services (other than usability, speed, latency). There's only one interface to learn (custom menus and toolbars &c. can all be part of it, and needn't be "plugins", they can just be part of the markup language).
- XML everywhere: no more plain text! No need for parsers in compilers! Much easier to design editors for different data types (the big problem becomes how to feed back from the view to the model in complex relationships such as vector art, music or DTP).
- No more overlapping windows (except for things like transient dialogs such as confirmation boxes); use moderately intelligent panes.
Also see Tau.
An Attempt at Emacs Humor
One for the cognoscenti only, I'm afraid; others probably won't find it funny.
After a clash with Richard Stallman over his refusal to support Opera, a non-free browser, in FSF Emacs, I thought it was time for some light relief, and posted the following message to gnu.emacs.bug:
From: Reuben Thomas <rrt@sc3d.org>
Subject: Emacs inventing system documentation
Newsgroups: gnu.emacs.bug
To: Emacs Bugs <bug-gnu-emacs@gnu.org>
Date: Thu, 22 Jan 2004 13:00:05 +0100 (CET)
Reply-To: Reuben Thomas <rrt@mupsych.org>
I'm using Emacs 21.3.1, and have noticed that from time to time, when I
use M-x man foo RET to get a man page, the man page is displayed along
with a message "foo man page made up". I don't want Emacs inventing man
pages! I'd rather it just displayed the man page I have installed, or gave
an error if it didn't exist.
I must admit that up to now I haven't noticed any differences between the
pages made up by Emacs and those I get from using the "man" command, but I
haven't checked the details. What if Emacs guesses wrongly about some
arcane corner of bash variable expansion? I could end up wasting hours
trying to track down a bug in a script (and even perhaps waste developers'
time by mistakenly reporting a bug in bash) when the real problem is
Emacs's unwilligness or inability to just look at the real man pages.
Is this just a configuration problem? I think I have my MANPATH and so-on
correctly set up. Looking through apropos I notice:
Man-default-man-entry
Function: Make a guess at a default manual entry.
I'm guessing this function is being run when it shouldn't be.
When I checked the group again a month later, I was gratified to find the following (names removed to protect the unfortunate; look in a Usenet archive if you want to know):
(Are you joking? There's no smiley in your message, so I guess you're not.)
That message is displayed by the Man-fontify-manpage function, whose doc
string says:
| Convert overstriking and underlining to the correct fonts.
| Same for the ANSI bold and normal escape sequences.
"Make up" is used here in the publishing sense: converting markup into
presentation.
So I have to use smilies to indicate humour now? Oops.
And this:
Reuben> I'm using Emacs 21.3.1, and have noticed that from time to
Reuben> time, when I use M-x man foo RET to get a man page, the
Reuben> man page is displayed along with a message "foo man page
Reuben> made up". I don't want Emacs inventing man pages! I'd
Reuben> rather it just displayed the man page I have installed, or
Reuben> gave an error if it didn't exist.
Emacs doesn't invent the man page. M-x man simply runs the 'man'
command on your system, grabs its output, and then add the formatting.
If you don't have a man page for command 'foo', Emacs will give an
error.
Reuben> I must admit that up to now I haven't noticed any
Reuben> differences between the pages made up by Emacs and those I
Reuben> get from using the "man" command,
Because Emacs runs 'man' to get the page contents.
Reuben> but I haven't checked the details.
You should have done so before going out and shouting.
Reuben> What if Emacs guesses wrongly about some arcane corner of
Reuben> bash variable expansion? I could end up wasting hours
Reuben> trying to track down a bug in a script (and even perhaps
Reuben> waste developers' time by mistakenly reporting a bug in
Reuben> bash) when the real problem is Emacs's unwilligness or
Reuben> inability to just look at the real man pages.
The real problem is your unwillingness or inability to just look at
Emac's "man" buffers and compare them with the so called "real man
pages".
Reuben> Is this just a configuration problem?
A configuration in you mind, then.
Reuben> I think I have my MANPATH and so-on correctly set
Reuben> up. Looking through apropos I notice:
Reuben> Man-default-man-entry Function: Make a guess at a default
Reuben> manual entry.
Read further:
Make a guess at a default manual entry.
This guess is based on the text surrounding the cursor.
Now, you tell me what this last sentence means, according to YOUR
understand.
Reuben> I'm guessing this function is being run when it shouldn't
Reuben> be.
You're making an even worse guess than Emacs.
But then came the knockout punch:
I thought Reuben's message was meant as a humorous
way to report that the term "made up" was not clear.
So I will change it to "formatted for display".
Why is it funny? Because the only person who saw the joke was none other than the humourless saint whose organisation's aims I had just been questioning in the same public forum: Richard Stallman.
LOL. Something tells me that the people who assumed your ranting was straight-faced are either way too uptight, or only know how to speak American, or both. D
>TpForth
Some notes on wasting less time on computers
If I seem to be on the right track I can write these up more formally.
The problem
We have two things we want to safeguard: data and time. How can we keep our data safe and accessible with the minimum of time wasting (especially unpredictably due to emergencies)? When things do go wrong, how can we recover quickly?
Orientation
The key is to realise that the important and unique things are our data and time. Hardware is neither. The market provides cheap, consistent (but not always reliable) commodity hardware; we need to combine it with high quality software and processes to achieve a reliable system.
Elements of a solution
0. Simplicity. Setup and recovery in particular should be simple. The essential information you need to access things in an emergency should fit on a business card. The systems must be simple to set up and administer, so we spent almost all our time working, not staying afloat.
1. Repetition. Use the same hardware and software everywhere as far as possible. Also, use the same processes, so that there are, as far as possible, no emergency-only, easily forgettable procedures.
2. Automation. Backups and reinstalls should be fully automated as far as possible. Where they aren't, they should be machine-guided and thoroughly documented. This is also the key to addressing ease of use: if everything is automated, there's nothing to remember day to day. If everything is documented, you can understand it quickly when it goes wrong.
3. Redundancy. Redundant hardware, and redundant software checks, eliminate single points of failure. Redundant hardware can be reused when needed (e.g. turning a server into a desktop machine in an emergency).
4. Distribution and networking. Data should be replicated in multiple places (on disconnected machines, on a central server, and off-site). Again, this should be fully automatic. Servers should serve not just data, but also applications: if your laptop breaks, you should be able to boot an arbitrary machine from a CD or USB key, and continue working remotely on the server.
5. Compatibility. Without compromising reliability or security, we should easily interwork with the rest of the world, using protocols and formats that allow us with little work to both interwork with others and commandeer standard hardware and software for our needs (e.g. web browser access to files and email, NoX client for remote login).
6. Security. We need to keep our data safe so that we avoid fraud, IP and identity theft, and also fulfil our various legal obligations.
7. Monitoring. We should be able to tell at a glance how our hardware is performing, and problems should be automatically notified. Of especial interest is incipient disk failure, and network bandwidth problems.
This is about principles, not technologies, although it is informed by the state of the market. If we can agree on what we're trying to achieve, and in what manner, then I can write an infrastructure plan imbued with those values to satisfy those goals.
An unreadable book on usability
Sadly, Ben Shneiderman's book Leonardo's Laptop, rather than taking its inspiration from da Vinci and using it to inform an intelligent foray into usability hijacks the great man, making him the author's mouthpiece, and contrives to spew almost uninterrupted marketese, in the process getting under the skin of the thoughtful reader by mis-quoting Star Trek, glibly asserting that computers will never be creative, and making the ideal future look as though it has come straight from a Silicon Valley press release.
Computers as interfaces and repositories
Neither the "my PC/laptop is my only machine, and is sacred" or "computers are just interfaces to information in cyberspace" are currently practical models, though the second is desirable. Instead, computers should be viewed as approximating the ideal by caching our data and applications, while also using the resources of each platform appropriately (example: I want Emacs to migrate from my server to my laptop, but it won't fit on my PDA, so a simple text editor should be used there). This involves issues of caching, reconciliation, and format modification. I'd like to start jotting down some practical approaches for the kit I have and use today to approach this ideal of "all my data, everywhere, with best possible access".
Older entries