The importance of information hiding in modules

In programming some modules feel more complex than others. Why is that? Often the complex modules do not hide their complexity well.

The importance of information hiding in modules
Photo by Marcello Gennari / Unsplash

Why are some modules more complex than others? During the course of my career I have seen many complex modules. They usually have something in common: they do not hide their complexity well from the consumer. However, isn't that exactly what modules should do? Let's dive deeper.

Complexity of modules

Modules (APIs, services, classes, functions) will be used by other modules. To the outside a module becomes usable by providing an abstraction of its implementation, an interface. The simpler the interface of a module is, the easier for the developer to use it. Ousterhout defines such modules to be deep modules[1].

On the contrary, if a module's interface is difficult to understand relative to the functionality it provides, it is a shallow module. Shallow modules increase complexity as understanding their interfaces is more difficult. In turn this means, if you focus on creating small modules you will end up having lots of simple (shallow) modules, which increases the overall system complexity.

Now you might ask: How do we create deep modules?

Information hiding

To create deep modules, the idea is the following. A module should encapsulate pieces of knowledge which are embedded in its implementation. The module's interface hides this knowledge. By creating simple interfaces we reduce the necessary amount of cognitive load. This is due to the fact, that we hide details and define an abstract view on the module's functionality. Simpler interfaces tend to hide information better than complex ones.

Let's have a look at the following example, a function that can be used to write a XML file.

function writeXmlFile(
  data,
  outFileName,
  xmlSchemaNamespace,
  xmlVersion,
  xmlEncoding,
) {
  const xmlHeader = buildXmlHeader(
    xmlSchemaNamespace,
    xmlVersion,
    xmlEncoding,
  );
  const xmlData = buildXmlData(data);
  const xmlFile = createXmlFile(xmlData, xmlHeader, xmlData);
  sendFileToExternalSystem(xmlFile);
}

Do you think that the function's signature hides its implementation well? Probably not. The function does not hide its implementation well. The main reason for that is that the user of the function needs to pass XML-specific information like the schema namespace, the version and encoding used in the file.

This can result in different unfortunate situations. If this function is used in multiple places, you will need to pass the XML-specific information in each and every place. What needs to happen when from now on the system you need to send the XML file to requires a different XML encoding? Exactly, you will need to make changes in all places this function is being used.

Another factor that might increase cognitive load is that the function does not do exactly what its name suggests. Instead of writing the file - to a file system for example - it sends the file to some external system. Most likely this will leave your system and make a call over the network.

In general, if module-specific information is hidden by the module, there can be no dependency to this information outside of the module. A change of this information will only affect the module itself. In the example function above information is not hidden well. Instead, information leakage is what is happening.

Conclusion

In my experience code is read more often than written. Code is also extended more often than re-written. The same applies to a system architecture. The closer code comes to production, the harder it becomes to make changes. Once code is in production and your system is set up to accept requests of users that pay your bills and salary, it is much harder and expensive to change direction.

Having a look at system complexity is always worth it if you are in the game for the long-run. Working on a complex system that is not complex because of the domain but because of how it has been set up, will make generations of developers unhappy and frustrated. It can even be a reason why your engineers do not want to stay for longer.

In a following post I will go into more details about how to improve information hiding.


  1. J. K. Ousterhout, "A philosophy of software design", Vol. 98. Palo Alto, CA, USA: Yaknyam Press, 2018. ↩︎