[DRAFT] Emergent Design: Refactoring and the Stable Dependencies Principle
February 04, 2017
The Stable Dependencies Principle (link on C2 - wiki.c2.com/?StableDependenciesPrinciple) is often expressed as a principle applying between modules.
Sometimes language fails us, and sometimes it’s hard to understand when this might apply to code we’re writing. Is a module a class? A function? A NuGet / NPM / JAR / GEM / EGG / etc?
The idea is simple - try not to depend on things that change too often, because you’ll likely have to change with them. This is the key principle when disassembling a project that has become “large” (for whatever definition of large happens to suit you at the moment).
One of the core tenets of agile software development, is the idea that when we begin down a path, we know the least about where it will take us. We often start with fuzzy or missing requirements, loose definitions of what “done” might one day look like. Step by step we code software towards that goal. Claiming that we know what the shape of the software should be at the outset seems a fools errand.
Mary and Tom Poppendieck brought us the idea of the Last Responsible Moment. The idea that deferring decisions in the development of a system until we have gathered more information will serve us well. There will come a time at which further deference of that decision will cause harm, and that time is described as the Last Responsible Moment.
Think about decisions you make as you code. Should I extract an interface now or later? Is this one class or two? Do I see some groupings I can make around responsibilities in this system I see emerging in front of me?
Refactoring code can be time consuming without appropriate tools support. A strong IDE with refactoring features will help you keep your sanity while exploring this path. None of them are perfect, but we are slowly progressing towards better and better systems. Just remember, you are expected to deliver software today.
Some of the first concepts like extracting a variable or object property, extracting a method, extracting a class, these let you take a piece of code and gently lift apart concerns. Writing small methods let you build up classes that might begin to exhibit signs of multiple responsibilities. As you separate classes you start to explore along the edges of the stable dependencies principle.
As your classes begin to depend on each other, pay attention to what depends on what. Look at your source-code stats on how much things have changed in a class throughout your project (act on fact, not conjecture).