CSE687 - Lecture #3 Design Note

Encapsulation Principle

Revised: 12/9/2009
Home Courses Code Books Handouts Research SWDev WebDev News OtherLinks SiteDesign

CSE681-SWMA CSE687-OOD CSE691-IP CSE775-DO CSE776-DP CSE778-AWP CSE784-SWS

Lecture #3


Encapsulation Principle (ENCAP):

Webster's New World Dictionary defines encapsulation as:
"To enclose in or as if in a capsule"...
For modules and classes, encapsulation encloses an implementation, exposing only an interface.

Purposes of Encapsulation:

  1. Avoid breaking client code when an implementation changes.
  2. Support module or class abstraction by providing a simple interface to what may be a complex implementation.
Breaking client code:
  1. Design breaks:
    If names or types used by the client change, the client's design breaks. This could happen because the interface changes (we try very hard not to do that) or the client has references into the implementation due to failures in encapsulation.
  2. Compile breaks:
    If the size of the object changes, perhaps by adding a new private data member then the client must be recompiled.

    If the text of the class declaration changes, perhaps to change the qualification of a type of a private data member, and the client declares an object anywhere, then the client must be recompiled.

  3. Link breaks:
    If the client:
    • accesses a class through an abstract interface, e.g., an abstract base class from which the class derives
    • does not directly create any instances of the class (would require the client to include class's declaration)
    • statically links to the class's object code
    Then the client need not be recompiled when the class's implementation changes. However, the client must be relinked to the new object code.
  4. Nothing breaks:
    If all the conditions of the previous item are satisfied except that the client accesses the class through a dynamic link library, which will be loaded at run-time, then changing a class's implementation breaks nothing!
Design Rules:
Classes and modules should hide their implementations behind simple user interfaces.
  1. Modules:
    • Export only const global data. Declare it in implementation file, Declare it extern in header file.
      If you feel you must use non-const global data in a module, make it private by declaring only in implementation file and qualify as static.
    • Private global functions qualify their return values with keyword static.
  2. Classes:
    • All member data must be private or protected. We occasionally make an exception for constants and enumerations.
    • Make private any member function that requires knowledge of the design to use effectively or safely.
    • Avoid returning pointers. If the class design supports a part of abstraction by exposing some properly encapsulated inner object then return a reference to the internal object instead of a pointer. References allow the user to access the object. Pointers allow the user to access memory. Moreover, clients must then understand your design to know if they should or should not call delete on the pointer your class passed them.

      There is one notable exception to this no pointer return rule. If your class has a creational function, perhaps a static function that creates an instance of the class, or a function that creates an instance of some other class. Then it is appropriate to return a pointer to the newly created object. The client then must treat the creational function as a sophisticated form of new and assume management of the object's storage. You, of course, must warn the user in your manual page.

Should every class be properly encapsulated? Not necessarily. If your design uses a class internal to some other class, and never exposes it to clients, by declaring it in the implementation file rather than the class's header file, then you cause no problems for your clients. However, now maintainers of your code have to be careful with the unencapsulated inner class.

Example:

  1. Interface Example