The Fine Art of Complexity Management
Picture this: A magician sits in front of you with a pack of cards in his hands. He turns over the top card, it’s the Two of Hearts. He has you sign it. He then turns the card back over then takes the top card from the deck and pushes it home somewhere in the middle. He asks you to snap your fingers, then he turns over the top card of the deck again. It’s your signed Two of Hearts.
What I’ve described is the opening of one of the classics of card magic, called The Ambitious Card, in which a signed, selected card repeatedly jumps to the top of the deck in ever more implausible conditions. On the face of it, the effect is simple, the card just keeps jumping to the top of the deck. Behind the scenes, the method is simple too; you just have to execute a hidden move so that it looks like you’re really doing what you claim to be doing. And there’s the rub. I can execute the required move with no little skill, but if I stop to think of the complexities of what I’m doing, I won’t be able to do it well. I certainly can’t explain how it’s done to another magician, well, I can, but the explanation goes along the lines of “Just practice until it looks like the real thing”.
What does this have to do with complexity management? Well, apart from the fact that a good magic trick should be presented in such a way that, no matter how complex the method, the audience just sees the magic, obviously. But there I go again, using the tool we all instinctively use to manage complexity. That tool is the word ‘just’. We all do it, we push the complexities of something behind what I’ve taken to calling a ‘Just Story’. Here’s a just story for sole meunière:
The fish, fried in butter, is transferred to a serving dish and over it is poured a quantity of freshly cooked, hissing, foaming butter. A squeeze of lemon juice, a scrap of parsley, and the dish is ready.
Couldn’t be simpler, could it? Well… Elizabeth David, in French Provincial Cookery goes on to explain the full complexity of the dish so:
Picture this: A magician sits in front of you with a pack of cards in his hands. He turns over the top card, it’s the Two of Hearts. He has you sign it. He then turns the card back over then takes the top card from the deck and pushes it home somewhere in the middle. He asks you to snap your fingers, then he turns over the top card of the deck again. It’s your signed Two of Hearts.
What I’ve described is the opening of one of the classics of card magic, called The Ambitious Card, in which a signed, selected card repeatedly jumps to the top of the deck in ever more implausible conditions. On the face of it, the effect is simple, the card just keeps jumping to the top of the deck. Behind the scenes, the method is simple too; you just have to execute a hidden move so that it looks like you’re really doing what you claim to be doing. And there’s the rub. I can execute the required move with no little skill, but if I stop to think of the complexities of what I’m doing, I won’t be able to do it well. I certainly can’t explain how it’s done to another magician, well, I can, but the explanation goes along the lines of “Just practice until it looks like the real thing”.
What does this have to do with complexity management? Well, apart from the fact that a good magic trick should be presented in such a way that, no matter how complex the method, the audience just sees the magic, obviously. But there I go again, using the tool we all instinctively use to manage complexity. That tool is the word ‘just’. We all do it, we push the complexities of something behind what I’ve taken to calling a ‘Just Story’. Here’s a just story for sole meunière:
The fish, fried in butter, is transferred to a serving dish and over it is poured a quantity of freshly cooked, hissing, foaming butter. A squeeze of lemon juice, a scrap of parsley, and the dish is ready.
Couldn’t be simpler, could it? Well… Elizabeth David, in French Provincial Cookery goes on to explain the full complexity of the dish so:
But do they think to tell you, the instructors of the nothing-is-simpler school, that the butter in which you fry your sole must be clarified butter, that you must watch your fish like a hawk to see that it does not stick and burn, that to turn it without breaking it is a tricky business, that you should discard the remains of the butter in which your fish was cooked, and that you must start again with a clean pan and a quantity of fresh butter, not clarified, and that this butter must be brought just exactly to the right point when it turns a pale hazel-nut colour, no more and no less, that it must be poured instantly over the waiting fish which must with equal immediacy be set in front of those who are to eat it? Do they even tell you, the optimists who have seen the dish being cooked without doing it themselves, or the professionals who have special pans at their disposal, that in the ordinary 10-inch frying pan to be found in most households there will not be room to cook more than one not very large sole?
Few small households possess the large oval pans especially designed for the shallow frying of fish, and one must be realistic about this point. What is the use of instructing the housewife to cook sole meunière for six, or even four people in one small pan? By the time the second and third batches have been cooked, the first will be cold and sodden. In a restaurant or hotel the cooks can perhaps get away with this sort of thing—they are not paying for spoiled materials. The housewife with a critical family, or guests accustomed to good cooking, cannot take the risk of wasting fine-quality and expensive ingredients. So, unless your kitchen is supplied with a suitable pan, it is best not to try to cook sole meunière or similar dishes for more than two people.
Ah, sorry, it does go on a bit I know, but Elizabeth David is a delight to read (and even to transcribe). Now, David is writing here for someone who wants to cook sole meunière, so the extended level of description (rant?) is right for her intended audience. But someone who is thinking of eating the dish only needs the just story. (Incidentally, should you ever find a restaurant serving sole meunière, you can probably make yourself really popular with your chef by all ordering it at once).
The idea of hiding complexity behind ‘just’ is extremely powerful when you are designing interfaces to programs and libraries. Think of a module you’re working on and try and describe the most useful part of what it does in a single sentence. Now write the code and the interface so the library does just that. This ties in remarkably well with Test Driven Development. You just write a test that exercises the simple interface, code ’til it passes and then refactor.
When you need to add a little more functionality, tell yourself another just story (keeping it as simple as you possibly can), write the test, code, refactor. Rinse and repeat. Can you tell how much complexity I’m hiding behind this ‘simple’ development cycle?
Damian Conway is an absolute master at the art of pushing complexity behind simple just stories (abstractions). Take a look at anything in his CPAN directory. Almost without exception, his code is doing ingenious things, but he hides the complexity behind interfaces of exquisite simplicity. Take a look at
Text::Autoformat, or Class::Multimethods or, well almost anything he’s ever written and you’ll see careful attention to interface.
We did a similar thing when we were working on Pixie.
In essence you
just give Pixie an object, and it gives you a cookie back, which you can
use later to retrieve the object. Most of the time that’s all you need.
Sometimes you want to give an object a memorable name, so you use
$pixie->bind_name(aName => $the_object)
. Pixie handles the problems that
arise when you have complex nets of objects, it handles (in theory) the
issue of locking objects (but that bit’s slightly broken at the moment),
in general it just works. But when it doesn’t (suppose you have an
object that keeps its state somewhere that Data::Dumper can’t see it)
you can just become complicit with Pixie and implement px_freeze
and
px_thaw
methods extract state before saving. Our goal, at all times, is
to make everything as simple as possible for the end user, which can
increase the level of code complexity on the implementation side of the
interface (Perl’s reflection capabilities, whilst extensive, often
require some serious hoop jumping to access), but hiding it behind the
interface in the way that we do means we only have to deal with it
once, making life easier for the user.
It could be said that Larry’s doing the same thing with the design of Perl 6. Don’t believe me? Take a look at the latest exegesis and count the just stories (I would say count the ‘just’s, but Damian uses about 3 different meanings and not all of ‘em count for ‘just story’ purposes).
So, if you want to write a tool with a useful, humane interface, here’s the steps you need to go through once more:
- Pick the most important/frequent thing that your module does/needs to do
- Frame it as a simple story about what’s happening
- Recast that simple story as test code
- Make the tests pass
- Refactor
- If you haven’t run out of time/money/features to add, return to step 1.
And that’s all there is to it. I didn’t mean to end up with another description of the process of Test-Driven Development, it just fell out of my thinking about managing complexity.
Here’s one last idea to take from this approach. Next time your boss comes to you and asks “Can’t you just…?” Stop. Think about what he just asked. Your boss is managing complexity and she doesn’t even know it, and she’s just described the interface she wants. Before you dismiss her as asking for the impossible, at least consider whether or not you could arrange things so that it looks like you’re doing the really simple thing she’s asking for, rather than making it obvious to all your users that you’re doing the really complex thing that you have to do to achieve it. You know that’s what you’re doing, but you don’t have to share your pain with people who don’t know or care about the underlying complexity.
Of course, you need a boss who’ll trust you when you tell her that, although what she just asked for sounds simple, implementing it is rather more complicated and it’s going to take some time. But do tell her, that way she can decide if she really wants it. (Which is an article for another day I think.)
For… reasons, I found myself trawling back through the early entries here and found that a bunch of them had been truncated at some point in the blog’s history of migrating from engine to engine. Luckily, the Wayback Machine has a sufficiently complete archive, so I’m slowly working my way through the broken posts, bringing them into the big old
Content.org
file that the site’s generated from and adding a margin note or two to supply a bit of 2025 context where appropriate. The Fine Art of Complexity Management is the first post to receive such attention. Twenty two years on, I still think it’s good advice.