Keeping Secrets

April 4, 2010

One of the best articles on software design is David Parnas’ 1972 article, On the criteria to be used in decomposing systems into modules” (CACM 15:2). In this paper, Parnas describes two decompositions of a small program. On the surface, these decompositions seem almost identical. However, on closer inspection, Parnas shows that one of these is driven by a functional decomposition of the problem (what he called the “flow chart” approach), while the other one is driven by the principle of information hiding. He goes on to illustrate the benefits of driving design by the principle of the later.

In the flow chart approach, one identifies the computational steps implied by the requirements of the system (first do A, then do B, then do C), and then decomposes the system according to those steps. Parnas claims that the flow chart approach typically leads to software that is not extensible and is otherwise hard to maintain (mostly because the data structures passed between the modules end up being fragile).

The information-hiding approach is based on two simple steps. First and foremost, identify critical subproblems whose solutions are likely to change over time (e.g., because a better algorithm is found, or because different solutions work better in different environments). These subproblems have become known as the secrets to be encapsulated by a module. Second, define abstract interfaces for these secrets, i.e., interfaces that allow clients to access any solution to the problem that may be provided by the module, without exposing any details of a particular solution.

In my experience (and Parnas’ too, see “The secret history of information hiding”), programmers still too often generate designs using the flow-chart approach. True information hiding is hard, and most programmers haven’t learned how it’s done. Here are some tips on mastering this art:

— Read a bunch of Parnas’ papers. He wrote extensively on the topic, using case studies, which really help you understand what he’s saying.

— Consciously stay away from flow-chart thinking. Focusing on data structures is one way to break the flow-chart mindset. Also, Parnas’ writings on “Virtual Machines” might inspire you to think in another direction (see, for example, “Designing software for ease of extension and contraction”).

— Ask about each module in your design: What is the “secret” being encapsulated by this module? What is the subproblem I’m trying to carve off? If you can’t answer this question in a sentence or two — or if your answer sounds like the summary of a step in a larger process — you probably have a problem.

— Focus on problems not solutions. When confronted with a design problem, don’t generate a solution and then attempt to organize that solution into modules. Rather, decompose the larger problem into a series of subproblems. It’s these subproblems that are exposed in the design; solutions to those subproblems are the secrets being encapsulated.