The Law of Leaky Abstractions

Image created with Midjourney. Image prompt:
Image created with Midjourney. Image prompt: 2d illustration minimal style of a flowing stream representing a binary data flow from a file. Around the stream is a semi-transparent casing, showing the abstracted process. But here and there, drops of water are escaping through cracks in the casing, symbolizing the 'leaks' in the abstraction. In the background, subtly illustrate elements of the underlying system, like a magnetic platter or a network symbol

💬
All non-trivial abstractions, to some degree, are leaky.

In the realm of software development, abstractions are invaluable. These conceptual simplifications allow us to navigate complex systems without delving into every minute detail of their operation. But as powerful as they are, abstractions aren't infallible. This is the crux of the Law of Leaky Abstractions.

Coined by software engineer Joel Spolsky, the Law of Leaky Abstractions posits that "all non-trivial abstractions, to some degree, are leaky." This means that abstractions, while simplifying most interactions with a system, can sometimes fail to completely mask the underlying complexities. As a result, elements of the lower-level system may "leak" through, causing the abstraction to behave in unexpected ways.

This law serves not as a critique of abstraction but as an indispensable warning: abstractions are beneficial, but they can lead you astray if you rely on them too heavily without understanding the underlying system. Let's delve into three examples of this law in action, demonstrating how this concept is intimately tied to the creation of digital software products.

Examples

File System APIs

File system APIs are abstractions of the lower-level kernel systems, which are themselves abstractions of the physical processes involved in altering data on storage media like a hard drive's magnetic platter or an SSD's flash memory. In most scenarios, treating a file as a stream of binary data is effective. But there are cases where this abstraction leaks: for instance, reading data sequentially from a magnetic drive is significantly faster than random access due to the increased overhead of page faults—an aspect that doesn't apply to SSDs. In performance-critical applications like databases, which are designed to minimize random access overhead, understanding these underlying details is essential, revealing the leakiness of the file abstraction.

Networked Files

In Linux, files can be accessed over a network yet represented locally as 'normal' files—an abstraction that, too, can leak. Network failures can cause these 'normal' files to behave unexpectedly. If a developer treats these files as 'normal' without considering the potential for network latency and failures, the resulting software can be prone to bugs.

Programming Languages

Programming languages provide another layer of abstraction, this time over machine code. They mask the nitty-gritty details of the hardware, enabling us to write software without intimate knowledge of the processor architecture or the operating system's system calls. Yet, this abstraction can leak during performance tuning or debugging, where insights into the underlying system can be critical.

Real-world example

Photoshop would be slow to startup, sometimes taking minutes. It seems the issue was that on startup it reads some information about the current default printer. However, if that printer is actually a network printer, this could take an extremely long time. The abstraction of a network printer being presented to the system similar to a local printer caused an issue for users in poor connectivity situations.

Conclusion

The Law of Leaky Abstractions underscores an essential reality of software development: while abstractions are powerful, they're not flawless. They can sometimes make dealing with the problem at hand even more complex, particularly when over-relied upon without a solid grasp of the underlying processes. As we design and build digital software products, we must keep this law in mind. Understanding that abstractions can leak encourages us to seek a balance between abstraction and understanding, contributing to more robust, efficient, and reliable software.

See also

Sources