Sunday, March 16, 2014

How to untangle code: make member variables private

Tangled code is hard to read, hard to understand, and hard to change. (Well, hard to change and get right. Tangle code is easy to change and get the change wrong.)

I use a number of techniques to untangle code. Once untangled, code is easy to read, easy to understand, and easy to change (correctly).

One technique I use is to make member variables of classes private. In object-oriented programming languages, member variables can be marked as public, protected, or private. Public variables are open to all, and any part of the code can change them. Private variables are walled off from the rest of the code; only the "owning" object can make changes. (Protected variables live in an in-between state, available to some objects but not all. I tend to avoid the "protected" option.)

The benefits of private variables are significant. With public variables, an object's member variables are available to all parts of the code. It is the equivalent of leaving all of your belongings on your front lawn; anyone passing by can take things, leave new things, or just re-arrange your stuff. Private variables, in contrast, are not available to other parts of the code. Only the object that contains the variable can modify it. (The technical term for this isolation is "encapsulation".)

But one cannot simply change the designation of member variables from "public" to "private". Doing so often breaks existing code, because sections of the code have been built with the ability to access those variables.

The process of "privatizing" member variables is slow and gradual. I start with an general survey of the code and then select one class and change its member variables to private. The class I select is not picked at random. I pick a class that is "elementary", one that has no other dependencies. These "elementary" classes are easier to "privatize", since they can be modified without reliance on other classes. They also tend to be simpler and smaller than most classes in the system.

But while they do not depend on other classes their changes may affect other parts of the code. These low-level "elementary" classes are used by other classes in the system, and those dependent classes often break with the changes. Making member variables private means that those other classes cannot simply "reach into" the elementary class anymore.

To fix these problems, I create special accessor functions. These functions let other classes read (or write) the member variables. Often I find that only the "read" accessor is necessary. Sometimes "the write" accessor is necessary.

After I make the member variables private, I create the accessor functions. Then I modify the dependent code to use not the member variable but the accessor function.

These are simple changes; they do not change the semantics of the code. The compile helps you; once you make the member variables private it gleefully points out the other parts of the code that want access to the now-private variables. You know that you have corrected all of the dependent code when the compiler stops complaining.

Making member variables private is one step in untangling code, but not the only step. I will share more of my techniques in future posts.

No comments: