The document discusses principles for writing simple testable code including focusing on core values like simplicity over flexibility, keeping code clean and formatted, injecting dependencies through constructors or parameters to reduce coupling, writing isolated tests that assert behavior rather than implementation, and using refactoring to maintain simplicity. It also provides references for further reading on simple code design.
How it all started...I was doing TDD and felt that my code could have been simpler. So I started to think about how to make simpler code while still being able to unit test it. Started a few months ago, so still work in progress, but I want to share what I have concluded so far. Who does refactoring? Who does unit testing? Who does TDD?
Software evolves. You will have to go back to the crappy code. Simplicity and testability for maintainability. For fun!
As I mentioned, I was doing TDD and was not very satisfied with the results. I'm not saying that TDD is bad, but I want to highlight some problems I have with TDD: Tests direct the design...but is it the simplest design or is it a local minima. Unit tests are often seen as a substitute for thinking...I need to change this, let's change it, check if anything is broken. Unit tests are safety nets, but they have holes...better not to fall. It is not because you are doing TDD that you write good code. TDD with bad test code is dangerous.
Starting point for the reflection.
Clean Code is good, but sometimes goes too far. Clean code is more about rules than mindset. I have a problem with the whole software craftmanship...you are not doing TDD then you are not a professional programmer. So I warn you, I'm not a professional programmer, but still getting paid to program.
You chose not to go the the session on refactoring...there you go all you need to know :) Writing simple code is good. Evolving simple code is not as easy. That is were refactoring comes into play. Refactoring plays a role in keeping the code simple after each evolution. Unit tests allows refactoring with a safety net. So we need unit tests!
Why test in isolation? control: the option to provoke some hard to produce scenarios in real life. to test edge cases. stability: want to investigate real test failures. So we want to test class in isolation...how do we isolate?
Show dependencies. Show testable version. Show unit test.
That explains why test code can slow down. Test code is fragile! Can we write better tests...tests that would not have to change everytime the production code changes. Test code has to be coupled with the class interface/methods. Test code should not be coupled with the implementation details. Not an easy task...
First, keep test code minimal and keep test code simple.
When injecting dependencies to a class, you can choose what to inject.
This is the hard part... Stop verifying everything you can!
I've used EasyMock for years...here is why I switched. Do I care to verify all interactions? Maybe I just care about the result. Do I care if the configuration is accessed 1 or 5 times? Do I want to check all interaction in all tests?
Default behavior. Change if needed for a single test. Assert what is tested.
Side note... Pattern that both create simple code and easily testable code. Stateless classes.