Table of Contents

Law Of Leaky Abstractions (LLA)

Variants and Alternative Names

Context

Principle Statement

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

A solution is bad if

Description

Abstractions are typically not perfect. Especially performance aspects are very hard to abstract away from. So there are cases when using the abstraction properly is not possible without knowing the basics underneath the abstraction. So developing and, even more, fixing defects in a system with leaky abstractions makes it necessary to know about all the details the abstraction is supposed to protect the developers from. Often abstractions reduce the effort to develop a feature while they increase the effort for fixing bugs.

A typical problem with leaky abstractions is that the leakiness is ignored. This does not directly mean that the abstraction itself is bad. Often the situation without the abstraction would be worse so it's good to have it. Nevertheless its unavoidable leaks have to be kept in mind. See example 1.

There are also situations where the abstraction is not crafted well. Sometimes there is a way to make the abstraction better (see example 2) but sometimes the whole abstraction is wrong and not having it would be better.

Rationale

Strategies

Caveats

The law of leaky abstractions by no means says that abstractions are generally a bad thing. Abstractions are extremely helpful and software development without abstractions is virtually impossible. So abstractions are good and developers should strive for creating good abstractions. But abstractions are never perfect and this has to be kept in mind.

See also section contrary principles.

Origin

Joel Spolsky: The Law of Leaky Abstractions

The blog article has another focus as it rather explains LLA as an effect rather than an engineering advice. Because abstractions are leaky, developers should and have to know the details abstractions try to protect them from. The principle aspect is only a side aspect there but the main focus here.

Evidence

Relations to Other Principles

Generalizations

Specializations

Contrary Principles

Complementary Principles

Principle Collections

Examples

Example 1: Distributed Objects

There is plenty of middleware which centers around the notion of distributed objects: RMI, CORBA, DCOM, … These technologies abstract away from the fact that the objects are not local but distributed over the network. They create the illusion that calling all objects are local. But all these technologies are leaky abstractions. There is no way to abstract from the fact that calling a remote object may fail. The network connection may break down, the remote machine may not be available, etc. Furthermore there are completely different performance characteristics of remote calls. There is some unavoidable latency and no abstraction what so ever can change this.

This does not mean that these technologies are generally bad. There is a value in these abstractions but the leaks have to be kept in mind. Ignoring the fact that remote calls may fail will result in fragile systems. If the distributed system to develop should be robust, there has to be code handling failing remote calls. And for performance reasons, remote interfaces have to be crafted in a way that remote calls are minimized. So for example Data Transfer Objects are employed in order to transfer larger chunks of data instead of making a remote call for every access to a getter method.

Example 2: String Classes In C++

In C++ string literals such as “test” are of type char* which means pointer to a character. There is some range in the memory where a sequence of characters is stored and there is a pointer pointing to the first character. These strings are unhandy to use so there are string classes in C++ which abstract from these low-level strings which are simply a heritage of the C programming language C++ is built upon. These string classes are much more convenient to use and create the illusion of a built-in string type.

#include <iostream>
 
int main()
{
	std::string s = "Hello";
	s = s + " World";
	std::cout << s << std::endl;
}

In this code it looks like there was a native string type in C++. This is the abstraction. But the abstraction is leaky. The following code does not work:

#include <iostream>
 
int main()
{
	std::string s;
	s = "Hello " + "World";
	std::cout << s << std::endl;
}

So it would be better if C++ had a real native string type.

(this example is taken from 2))

Example 3: List of further examples

Description Status

Complete

Further Reading

Discussion

Discuss this wiki article and the principle on the corresponding talk page.