Classes

Class Organization

Following the standard Java convention, a class should begin with a list of variables. Public static constants, if any, should come first. Then private static variables, followed by private instance variables. There is seldom a good reason to have a public variable

Public functions should follow the list of variables. We like to put the private utilities called by a public function right after the public function itself.

Encapsulation

We like to keep our variables and utility functions private (or protected when accessed by a test).

Classes Should Be Small!

The first rule of classes is that they should be small. How small? We count in reposibilities. The name of a class should describe what responsibilities it fulfills. In fact, naming is probably the first way of helping determine class size. If we cannot derive a concise name for a class, then it’s likely too large.

The Single Responsibility Principle

The Single Responsibility Principle (SRP)2 states that a class or module should have one, and only one, reason to change.

Cohesion

Classes should have a small number of instance variables. In general the more variables a method manipulates the more cohesive that method is to its class. A class in which each variable is used by each method is maximally cohesive.

Maintaining Cohesion Results in Many Small Classes

Consider a large function with many variables declared within it. Let’s say you want to extract one small part of that function into a separate function. Must you pass all four of those variables into the new function as arguments? Not at all! If we promoted those four variables to instance variables of the class, then we could extract the code without passing any variables at all.

Unfortunately, this also means that our classes lose cohesion because they accumulate more and more instance variables. But, if there are a few functions that want to share certain variables, doesn’t that make them a class in their own right? Of course it does. When classes lose cohesion, split them!

The first thing you might notice is that the program gets a lot longer.

Organizing for Change

For most systems, change is continual. Every change subjects us to the risk that the remainder of the system no longer works as intended. In a clean system we organize our classes so as to reduce the risk of change. In an ideal system, we incorporate new features by extending the system, not by making modifications to existing code.

  • Open-Closed Principle, or OCP: Classes should be open for extension but closed for modification.

Isolating from Change

Needs will change, therefore code will change. A client class depending upon concrete details is at risk when those details change. We can introduce interfaces and abstract classes to help isolate the impact of those details.

By minimizing coupling in this way, our classes adhere to another class design principle known as the Dependency Inversion Principle (DIP). In essence, the DIP says that our classes should depend upon abstractions, not on concrete details.