#begin
Today we will continue with A Philosophy of Software Design chapter 5. There are some really interesting concepts in here about information hiding, and leakage. I also particularly like how Prof. OusterHout describes there are formal and informal elements to an interface. But let’s take a look and see what he has to say!
Information Hiding (and leakage)
But let’s continue with chapter 5, information hiding. John says that this is the most important thing deep modules do. They provide a small interface and to hide a lot of complexity. He says he got this idea from a David Parnas. The basic idea is this; “Each module should encapsulate a few pieces of knowledge, which represent design decisions. The knowledge is embedded in the module’s implementation but does not appear in it’s interface, so it is not visible to other modules”. This sound like true, OO design doesn’t it.
Hidden information can include many things like data structures or algorithms related to mechanism it provides. It can also include low level details like interactions with a file system or higher level concepts. John says that information hiding battles complexity in two ways. It will simplify the interface to a module since you will not, and do not want to expose inner details to the outside. And second, information hiding increases the ease of evolving the system since all of this logic is local to the specific module. It’s encapsulated, hidden from the outside and thus there cannot be dependencies on these inner workings. This makes it easy to evolve the system because it’s isolated.
And he also rightly notes that information hiding is not simply marking things private. He says that information hiding goes a step further than that. Private variables or properties can still be exposed to the outside by getters and setters for example. But information hiding goes deeper in the sense that you simply want to hide everything local to that module. Like for example; if you have some persistence or data access layer in your game, you don’t want to expose what database you are using. I mean it could be implemented with simple json files on the file system, on maybe an SQLite database. I don’t care about that when I ask for an object. This information should be hidden and not leak to the rest of the game. And this advise nicely correlates with the advise given in clean code. Objects hide implementations and use the dependency inversion principle to hide the larger aspects of the design and thus you are better able to manage complexities and dependencies in your game.
Next-up is the concept of information leakage. This is the opposite of information hiding and it occurs when a design decision is reflected in multiple modules. This creates a dependency between them and thus any change to that design decision will require changes to all of these modules. Information leakage can happen when an interface is too complex or exposes too much that should be internal. And there is another way that information leakage can occur and that’s again a bit more subtle. Imagine that you need to call specific functions on an interface in specific order, that’s information leakage. Or another example, which John gives in the book, is that when you have some functions that read files from disk, they know about file formats. If the file format changes, so will your functions have to change.
John says that information leakage is one of the most important red flags in software design. He says an understanding of sensitivity to information leakage is one of the best skills you can learn as a software engineer. He says a strategy to battle information leakage might be to view all affected classes and extract the dependencies out into a new class. This way you can remove the leakage and embed it in a single new class.
He then raises the next red flag which says: “Information leakage occurs when the same knowledge is used in multiple places, such as two different classes that both understand the format of a particular file”.
A common cause of information leakage is a design style he calls temporal decomposition. In temporal composition, the structure of a system corresponds to the time order in which operations will occur. Hmm isn’t that a cool observation. The example he provides in the book demonstrates that nicely. He says that if you have a process that loads a file into memory, then processes it, and then writes it out to disk again. You might embed that behaviour into three classes, one that reads, one that processes and the last which writes it to disk. So the software design reflects the processes which in his view is incorrect. John says that you should combine the concepts of reading and writing in a single class since these concepts are highly related and it will get used in both the reading part and the writing part of the application.
I think he’s totally right. When designing a system such abstractions should be hidden away behind nice interfaces. But the concept op temporal composition also highly reflects the use-case driven approach I have described a couple of times in previous clean code blogs. The entire purpose of such design is to document each step in a use-case or maybe multiple. So a use-case object embeds all the steps to complete a specific feature provided by the system and use-cases might be linked or put in some kind of sequence. However, these use-cases will use lower level abstractions like reading and writing to a file system. So you might say that these use-case objects have information leakage and promote the temporal decomposition. But I think this is more nuanced since these use-cases object will hide all the implementation details that have to be done in order to complete it. So you might have like a LoginUseCase which takes some credentials object and an API client object and returns an object which defines whether you are logged in or not. I think this is a perfectly nice abstraction. I’m not sure of John would agree with me on that. Note that this LoginUseCase might also embed smaller use cases like, RegisterUser or forgot Password.
He then raises another red flag which says: “In temporal coupling, execution order is reflected in the code structure: operations that happen at different times are in different methods or classes. If the same knowledge is used at different points in execution, it gets encoded in multiple places, resulting in information leakage”.
He finishes the chapter of with some examples of information hiding so if you want to check them out, go ahead and read the book. 🙂
I hope you enjoyed this read and join me on the next one as well! Cya.
#end
01010010 01110101 01100010 01100101 01101110.
Recent Comments