A Note on Information Hiding and Encapsulation

Alex Muscar

January 07, 2024

I have a feeling that Computer Science suffers from cargo culting more than other fields. There’s plenty of examples —process theatre, security theatre— but in this note I’m going to talk about information hiding and its doppelgänger, encapsulation.

Information hiding was introduced by David L. Parnas in his seminal paper “On the Criteria To Be Used in Decomposing Systems into Modules”.1 At its core information hiding is about hiding design decisions:

Every module in the second decomposition is characterized by its knowledge of a design decision which it hides from all others. Its interface or definition was chosen to reveal as little as possible about its inner workings.

That’s it. There’s nothing here about public or private data, getters or setters and so on. Which brings us to encapsulation.

Unlike information hiding, which has pretty clear definition, encapsulation is a vague term. Depending on who you ask, it can mean either (a) grouping the procedures that implement an abstraction together with the state they are operating on, or (b) the language mechanisms used to restrict access to the state. For one of the most fundamental concepts in OOP, it's awfully murky.

Now, you can get information hiding using encapsulation. But what tends to happen in a lot of cases is that people confuse the mechanism with the concept. And because information hiding is a good thing, it must mean that encapsulation is also good. Suddenly this is a Good ThingTM:

class Point {
    private float x;
    private float y;

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() { return x; }
    public float getY() { return y; }

    public void setX(float x) { this.x = x; }
    public void setY(float y) { this.y = y; }
}

Because of course you’re going to want to change the “implementation details” of your Point. Making fields that are not likely to change private and adding trivial getters and setters is not information hiding. It’s cargo culting.

Here’s a sounder —in my opinion— approach taken from Niklaus Wirth’s Project Oberon:

TYPE
  Rider* =
    RECORD eof*: BOOLEAN;
      res*: INTEGER;
      file: File;
      apos, bpos: INTEGER;
      buf: Buffer
    END;

The * marker means eof is a public field. Because, guess what, chances are it’s not going to change any time soon. The crucial point is that it’s exported read only. Clients of the module are free to inspect the field directly, but can’t modify it. That’s a conscious design decision. And while the field is public, the code that updates it is not. That’s information hiding.

To paraphrase Dijkstra: “Encapsulation is information hiding for those who can not”.


  1. To be completely accurate, it was introduced in “Information distribution aspects of design methodology”, a year earlier, in 1971. But “On the Criteria…” is the better known of the two.↩︎