Encapsulation is not information hiding

The principles of information hiding go beyond the Java language facility for encapsulation

1 2 3 Page 3
Page 3 of 3
Encapsulation rule 1: Place data and the operations that perform on that data in the same class

This standard practice creates classes that adhere to the principles of abstract data types.

But you want more of your objects; you want them to represent cohesive, workable entities. A second rule concerns the manner of choosing the data and operations to encapsulate:

Encapsulation rule 2: Use responsibility-driven design to determine the grouping of data and operations into classes

This second encapsulation rule actually pertains to information hiding as well: don't just bundle data and operations together; let design principles guide you. Ask yourself what actions an object of the class will be responsible for. Don't let the class encapsulate more or less than a comprehensive set of reasonable responsibilities.

As you have seen from the many examples above, the Java language encapsulation facility isn't enough to ensure a solid class design. The principle of information hiding stipulates that you shield an object's clients from the internal design decisions made for that class of objects. So as a first rule for information hiding:

Information hiding rule 1: Don't expose data items

Make all data items private and use getters and setters. Don't fool yourself into believing no harm will result from directly accessing an object's internal data items. Even if only you code against those internals, future vulnerability still exists. You can't predict when you might need to change the internal data's nature, and brittle coupling with client objects sounds unnerving when shattered.

Go one step further when hiding design decisions concerning internal data. When possible, don't even reveal whether an attribute is stored or derived. Client objects don't need to know the difference. An attribute is a quality or characteristic inherent in a class of objects. From the client's perspective, object attributes correspond to responsibilities, not internal data structure. That brings us to the next rule:

Information hiding rule 2: Don't expose the difference between stored data and derived data

For example, a client object only needs to know that an object has an attribute of speed. Use an accessor method named speed() or getSpeed() rather than calculateSpeed(). Whether the value is stored or derived is a design decision best kept hidden.

As a corollary to the first two information hiding rules, I place all internal data at the bottom of the class text, after the methods that operate on the data. When I examine a class to understand its code, looking first at its internal data leads me to ask the wrong initial questions. I strive to understand the responsibilities of a class before concerning myself with any data structure details. Placing data after methods in the class text reminds me, every time I look at the code, to think first about a class's behavior, not its structure.

The next rule concerns the choice of internal structure:

Information hiding rule 3: Don't expose a class's internal structure

Clients should remain isolated from the design decisions driving the selection of internal class structure. For example, a client should not know whether a primitive array or an ArrayList is used to maintain an internal collection of objects. Internal structure is particularly apparent through the use of method names like getDataArray() or getTreeMap().

The final rule concerns choices of implementation details:

Information hiding rule 4: Don't expose implementation details of a class

Don't allow clients to know or invisibly affect a class's implementation details. For example, a client should not be able to alter an internal calculation's result by changing the state of objects used in that supposedly hidden calculation.

Though not an exhaustive list, those rules help separate the concept of encapsulation provided by the language from the information hiding provided by design decisions. Each rule is fairly easy to follow, and each will assist in creating classes that are not only more resilient to change, but also more easily used by client objects.

Wm. Paul Rogers is a senior engineering manager and application architect at Lutris Technologies, where he builds computer solutions utilizing Enhydra, the leading open source Java/XML application server. He began using Java in the fall of 1995 in support of oceanographic studies conducted at the Monterey Bay Aquarium Research Institute, where he led the charge in utilizing new technologies to expand the possibilities of ocean science research. Paul has been using object-oriented methods and technologies for more than nine years.

Learn more about this topic

1 2 3 Page 3
Page 3 of 3