You may be familiar with the SOLID principles of object-oriented design. SOLID is an acronym introduced by Michael Feathers to help remember five of the important principles of object-oriented design outlined by Uncle Bob Martin. If you’ve never heard of them, I highly recommend learning about them.
The SOLID principles apply mainly at the class, object, or method levels. They can have wider application, but they are largely used at these lower levels of code.
When Uncle Bob was originally writing about these principles, he also outlined six principles for design at the package level. These principles are far less commonly known and understood today, but they’re still important to think about.
Over the next few posts, I’ll introduce the principles and then discuss the implications of applying these principles to our code.
First up, the three principles of package cohesion.
The first three packaging principles are about package cohesion. That is, how do we partition classes into packages? How big should our packages be? How many of them should we have?
The Reuse-Release Equivalence Principle (REP)
The granule of reuse is the granule of release.
The basic idea of this principle is that packages must be separately released, versioned, and tracked. In order to make use of a package in other code, we need to be able to safely depend on that package. For that, we need to be able to choose when and if to update to a newer version of the package.
Consider using Semantic Versioning for your packages to provide clues to your users about how much work they can expect when upgrading to a new version of your package.
The Common-Reuse Principle (CRP)
The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all.
This principle suggests that we group classes into packages based on whether or not they are used/re-used together.
If you depend on a package but only use a small part of it, you still depend on the entire package. If other parts of the package change, you have to think about updating your dependency, even though the changes have no effect on your code.
For example, on an episode of the Ruby Rogues podcast James Edward Gray mentioned that in the old days of Ruby, people would depend on WEBrick in order to use its internal utility for starting a daemon process. These projects would depend on all of WEBrick for one little piece of plumbing that it had built-in.
If you see something like this happening in your code, it’s a signal that there is a separate package wanting to get out.
The Common-Closure Principle (CCP)
The classes in a package should be closed together against the same kinds of changes. A change that affects a package affects all the classes in that package and no other packages.
This principle is essentially the Single Responsibility Principle (SRP) for packages. “Closed” is used here in the same sense as it is in the Open-Closed Principle (OCP).
When we need to change our code, it is best if we only have to change one package. So, it makes sense to group classes together that have to change for similar reasons and to separate classes that have to change for different reasons.
As an example, I work on a system that has packaged the code along infrastructure boundaries. There’s an API used by other systems, a “model” layer, a hardware interface layer, a hardware simulation, and a few other pieces. When we add a feature to this system, we typically have to touch all of the packages, because we need to make changes in all of the layers. This principle suggests that there might be a better way of structuring this system.
* Agile Software Development: Principles, Patterns, and Practices: This is Uncle Bob’s book that introduces all of these principles. All of the quoted principle summaries above are taken from this book.
* Principles of OOD: Blog post by Uncle Bob briefly describing the principles.
* Object Mentor Articles: Numerous articles by Uncle Bob and others from Object Mentor on many topics. I learned a lot by reading these articles when they were written, and they have significantly shaped how I think about software today.