Information Hiding

When objects expose their internal implementation, modifying code becomes harder. In fact, a single change can unexpectedly trigger many others across the code base. Let's take a look at the following example.

class Die {
  var value: Int = 1

  fun roll() {
    value = (1..6).random()
  }
}

class Game{

  fun play() {
    val player1Die = Die()
    val player2Die = Die()

    player1Die.roll()
    player2Die.roll()

    if(player1Die.value > player2Die.value) {
      print("Player 1 wins")
      return
    }
    if(player1Die.value < player2Die.value) {
      print("Player 2 wins")
      return
    }
    print("Draw")
  }
}

In the above code Die is leaking two pieces of information:

  • The die faces are modelled as integer numbers
  • A die wins over another if the former value is greater than the latter

If any of the above two change, we will need to adjust Game as its play method uses that information. An example of such changes is a new rule by which the number 3 wins over any other number. However, we can prevent those unintended changes in Game by not leaking information out of Die as follows.

class Die {
  private var value = 1

  fun roll() {
    value = (1..6).random()
  }

  fun winner(player2Die: Die): String {
    if(value > player2Die.value) {
      return "Player 1 wins"
    }
    if(value < player2Die.value) {
      return "Player 2 wins"
    }
    return "Draw"
  }
}

class Game{

  fun play() {
    val player1Die = Die()
    val player2Die = Die()

    print(player1Die.winner(player2Die))
  }
}

Die has now become the only class knowing about how a die is made and how it wins over another. This means we are now free to change its internal implementation without interfering with Game or any other part of the codebase.

As a final note, leaking information can be subtle and can occur even at naming level. For instance, there is nothing wrong in naming a class InMemoryResource. However, if we want to modify it to fetch the resource over the internet, we first need to ask ourselves if other code has been written using InMemoryResource implicitly assuming that it guarantees high availability.


Recommended reads

Teach me back

I really appreciate any feedback about the book and my current understanding of software design.