Design Like a Dev: What if You Had to Redesign QR Codes?
Despite its ubiquity, the humble QR code has been somewhat taken for granted by developers. The Quick Response (QR) code was invented by a subsidiary of Toyota to track parts across the manufacturing process. But the subsidiary, Denso Wave, never exercised their patent and so the technology is free to use.
Today, we usually use QR codes to get lengthy URLs onto our phones from walls, serviettes, business cards or even t-shirts; that is, any visible surface we can take a photo of. Here is one I made for thenewstack.io thanks to QRFY (it uses a short code that will be disconnected eventually — so try it out sooner rather than later.)
Let’s play a design game. Senior software designers should always be going through redesigns in their head to practice their analysis skills. Your next job may well start with an existing system that you never thought about before, even though you use it all the time. How would you expect a QR code to look and behave? How would you go about designing it from scratch? How would you test it?
But first of all, what were barcodes not delivering that QR codes can? Barcodes extend laterally across a surface, and they work efficiently enough in your local supermarket. But light contrast across the surface can make them hard to read at an angle. In your supermarket self-checkout, you can waggle a pack of couscous until it scans — but you can’t do that with a packing crate in a warehouse.
Let’s summarise the principles of what we think we should be looking for in a QR code before we look at how it actually works:
- It needs to work well in different light conditions, and on various surfaces.
- It needs some degree of error correction, so minor damage doesn’t render it useless.
- As it can’t automatically update, it will have to have a fair bit of metadata baked in; like version information for example.
Understand the Patterns
OK, so you have to know where the code is, and where it isn’t. That is, to detect the position and boundary of the container before you can read the contents within. You’ve probably noticed those big squares that contain dots. These make the Finder pattern. If you see the little square with a dot in it, that is the alignment pattern. This allows confirmation of the angle and orientation of the image.
One thing a good developer will be aware of is the importance of meta information. This gets more important with the age of a project, as different variations and versions proliferate.
In the case of a QR code, the reader has to work out how big the content holder is. The dots that cross from finder square to finder square level with the inner sides make the Timing pattern. These tell the reader how big a single module is and how big the whole QR code is — known as the version. Note that these appear in two places.
I have never seen a QR code like the one on the right, but it is describable within the system!
Redundancy has an interesting place in any system, especially for systems that exist out in the deep wild. It stands to reason that a QR code needs to have more than one way to access its data, in case a small part of the code is obscured. Redundancy and error correction help achieve this — try reading the code at the top with a little part of the image obscured.
Format information is stored and repeated in strips around the Finder patterns. The format stores information on the mask, as well as the level and type of error correction.
Most developers should be familiar with masks, but the application here is a little different. Because the pattern works best when there is a balance between dark and light areas, the idea is to remove the larger light or dark patches that upset the pattern. When a mask is applied onto the code during creation, any dots that fall under the white part are retained, whereas any under the dark part are inverted. So when the code is read back, the mask can be reapplied to return the code to its original state. Various masks are applied to see which one achieves the best result; and this stored in the format pattern.
This reads slightly strangely at first, but it represents the idea that software is controllable but external conditions are not. This undoubted complication still helps to create a more reliable final product. Shaping the data itself to work better with the rest of the toolchain is something you do to enhance an existing solution — you would never have thought to do this initially.
The error correction level controls the density of the code. By increasing the density of the information, redundancy increases and it gets easier to recover information when the code is covered; but the whole image is more complex. This is where the intended use case comes in — where the surface is accessible and close, a low-density simple code is perfectly reliable. Otherwise, trusting the correction strategies becomes more convenient.
What about the Data?
So after all that, where is the data itself? Oddly, it snakes along from the bottom-right (the traditional Japanese reading direction is right to left).
The remaining area on the other side is for the mathematical Error correction. Reed-Solomon Code is an error correction method used for music CDs, but it was originally developed to counter noise in satellite communication. There are still various strategies that can be adopted — whether to spot an error in whole or in part and re rereading the code, comparing redundant areas, or calculating a correction.
So there we have it. A simple premise, but packed with the normal complications of any project that has had to adapt to the environment. This brings us to the final quality a designer has to have: empathy. To appreciate the work done by others to make something functional may be tough to understand at first, but unpicking it patiently is the only way to absorb it.
(I’ve wanted to write about QR code design for some time, but this post by Dan Hollick propelled me into starting; and provided some excellent images, which I have borrowed for this article.)