Tests are superglue for design
Tests and design has a close relationship. If your design sucks, writing tests is really difficult. If you want to change your code…
Tests and design have a close relationship.
If your design sucks, writing tests is really difficult.
If you want to change your code, your tests can push you to avoid the change.
Spoiler Alert: I’m going to talk about the end of “The Lego Movie” to explain all of this.
In “The Lego Movie” Lord Business has a weapon called Kragle that uses to freeze Lego World.
“The Kragle” is just glue and Lord Business wants a perfect immutable world, he hates change, any kind of change, this is why it is a really powerful weapon for him.
In software everything is about change, we have to define what to change easy and what should not change so easy.
This is one of the reasons why I suggest testing behavior and not to test every public method of every class, function whatever the language is based on.
Because tests behave as glue related to the service under test, they are testing.
This is related to design, the units you have created and how to interact between them are related to the signature of the methods you use in your code, but also about the behavior of those methods.
Tests will persist both things, the signature of the method and the behavior, this is part of the tradeoff.
If all the methods I have are tested I’m doing the same as Lord Business, I’m creating a world difficult to change, difficult to refactor, difficult to redesign.
I need to persist behavior, I want a way to be sure that if behavior changes I’m notified about that change and I can react to fix the problem. Tests are fitness functions that help me on this.
I also want to be sure my public APIs, those used outside my influence to change things, remains as immutable as I can. Because If I change deeply an API used by other people, I’m creating a big problem to them.
API first is a way to focus first on design of what others will interact with the behaviors my code provide.
I also want to change things in the internal parts of my code with no much effort not affecting the edges, what means to have internal parts that are isolated of the public APIs and from third parties my code needs to use.
Change internal parts of my code without changing the behavior is refactoring. I want to be able to make easy to refactor.
This is a design decision. Design is about what things will be easy to change and what other things will not be so easy to change.
Design appears here really related to my testing strategy, my tests can guide me on what to persist, behavior, design or both things.
Tests persist design, if I decide to design my code using hexagonal architecture and all my tests are testing use cases and set doubles for secondary ports the things difficult to change will be the signature and semantic of those use cases and the signature and semantic of the secondary ports.
In the middle of those edges I will be able to change everything but behavior because the behavior will be checked by my tests.
This is a design decision. My tests are helping me to allow internal refactoring and to design in that way to have an internal thing that I can change easily.
If I write tests for every class everywhere, the cost of refactoring will be high, so I’m persisting the previous design without allowing people to change it. I’m creating a natural force (my tests) that pushes for an immutable design => I’m persisting my first design.
Basically, tests can be used like glue to decide what to change easy and what to make harder to change, one of the main things a good design should do.
This is why you can use tests to design software in an evolutionary way.
Stackademic 🎓
Thank you for reading until the end. Before you go:
Please consider clapping and following the writer! 👏
Visit our other platforms: In Plain English | CoFeed | Differ
More content at Stackademic.com