10: Classes
Class Organization
Variables
Public static constants, if any, should come first.
Private static variables
Private instance variables
There is seldom a good reason to have a public variable.
Functions
Ordering should follow the ordering of variables.
Encapsulation
Utility functions should typically be private, but we're not fanatic about it.
Sometimes a variable or utility function needs to be protected so it can be accessed by a test. If a test in the same package needs to call a function or access a variable, we'll make it protected or package (internal) scope.
Loosening encapsulation should be a last resort.
Classes Should be Small
First Rule: Classes should be small! Second Rule: They should be smaller than that.
Function size is measured by counting lines. With classes, we count responsibilities.
Class names should describe the responsibilities it fulfills.
If this is difficult, the class may be too large.
The more ambiguous the class name, the more likely it has too many responsibilities.
Avoid weasel words:
Processor
,Manager
, orSuper
Single Responsibility Principle
Getting Software to work and making software clean are two very different activities.
Too many of us think we are done once the program works.
We fail to switch to the other concern or organization & cleanliness - breaking down overstuffed classes into decoupled units that follow the SRP.
Do a large number of small, single purpose classes make it more difficult to understand the bigger picture?
Would we rather have tools organized into toolboxes with many small drawers each containing well-defined and well-labeled components? Or do we want several large junk drawers?
The primary goal in managing complexity is to organize it so that a developer knows where to look to find things.
Summary
We want our systems to be composed of many small classes.
Each small class encapsulates a single responsibility, has a single reason to change, and collaborates with a few others to achieve the desired system behaviors.
Cohesion
Classes should have a small number of instance variables.
Each of the methods should manipulate one or more of those variables.
A class in which each variable is used be each method is maximally cohesive, but it's not advisable nor possible to achieve this fully.
When cohesion is high, methods and variables of the class are co-dependent.
Maintaining Cohesion Results in Many Small Classes
When classes lose cohesion, split them!
Breaking large functions into many smaller functions often gives us the opportunity to the code into several smaller classes.
Organizing for Change
We want to structure our systems so that we muck with as little as possible when we update them with new or modified features.
Small cohesive classes help us do this.
In an ideal system, we incorporate new features by extending the system, not by making modifications to existing code.
Isolating from Change
A client class depending on concrete details is at risk when details change.
Interfaces & abstract classes help isolate the impact of those details.
Dependencies on concrete details create challenges for testing our system.
A system that is decoupled enough to be tested will also be more flexible and promote more reuse.
A lack of coupling means that elements of our system are better isolated from each other and from change.
Isolation makes it easier to understand each element of the system.
Minimizing coupling helps us adhere to the Dependency Inversion Principle (DIP).
Last updated