Thursday, 18 June 2009

The myth of idiot-proofing

Idiot-proofing is a myth. Attempting to simplify an over-complex task is good, but be careful how you do it - beyond a certain point you aren't idiot-proofing, just idiot-enabling.

Three classes of tool

Tools (like programming languages, IDEs, applications and even physical tools) can be grouped into three loose categories: idiot-prohibiting, idiot-proof and the merely idiot-enabling.

Idiot-prohibiting tools are those which are effectively impossible to do anything useful with unless you've at least taken some steps towards learning the subject - tools like assembly language, or C, or Emacs. Jumping straight into assembly without any idea what you're doing and typing code to see what happens will never, ever generate you a useful program.

Perhaps "prohibiting" is too strong a word - rather than prohibiting idiots these tools may only discourage naive users. These idiot-discouraging tools are those with which it's possible to get some results, but which leave you in no doubt as to your level of ability - tools like perl, or the W3C XHTML validator. Sure you might be able to open a blank .html or .pl file and write a few lines of likely-looking pseudocode, but if you want to have your HTML validate (or your Perl code actually do anything useful and expected), you're soon going to be confronted with a screen-full of errors, and you're going to have to stop, study and get to grips with the details of the system. You're going to have to spend time learning how to use the tool, and along the way you'll practice the skills you need to get good at what you're doing.

The myth of idiot-proofing

Garbage in, garbage out is an axiom of computing. It's generally impossible to design a system such that it's completely impossible for someone sufficiently incompetent to screw it up - as the old saw goes: "make something idiot-proof and they'll invent a better idiot".

A natural fall-out consequence of this is that making anything completely idiot-proof is effectively impossible - any tool will always be somewhere on the "prohibiting->discouraging->enabling" scale.

Furthermore, even if your tool merely makes it harder for "idiots" to screw things up, at the same time that very feature will attract more idiots to use it.

Shaper's Law of Idiot-Proofing:

Lowering the bar to prevent people falling over it increases the average ineptitude of the people trying to cross it.

Or, more simply:

Making a task easier means (on average) the people performing it will be less competent to undertake it.

Obviously I don't have hard statistics to back this up (though there could be an interesting project for a Psychology graduate...), but it often seems the proportion of people failing at the task will stay roughly constant - all you're really doing is increasing the absolute number of people who just scrape over the bar... and who then go on to produce nasty, inefficient, buggy - or just plain broken - solutions.

Fixing the wrong problem

The trouble with trying to make some things "idiot-proof" is that you're solving the wrong problem.

For example, when people are first learning programming they typically spend a lot of their time concentrating on the syntax of the language - when you need to use parentheses, remembering when and when not to end lines with semi-colons, etc. These are all problems for the non-programmer, but they aren't the important ones.

The major difficulty in most programming tasks is understanding the problem in enough detail to solve it[1]. Simplifying using the tools doesn't help you understand the problem better - all it does is allow people who would ordinarily never have attempted to solve a problem to try it.

Someone who's already a skilled developer won't benefit much from the simplicity, but many unskilled or ignorant people will be tempted by the extra simplicity to try and do things that are (realistically) completely beyond their abilities. By simplifying the wrong thing you permit more people to "succeed", but you don't increase the quality of the average solution (if anything, you drastically decrease it).

By analogy, spell-checkers improved the look of finished prose, but they didn't make anyone a better author. All they did was make it easier to look professional, and harder to tell the difference between someone who knew what they were talking about and a kook.

Postel's Law

The main difficulty of programming is the fact that - by default - most people simply don't think in enough detail to successfully solve a programming problem.

Humans are intelligent, flexible and empathic, and we share many assumptions with each other. We operate on a version of Postel's Law:

"Be conservative in what you emit, liberal in what you accept"

The trouble begins because precision requires effort, and Postel's Law means we're likely to be understood even if we don't try hard to express ourselves precisely. Most people communicate primarily with other humans, so to save time and effort we express ourselves in broad generalities - we don't need to specify every idea to ten decimal places, because the listener shares many of our assumptions and understands the "obvious" caveats. Moreover, such excessive precision is often boring to the listener - when I say "open the window" I don't have to specify "with your hand, using the handle, without damaging it and in such a way that we can close it again later" because the detail is assumed.

Sapir-Whorf - not a character on Star Trek

The problem arises that because we communicate in generalities, we also tend to think in generalities - precision requires effort and unnecessary effort is unpleasant, so we habitually tend to think in the most vague way we can get away with. When I ask you to close the window I'm not imagining you sliding your chair back, getting up, navigating your way between the bean-bag and the coffee table, walking over to the window, reaching out with your hand and closing the window - my mental process goes more like "window open -> ask you -> window closed".

To be clear: there's nothing inherently wrong with thinking or communicating in generalities - it simplifies and speeds our thought processes. Problems only arise when you try to communicate with something which doesn't have that shared library of context and assumptions - something like a computer. Suddenly, when that safety-net of shared experience is removed - and our communication is parsed exclusively on its own merits - we find that a lifetime of dealing in vague generalities has diminished our ability to deal with specifics.

For example, consider probably the simplest programming-style problem you'll ever encounter:

You want to make a fence twenty metres long. You have ten wooden boards, each two metres long, and you're going to the hardware shop - how many fence-posts do you need?

No programmer worth his salt should get this wrong, but most normal people will have to stop and think carefully before answering[2]. In fact this type of error is so common to human thinking that it even has its own name - the fencepost (or off-by-one) error.

Solve the right problem

Any task involves overcoming obstacles.

Obstacles which are incidental to the task ("publishing my writing">"learning HTML") are safe to ameliorate. These obstacles are mere by-products of immature or inadequate technology, unrelated to the actual task. You can remove these without affecting the nature of the task at hand.

Obstacles which are an intrinsic part of the task are risky or even counter-productive to remove. Removing these obstacles doesn't make the task any less difficult, but it removes the experience of difficulty.

Counter-intuitively, these obstacles can actually be a good thing - when you don't know enough to judge directly, the difficulties you experience in solving a problem serve as a useful first-order approximation of your ability at the task[3].

Despite years of trying, making programming languages look more like English hasn't helped people become better programmers[4].

This is because learning the syntax of a programming language isn't an important part of learning to program. Issues like task-decomposition, system architecture and correct control flow are massively more important (and difficult) than remembering "if x then y" is expressed as "if(x) { y; }".

Making the syntax more familiar makes it easier to remember and reduces compile-time errors - making the task seem easier to a naive user - but it does nothing to tackle the real difficulties of programming - inadequately-understood problems or imprecisely-specified solutions.

The trouble is that the "worth" of a program is in the power and flexibility of its design, the functionality it offers and (inversely) the number of bugs it has, not in how many compiler errors it generates the first time it's compiled.

However, to a naive beginner beauty and solidity of design are effectively invisible, whereas compiler-errors are obvious and easy to count. To a beginner a program that's poorly designed but compiles first time will seem "better" than a beautifully-designed program with a couple of trivial syntax errors.

Thus to the beginner a language with a familiar syntax appears to make the entire tasks easier - not because it is easier, but because they can't accurately assess the true difficulty of the task. Moreover, by simplifying the syntax we've also taken away the one indicator of difficulty they will understand.

If a user's experiencing frustration because their fire-alarm keeps going off the solution is for the user to learn to put out the fire, not for the manufacturer to make quieter fire alarms.

This false appearance of simplicity begets over-confidence, directly working against the scepticism with the current solution which is an essential part of the improvement process[5].

Giving a short person a stepladder is a good thing. Giving a toddler powertools isn't.


Footnotes

[1] This is why talented programmers will so often use exploratory programming (or, more formally, RAD) in preference to designing the entire system first on paper - because although you might have some idea how to tackle a problem, you often don't really understand it fully until you've already tried to solve it. This is also why many developers prefer to work in dynamic scripting languages like Perl or Python rather than more static languages like C or Java - scripting languages are inherently more flexible, allowing you to change how a piece of code works more easily. This means your code can evolve and mutate as you begin to understand more about the problem, instead of limiting your options and locking you into what you now know is the wrong (or at least sub-optimal) approach.

[2] Obviously, the answer's not "ten".

[3] When I'm learning a new language I know I'm not very good at it, because I have to keep stopping to look up language syntax or the meanings of various idioms. As I improve I know I'm improving, because I spend less time wrestling with the syntax and more time wrestling with the design and task-decomposition. Eventually I don't even notice the syntax any more - all I see is blonde, brunette, readhead... ;-)

[4] Regardless of your feelings about the languages themselves, it's a truism that for years many of the most skilled hackers have preferred to code in languages like Lisp or Perl (or these days, Python or Ruby), which look little or nothing like English. Conversely, it's a rare developer who would disagree that some of the worst code they've seen was written in VB, BASIC or PHP. Hmm.

[5] From Being Popular by Paul Graham, part 10 - Redesign:

To write good software you must simultaneously keep two opposing ideas in your head. You need the young hacker's naive faith in his abilities, and at the same time the veteran's scepticism... The trick is to realize that there's no real contradiction here... You have to be optimistic about the possibility of solving the problem, but sceptical about the value of whatever solution you've got so far. People who do good work often think that whatever they're working on is no good. Others see what they've done and are full of wonder, but the creator is full of worry. This pattern is no coincidence: it is the worry that made the work good.

Stereotypes are useful tools

Humans generalise. It's what we do.

If you chose to handle every single experience as an isolated event, you'd never go anywhere or do anything for constantly investigating options, exactly like how you'd never get out of your house if you had to check every room was empty before leaving - by the time you've checked the last one, someone could have entered the house and got into the first one again, so you have to start back at the beginning and check them all over again.

Stereotyping is a very useful, essential mechanism for bypassing all of that - when we meet a new situation, we compare it to situations we've experienced before, and this gives us a guide as to what this one is likely to be like. For example, "this room was empty and I closed the door. People don't generally break into second-story rooms in any given five-minute period, so it's safe to assume it's still empty and leave the house".

The problem comes when people assume that stereotypes are facts - stereotypes/generalisations only give good indications of probabilities, and as long as you're always aware of the possibility that this situation is an edge-case where the "general rule" doesn't apply, there's no harm in it.

In our touchy-feely, inclusive, non-discriminatory society it's become deeply un-trendy to stereotype or generalise. People feel that because stereotypes have been over-used, or used to excuse discrimination or bigotry, there must be something inherently wrong with stereotyping. This is itself stereotyping, and - in this case - it's wrong.

What people really disapprove of are:

  • Unfair generalisations (although since stereotypes come from repeated observations, there are a lot less of them than you think)
  • People mistaking statistical guidelines for hard facts.

However, as ever as a culture we err on the side of throwing the baby out with the bathwater, and conclude that because some people have tried to use stereotypes to justify bad actions in the past, there's something inherently wrong with the whole idea of stereotypes. That's not the case.

Friday, 1 May 2009

The incompetent leading the credulous - your mildly disconcerting thought for the day

It's well-known to psychologists, public speakers, politicians and con-men[1] that in general the more confident an individual appears, the more persuasive they are to other people. This effect holds regardless of the veracity or provability of their assertions. In other words, confidently and assertively talking horseshit will make you more persuasive than simply talking horseshit on its own, regardless of the fact it's horseshit.

In other news, the Dunning-Kruger effect demonstrates that - in general - the more incompetent or ignorant someone is of a subject, the more they will over-estimate their own expertise or understanding of it. Equally, the more experienced and competent a person becomes in a subject, the more they will begin to underestimate their true level of knowledge or expertise, downplaying their understanding and qualifying their statements. In effect, when trying to assess one's own level of ability in a subject increased expertise is inversely proportional to confidence in your expertise.

The net effect of this is that - again, in general - ignorant or incompetent people are subconsciously predisposed to be more confident in their opinions, and all people are subconsciously predisposed to find confident people persuasive.

In a nutshell, all things being equal, people are instinctively predisposed to find ignorant or incompetent people disproportionately persuasive and trustworthy compared to more competent, more experienced experts.

Distressingly it appears that in the kingdom of the blind the one-eyed man is not king. Instead, in the kingdom of the blind the true king is the one blind guy who's sufficiently incompetent or delusional that he honestly believes he can still see.

This has been your mildly disconcerting thought for the day.


Footnotes

[1] The author acknowledges that there may be some overlap in these categories.

Monday, 16 March 2009

Rules for system designing #1: If a system can be gamed, it will

I first encountered this rule in web development, but once spotted I discovered it holds true in many, many diverse areas of life.

When designing a system of rules or procedures (a computer program, laws, a business's internal policies and procedures, etc) it's always tempting to ignore or avoid edge-cases - they seem so obscure or unlikely it's tempting to decide they don't matter, and not to bother resolving or fixing any ambiguities or loopholes.

People think about systems of rules the way they think about other people - you don't have to be too precise, because it'll be clear what the intent of your words is.

However, once set up systems are administrated according to the rules which define them - while "the original designer's intent" is nebulous and open to interpretation, the letter of the law is usually quite specific, even if the eventual result of them is quite different from what the original architects intended. Nobody ever got fired for following the letter of the law, even if by doing so they did great violence to its spirit.

This can be seen in all walks of life - if you're a naive programmer developing a web application it can seem tempting to ignore security holes or undefined edge-cases. "Who will ever spot that?" you think to yourself, "nobody will bother poking around in odd corners of my application, or try firing odd url parameters into my server. I'm much better off adding Whizzy New Feature #436 to my application than tidying up some dusty old corner of the code".

This sounds perfectly reasonable to most people, but any experienced web developers will be shaking their heads about now - first off, when you write code for websites your code is exposed to the entire internet, and there's always someone out there who'll start poking it with a stick, just to see what it does.

Even worse, there are also whole swathes of entirely automated systems like web spiders, spam-bots and automated vulnerability scanners that will systematically follow every link and try every combination of URL parameters it can imagine, simply to see what will happen.

The key point to take away here is that - almost invariably - your audience will turn out to be a lot larger and more diverse than you imagine, and what might seem obscure, boring or unimportant to you might not seem the same way to all of them... and neglecting to handle these edge-cases can lead to the entire system becoming compromised.

Likewise, laws suffer from this problem - they're typically crafted using vague language, and - like any non-trivial system - typically contain numerous unspotted edge-cases and loopholes. Moreover, the equivalent of issuing a patch to an existing law once it has been passed is about as complicated, fraught and long-winded as passing the law in the first place, making it difficult, time-consuming and expensive to correct errors once a law has been passed.

Like programs, relying on obscurity to paper over these loopholes is a mug's game - when laws apply to the number of people in an entire country you're pretty much guaranteed that eventually someone will either deliberately target or just stumble upon an unhandled edge-case. When this happens the system can be gamed, and the laws fail to perform their required function.

When this happens, the results may be anything from a single individual getting away with a parking ticket to your entire society taking a turn for the worse.

Remember: if a system can be gamed, it will, so take care to eliminate all possible edge-cases, and practice defence in depth so when an unknown compromise or loop-hole is inevitably eventually discovered, the amount of the system which is affected and can then be compromised is limited.

This advice applies equally whether you're a developer writing computer code, a politician crafting new laws or a manager adjusting business processes in a company. If it's a system of rules, this design axiom applies.

Friday, 9 January 2009

Lifecycle of a meme

A recent discussion on reddit prompted me to sketch out the stages of an internet meme's lifecycle.

Lest there be any confusion, I'm talking here about internet memes - LOLcats, Soviet Russia jokes and the like, not about memes in the more general sense of the word.

As far as I can see, all memes go through this lifecycle:

  1. Meme is born. Almost nobody understands it, and it's barely funny even when you do.
  2. Meme gets adopted by a specific social group. Meme now serves as a shibboleth indicating membership of the group, and encourages feelings of belonging and "insidership" whenever it's encountered. At this stage, the meme is usually either utterly baffling or hilarious, depending on whether or not you're an insider in that social group.
  3. Meme becomes mainstream - everyone is using it at every opportunity, and - its use as a shibboleth negated - it gradually gets stale from overuse. Meme is hilarious to newcomers, but increasingly sterile and boring to older users.
  4. Meme effectively dies - people using it are generally downmodded or castigated for trying for "easy" posts. Importantly, it can still be funny even at this stage if it's used particularly well... however, 99% of the uses at this point are people trying to cash in on easy karma - the kind of people who tell the same jokes for years without realising that the 17th time you hear it, it's no longer funny.
  5. Meme is effectively dead, but may experience rare and infrequent resurrection in particularly deserving cases. Generally these uses get applauded, because nobody wants to risk approbation for posting stale memes unless they're really sure this is a perfect opportunity for it - one that's literally too good to miss.

Importantly, by stage 5 the meme starts once again to be funny, because it's once again serving as a shibboleth... though this time instead of showing how advanced and up-to-date the poster is, it instead serves to indicate his membership in the "old guard" of whatever social group it's posted to - "I've been around here so long I remember when this was funny", it quietly indicates to other old-timers and well-educated newbies alike.

Thursday, 1 January 2009

Engines of reason

Initially we as acted as individuals - what we understood of reality was what we experienced and determined for ourselves. There was no understanding or appreciation of the world outside our direct experience.

Later we developed language, and what we understood of reality was formed from our own perceptions and conclusions, influenced by the perceptions and conclusions of our family and social group (family, clan, village, etc).

Next we developed the printing press, and mass-media. These allowed centralised governments and organisations to accumulate and weigh information and experiences and broadcast them to the populace. We still held our own council on personal or local matters, but since we rarely (if ever) knew anyone who had experienced such events outside our local region, we largely received all our knowledge and understanding of the outside world from centralised authority - governments, news media organisations, etc.

Finally, with the advent of the web we're enabling anyone to publish their personal experiences, in a way that anyone else in the world can then receive. No longer do we simply not have access to information, nor do we receive distilled, refined, potentially biased information from one or a few sources. Now we're capable in theory of hearing every point of view from every participant in an event, untainted by anything but their personal, arbitrary biases.

We are still receiving information on a global scale, but for the first time it's potentially all primary evidence, untainted and unfiltered by a single agenda or point of view.

The trouble with this is that brains, personalities, cultures and institutions long-accustomed to received wisdom now have to compare, contrast, weigh and discern the trustworthiness of multiple conflicting points of view for themselves. For the first time since our pre-linguistic ancestors you - and only you - are primarily responsible for determining truth from falsehood, and for the first time in history you have to do so on a global scale, involving events of which you have no direct experience.

To be clear: this is hard. Many people instinctively reject the terrifying uncertainty and extra effort, instead abdicating their personal responsibility and fleeing to any source of comforting certainty they can find. This explains why even in these supposedly scientific and rational times people still subscribe to superstitions or religions, or simplistic, fundamentalist philosophies, or blindly consume and believe opinionated but provably-biased sources like political leaders, charismatic thinkers or biased news organisations.

So it's a double-edged sword - for the first time in history we have access to primary evidence about events in the world, rather than receiving conclusions from a central source along with only what secondary or tertiary evidence supports them. However, in doing so the one thing we've noticed is that the channels we've relied-upon up till now are biased, agenda-laden and incomplete.

Obviously in an ideal world everyone could be relied-upon to train their bullshit-filters and research and determine the truth for themselves. However, given the newness of the current situation we can't rely upon this any time soon. Likewise, given both the sheer volume of information and humanity's propensity for laziness and satisficing, we'll likely never be able to rely on the majority of people doing this for every single issue they hold an opinion on.

So what's a species to do? We've turned on the firehose of knowledge, and it's shown that the traditional channels of received wisdom are unreliable, but many people find it impractically hard to drink from it.

There are three choices here:

  • We could allow the majority of people to reject their responsibilities and abdicate their reasoning processes to others of unknown reliability... though this is the kind of thing that leads to fundamentalism, anti-intellectualism and cultural and scientific stagnation.
  • Alternatively, we could encourage people to distrust authority and try to decide for themselves... though even if we win, if the effort of self-determination is too great we risk merely leaving people floundering in a morass of equally-likely-looking alternatives (I believe this is a primary cause of baseless, unproven but trendy philosophies like excessive cultural relativism - if you're lost in a sea of indistinguishable alternatives, it's flattering and tempting to believe there is no difference in their correctness).
  • Lastly, we can make an effort to formalise and simplify the process of determining reliability and truth - striving to create democratic, transparent mechanisms where objective truth is determined and rewarded, and falsehood or erroneous information is discarded... lowering the bar to individual decision-making, but avoiding unilateral assumption of authority by a single (or small group of) agendas.

Stupid as it may seem, I believe this is the ultimate destination towards which sites like reddit or Wikipedia are slowly converging - people post evidence, assertions or facts, those facts are discussed, weighed and put in context, and (so the theory goes) accuracy and factual truth is ascertained by exposing the process to a large enough consensus.

It doesn't always work - many of these early attempts suffer from a poor mechanism, or attract a community who vote based on their prejudices rather than rational argument, or end up balkanised in one or more isolated areas of parochial groupthink.

However, the first heavier-than-air aircraft didn't work too well either, and here we are a few decades later flying around the planet faster than the sun. As a species we're still only a few years into what may be a decades- or centuries-long process - one which could change the very foundations of (and mechanism by which we determine) what we understand as factual reality.

People love to rag on social news sites, discussion forums and sites like Wikipedia for what amounts to failing to have already achieved perfection. I prefer to salute them for what they are - hesitant, often blind, stumbling baby-steps towards solving a problem many people don't yet even realise exists.

Friday, 5 December 2008

The web is not a sheet of paper

Print-turned-web designers:

  1. Learn the medium you're working in. A five minute video of even the best print advert makes for a lousy TV advert. Likewise, techniques and habits refined by years of print design are often sub-optimal or flatly counter-productive when applied to the web.
  2. For the love of god, give up on pixel-perfect positioning and learn to appreciate flow layout. Sure, it makes design harder... but if you think designing flow layouts is hard, think about the poor schmuck developers who have to implement the damn things. And if you think flow layouts are ugly, let's see how good your precious pixel-perfect design works when I do something freakishly unusual like resize my browser window.
  3. Print pages are Things To Look At. Web sites are Things To Use. Prioritising aesthetics over usability or functionality is like putting a car steering wheel in the middle of the dashboard. Sure it looks nicer, but it makes the whole product useless. Incidentally, I swear if I get one more design through with a "button" image specified but no "pressed button" image (or "link" style but no "active/hover/visited link" style) I will personally bite off your head and defecate into your body-cavity. You have been warned.
  4. Conventions are not boring - conventions are your friend. Putting light-switches near doors is a convention. Sure, putting them square in the middle of the ceiling is innovative, but then so is cheesegrating your knees (hey - do you know anyone who's done it?). Innovative means "nobody else is doing it". Accept the possibility that nobody else is doing it because it's a fucking stupid idea.
  5. I don't want to "explore the interface". I want to get in, do my shit and get out again. If you think forcing users to explore the interface is such a good idea, try ripping the labels off all the cans of food in your cupboard. A couple of meals of cat-food, chilli and peaches should demonstrate exactly how "fun" this is for your users.

PANT, pant, pant... pant... ahem.


Originally via reddit.