Code Dynamics
How and When code changes are two seemingly very different dynamics? But wipe away the dust and we find they represent two sides of the Same Coin. In this post we are going to dig in to the dynamics of code change, and, if I do my job, we will also answer an implicit question raised by TDD & The Lump of Code Fallacy: Should there exist multiple fixture files for a given class. But first...
What Is Code?
Let's get one thing straight: Fixtures Are Code. They are on the very same level as what we typically think of as project code. This goes for any project resource: they are all First Class Citizens of a Software Project. The same professionalism we bring to our class files - we bring that same professionalism to SQL files, style sheets, images, content, documentation. We do this because we center on SRP, and in doing so we simply cannot treat anything about a project as ancillary, as less than, as somehow unworthy of our full Experience, Dedication, and Support.
So when we discuss code dynamics, we are talking about all the code. We are talking about the How and When of all project assets.
When Dynamics
Those of you who know me - or have read my blog - know that I center my software engineering craft around SRP. My wish is that you too center your software engineering around SRP. In terms of outcomes, in terms of speed, in any terms you want to measure, SRP at the center just makes sense. Even more so than TDD, it constrains How you do and When you do so that your options are limited to only the Right ones.
With SRP at the center we have two and only two reasons When code changes:
- Assertion Change is indicated.
- Refactoring is indicated.
Assertion Changes are indicated by user stories, load and stress requirements, failing tests. There are other sources, but in general they produce something the system needs to do to continue to be the Right System. Remember that we always define Right System in terms of outcomes, in terms of what the customer Needs today.
Refactorings are indicated by SRP...it will tell you...if you commit to it. What that looks like in practice is kind of like detailing the ingredients of a Secret Sauce...the range is too vast to detail. But in general any combination of the following will indicate Refactoring:
- Abstruse Symbols (Variable, Type, Namespace)
- More Than Three Parameters
- More Than Five Method Lines
- Commented-Out Code
- Orthogonal Methods
- Unwieldy Fixture Mechanics
- Intermittent Test Breaks
- Multiple Unit Fixtures (Clue!)
The key thing about When Dynamics is that we resist the temptation to predict change - rather, we wait until change is explicitly indicated. That is When Dynamics; that is When Our Code Changes.
How Dynamics
After writing When Dynamics section I think it is completely clear that the above also follows for How Dynamics. In other words, How code changes is directly driven by Assertions and Refactorings. How you effect a change When it is time to change is a byproduct of either SRP or assertion changes. You do what an assertion indicates to do. Or you do what SRP indicates to do.
How code changes has some additional aspects not relevant to When code changes. They center around Team Dynamics.
- Commit Often
- Integrate Early
- Repeat Right Patterns
- Highlight Wrong Patterns
- Share What You've Learned
- Share What You've Not Learned
The key thing about How Dynamics is that we sustain the source, the catalyst, the reason that made this When to change. In other words, if SRP indicates a Refactoring then carry through that stimulus. Make the refactoring the focus of your work, and don't get distracted from that mission. If the refactoring results in moving code to another code file - carry that through to the fixtures. As Michael Hill implied in his (linked) post, fixtures and implementation represent an indivisible pair. When the fixture is on a change vector, then also is its class under test. And now we can answer the question: One or more than one fixtures per class under test?
Fixtures Per Class?
Let's get particular here: in terms of Unit Tests there must be a one-to-one between fixtures and classes. We need only summarize what we covered in this post to prove it. Using SRP, a fixture will test the Single Responsibility of the class under test. If you must split a fixture, then you are looking at a Refactoring Indicator for the class under test. Or to summarize differently, both the class under test and fixture are on a change vector together...so whatever happens to one happens to the other. One-to-One.
Now, Functional and Integration fixtures also follow SRP - but they have multiple partners. They are on change vectors with other components of the system and/or other systems. This relationship is Many-to-Many and not One-to-One as with Unit fixtures.
Conclusion
I enjoyed discussing code change dynamics and how that drives the relationship between fixtures and classes under test. If you have questions or want to hear more about this topic hit me up @Rjae.