This is a mobile version, full one is here.
28 February 2017
How to Handle the Problem of Too Many Classes
During nearly every presentation in which I explain my view of object-oriented programming, there is someone who shares a comment like this: “If we follow your advice, we will have so many small classes.” And my answer is always the same: “Of course we will, and that’s great!” I honestly believe that even if you can’t consider having “a lot of classes” a virtue, you can’t call it a drawback of any truly object-oriented code either. However, there may come a point when classes become a problem; let’s see when, how, and what to do about that.
There were a number of “rules” previously mentioned that, if applied, would obviously lead to a large number of classes, including: a) all public methods must be declared in interfaces; b) objects must not have more than four attributes (Section 2.1 of Elegant Objects); c) static methods are not allowed; d) constructors must be code-free; e) objects must expose fewer than five public methods (Section 3.1 of Elegant Objects).
The biggest concern, of course, is maintainability: “If, instead of 50 longer classes, we had 300 shorter ones, then the code would be way less readable.” This will most certainly happen if you design them wrong.
Types (or classes) in OOP constitute your vocabulary, which explains the world around your code—the world your code lives in. The richer the vocabulary, the more powerful your code. The more types you have, the better you can understand and explain the world.
If your vocabulary is big enough, you will say something like:
Read the book that is on the table.
With a much smaller vocabulary, the same phrase would sound like:
Do it with the thing that is on that thing.
Obviously, it’s easier to read and understand the first phrase. The same occurs with types in OOP: the more of them you have at your disposal, the more expressive, bright, and readable your code is.
Unfortunately, Java and many other languages are not designed with
this concept in mind. Packages, modules, and namespaces don’t really help,
and we usually end up with names like
We’re trying to pack as many semantics into class names as possible so
their users won’t doubt for a second. Then we’re trying to put as many
methods into one class as possible to make life easier for users; they will
use their IDE hints to find the right one.
This is anything but OOP.
If your code is object-oriented, your classes must be small, their names must be nouns, and their method names must be just one word. Here is what I do in my code to make that happen:
Interfaces are nouns.
There are no exceptions. Types (also known as
interfaces in Java)
are the core part of my vocabulary; they have to be nouns.
Classes are prefixed.
My classes always
implement interfaces. Thanks to that, I can say they always are
requests, directives, or domains. And I always want their users to remember that.
Prefixes help. For example,
is a buffered request,
is a simple request,
is a request that represents a “live” HTTP connection,
is a request with an extra header.
An alternative approach is to use the type name as the central part of the
class name and add a prefix that explains implementation details.
is a domain that persists its data in DynamoDB.
Once you know what that
Dy prefix is for, you can easily understand what
In a medium-sized application or a library, there will be as many as 10 to 15
prefixes you will have to remember, no more. For example, in the
Takes Framework, there are 24,000 lines of code,
410 Java files, and 10 prefixes:
Xe. Not so difficult to remember what they mean, right?
Among all 240 classes,
the longest name is
I find this approach to class naming rather convenient. I used it in these open source projects (in GitHub): yegor256/takes (10 prefixes), yegor256/jare (5 prefixes), yegor256/rultor (6 prefixes), and yegor256/wring (5 prefixes).