Keep It SOLID
The SOLID acronym provides some guidance on design that you should follow.
- Single Responsibility Principle
- Open Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
Single Responsibility Principle
Separate your concerns - a class should do one thing and one thing only. To put it another way, a class should have a single reason to change.
Open / Closed Principle
You should be able to extend behavior, without modifying existing code.
".. you should design modules that never change. When requirements change, you extend the behavior of such modules by adding new code, not by changing old code that already works."
— Robert Martin
An indication that you might not be following this principle is the presence of
switch statements or
if/else logic in your code.
Liskov Substitution Principle
Derived classes must be substitutable for their base classes.
One indication that you are breaking this principle is the presence of
instanceof statements in your code.
Interface Segregation Principle
The Interface Segregation Principle states that clients should not be forced to implement interfaces they don't use; prefer small, tailored interfaces to large, catch-all ones.
One indication that you might be breaking this principle is the presence of empty methods or methods throwing
OperationNotSupportedException in your code.
Dependency Inversion Principle
High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
Abstractions should never depend upon details. Details should depend upon abstractions.
In practice this means you should follow one of two patterns:
- Package the interfaces a 'high-level' component depends upon with that component
- Package the interface a component depends upon separately from both the client and implementation
This first approach is classic dependency inversions (contrast it with the traditional approach of have the high level component depend upon the lower layers).
The second approach is known as the "Separated Interface Pattern". It is a little more heavy weight, but also more flexible as it makes no assumption about who should own the interface.
An indication that you are breaking this principle is the presence of package cycles within your code.