Wednesday, December 05, 2018

The Tyranny of the Lowest Common Denominator

One of my great frustrations in developing software that needs to interact with multiple versions, flavors, and configurations of external components and hardware is finding the simplest way to work with all components, each with varied capabilities.

A simple and familiar real world example is credit card receipts and printers that support different character width receipts. Receipts include basic transaction details such as the time, amount, card information, processing details, and merchant identification. Many of these fields are mandated by the payment processor. Additional optional details may also be included, such as the employee or order details. This information must fit within different receipt widths such as standards of 24, 32, or 40 characters.

In an ideal world with infinite time and resources, one would design software with flexible layouts and configurations to support a wide variety of printers with varying character widths, and even more advanced features such as colored, bold, or different sized text. Unfortunately, we're not living in an ideal world. In the real world, we sometimes need to make tradeoffs to save time and money, and make compromises to make things work adequately in multiple environments.

Making short term tradeoffs and concessions often leads to a poorer final product due to the tyrrany of the lowest common denominator. In the case of credit card receipts, we can support multiple receipt width printers if we focus first on the narrowest 24 character width receipts and simply reuse this format for the 32 and 40 character printers by adding a little extra padded space. By restricting ourselves, we are left with a cramped space and receipts that look less than visually appealing. We save effort in terms of supporting all environments at the cost of the final receipt layout, hopefully finding time to one day return and improve things.

Beyond this simple example, there are many cases where it may be simpler to throw a feaure away that cannot be supported everywhere. We may choose to reduce a feature's complexity and power in order to support multiple environments. Business is business, and these choices are not necessarily wrong, but it can be difficult to extract myself from the emotional impact of purposely selecting an inferiror design to accommodate shortcomings of a system outside of my control. The tyranny part comes in when the most inferior system dictates the experience for the superior systems, holding them to provide less than their full potential.

To overcome this tyranny, sometimes we need to reject the inferior system that is holdng back the rest. When this is not possible, sometimes we can find a way to downgrade a superior solution and wedge it into the lesser environment. Given enough time we can define a system of support for different feature sets, and simply disable advanced features for systems that cannot handle them, but continue to support those features for better environments. And sometimes, when all the stars align, we find the time and resources to do it the ideal way simply because it's great.

Cheers,

Joshua Ganes