Skeuomorphism, refactoring and the persistence of constraints
Photo credit: Jack Finnigan on Unsplash
Whenever I walk through Westminster (which, these days, I do a lot), there are queues of people waiting to take photos outside the red phone boxes that stand in Parliament Square. I can understand why: not only are the red phone boxes attractive symbols of Britishness, but if you line your shot up right, you can get Big Ben in the background.
However, there is an irony in crowds of people using expensive mobile phones to take pictures of the service that you used when you didn’t have a phone - and which has largely been rendered obsolete by those same mobile phones.
We see similar juxtapositions of old and new technology iconography every day, even if we don’t notice it. I’m looking at the home screen of my own mobile phone now, and I can see icons in the shapes of an old telephone handset, an old camera (twice), a wallet containing physical cards, a round clock with hands, and, finally, a mechanical gear wheel. This phenomenon is known as skeuomorphism: the use of old technology to represent new technology. It is remarkable how persistent these symbols are: I recognise them because I grew up with their analogue counterparts, but they are also used confidently by people who have never picked up a physical handset from a cradle, or clicked the button on an old-fashioned camera.
I believe that skeuomorphism is more than just iconography: I think that it is an important illustration of how design choices made today persist into tomorrow. I also think that it is pervasive in computer systems, even if it’s often unintentional, and invisible to anyone who can’t see the code.
One of my very first tasks as a professional programmer was to write a batch program which read an input file, manipulated and modified the data, and produced an output file. Pretty straightforward, except that the input file had a strange and, to me, inexplicable format: data that belonged together was spread over multiple records. There was no technical reason that each record could not be longer, so I was puzzled, curious and a little irritated.
After a bit of research, I tracked down one of the people who worked on the original suite of programs, and he explained that it was written several years ago, when the data was stored on punched cards rather than on disc. The length of the record was determined by the size of the card. If he’d had more time, he would have refactored the code and the file to remove this constraint - but he didn’t. Guess what? I didn’t have the time either, so the suite sailed into the future, carrying the marks of the past with it.
If you don’t write code, this might seem like an obvious example of an unavoidable phenomenon that occurs infrequently. Computing occasionally goes through major changes, such as the shift from punched cards to magnetic discs, or the shift from private networks to the Internet. It’s not surprising that some of the constraints imposed by the previous generation of technology persist into the next generation of technology - and perhaps it's a small price to pay.
But if you do write code, whether as a professional or an amateur, you know that this kind of persistence of constraints happens all the time, and that it imposes an enormous price. Languages and libraries are always being updated, and the way that you do things today is not necessarily the way that you would do things tomorrow.
Furthermore, the design choices you make are not only determined by the technology that is available to you, but by your own skills and understanding on the day that you write the code. The constraints you are subject to are not only determined by technology, but by the contents of your own head. If you work on a project over a long period of time, even as a single programmer, then, unless you refactor frequently, the code becomes a record of the development of your own capabilities and thought processes. It is not unusual to think, why did I do it that way?, and even more normal to think, I wish I’d done it differently.
To people who don’t code, but manage people who do, this is one of the reasons that your developers are always asking for time to refactor, and why their performance (whether you measure it in velocity, reliability or quality - or, ideally, all three) improves when you give them that time. Without refactoring, the code which provides the user interface you see is a boiling mass of anachronism underneath, a stew of constraints, mistakes and regrets. Giving your people time to refactor is one of the most important choices you can make. If you doubt this, get one of your developers to take you on a tour of some code that has been around for a while.
Some skeuomorphs should have a long life. There are aesthetic reasons that we love red phone boxes, and that other symbols of old technology have become literal icons. But we should not feel similarly sentimental about our code.