From charlesreid1


What is encapsulation?

Encapsulation is the idea that code - both methods and classes - should hide or abstract away detail.

This is a decision that must be made each time a new class, variable, or method is created - do we make it public, private, or protected?

Private means only instances of this class can access this method. No one else will be able to see the interface - not even child classes.

Protected means instances of this class, as well as instances of child classes, can see the interface - but no one else can see it.

Public means anyone who wants can walk up and do whatever they would like with your variable.

Rules of thumb

If we need to decide on what to expose to the outside world, what to keep public versus private versus protected, use this rule of thumb:

Always make everything as private as possible.

If you find that it's difficult to thoroughly test a class, then the class may be doing too much. Splitting the class up using composition can make the individual units more testable.

As Josh Bloch, creator of the Collections API, stated in an interview [1]:

I can be somewhat fickle, so my favorite rules might change if you ask me on another day, but today I'll go with Item 13, "Minimize the accessibility of classes and members," and Item 15, "Minimize mutability." Both of these rules transcend any particular programming language.

The first (minimize accessibility of classes and members) tells you to hide information to the maximum extent feasible. This principle, due originally to David Parnas, is one of the most fundamental tenets of good programming. If you hide information, you are free to change it without risking harm to the system. Information hiding decouples the components of the system, allowing them to be developed, tested, optimized, used, understood, and modified in isolation.

Item 15 (minimize mutability) tells you to keep the state space of each object as simple as possible. If an object is immutable, it can be in only one state, and you win big. You never have to worry about what state the object is in, and you can share it freely, with no need for synchronization. If you can't make an object immutable, at least minimize the amount of mutation that is possible. This makes it easier to use the object correctly.

So when should you break the rules? To paraphrase Orwell, you should break them when they'd result in code that is "outright barbarous." As a simple example, Item 25 says, "Prefer lists to arrays." So why does the values method present on every enum type return an array? Because the most common use of this method is to iterate over the elements of its return value, and it's much cheaper to iterate over an array than any List implementation. With the for-each construct, the code to iterate is the same either way.

- Josh Bloch


A few other heuristics:

  • Visibility of system status - keep status of things visible to users.
  • Match between system and world - keep verbiage and symbols system-oriented.
  • User control - allow users ability to leave unwanted state.
  • Consistency - maintain consistency across interfaces.
  • Error prevention - try and anticipate and prevent errors.
  • Recognition, not recall - make things visible, not things they have to retrieve
  • Flexibility - things should be flexible across situations
  • Accelerators - things unseen by novice users, allow speeding up interaction by expert users.
  • Minimal - keep it simple.


See also: