December 29, 2007
Usually developers spend more time on reading code rather than writing code. Consistency makes the code more readable.
Is it better to do things consistently wrongly than erratically well? Maybe not in life but when it comes to software. Here are my ratings:
:-D consistently well
:-) consistently wrongly
:-| erratically well
:-( erratically wrongly
Sometimes particular anti-pattern consistently infests whole application. There is no point in throwing bodies in refactoring it because the cost may be little compared to the gain. Anti-pattern may be well-known and in general not extremely harmful. Refactoring it in one place may seem decent but introduces inconsistency with all the other places. I value overall consistency over single-shot elegance.
There’s no rule without exception, right? Sometimes the goal is to implement something in completely different way, to implement an eye-opener, to create “the new way”. Then one could relay on distributed-refactoring spirit of the team and let others join refactoring feast. If the spirit evaporated :(, one could always make using “the old way” deliberately embarrassing or just frikin’ difficult.
Consistency rule helps in all those hesitations a developer has on daily basis. Ever felt like two-headed ogre from Warcraft?
“This way, no that way!” – the heads argue.
Yes, you can implement stuff in multiple ways… My advice is: know your codebase and be consistent. Choose the way that was already chosen.
Being consistent is important but not when it goes against The Common Sense. Obviously ;)
December 19, 2007
If the class is difficult to test don’t blame your test code or deficiencies in mock/test libraries. Instead try very hard to make the class under test easy to test.
Is class hard to test? Then it’s the class itself to blame, never the test code.
The punishment is simple: merciless refactoring.
Yet so many times the test is found guilty and unjustly sentenced to refactoring or improving.
Here are some real-life examples – I saw it, I moaned, I preached (poor soul who paired with me that day):
- Class calls static methods. New patterns of mocking static methods are introduced. Yet another mocking framework (or supporting code) is added. Instead, static class could be refactored into genuine citizen of OO world where dependency injection really does miracles.
Ok, I didn’t really see that one. But I read about it ;)
- Class has many dependencies. The builder is introduced to create instances with properly mocked/stubbed dependencies. The effort to refactor test code and introduce builder could be spend on splitting the class so that it is smaller, has less dependencies and doesn’t need a builder any more.
- Class has many dependencies yet again. The test class is enhanced with bunch of private utility methods to help in setting up dependencies. Yet again I would rather split class under test…
- Test method is huge. Test method is decomposed into smaller methods. Instead I would look at responsibility under the test. Perhaps responsibility/method under test is just bloated and solves multiple different problems. I’d rather delegate different responsibilities to different classes.
All of that goes down to very simple principles I follow.
If I find testing difficult I look for reasons in the class under test. If the test smells I look for reasons in the class under test. Class under test is always guilty until proven.
I’m not saying to stop refactoring test code, I’m saying to focus on class under test. Don’t make test code smarter if you can make the code easier to test. If you spend too much time on figuring out how to test something it means code under test sucks.
For me, the quality of the class is reflected by the clarity and simplicity of its test.
Here are some warnings you can find in the test code.
- too big setup() method
- too many fields
- too big test method
- too many test methods
- too many private utility methods
All of them smell and require refactoring. You can refactor test code, make it smarter and better. You can also refactor code under test so that the test doesn’t have to be smart and becomes simple. Simple code doesn’t smell. Usually. ;)
December 18, 2007
Tomo writes how to mock static methods and how cool is JMockit. This gives me an opportunity to write about something loosely linked with his post.
No offence Tomo ;), but I don’t believe that the class is difficult to test because I don’t know enough mock libraries. The class is difficult to test because its design sucks. Static methods are difficult to mock and I am really pleased with that. At least developers will avoid them in order to keep the code more testable. When you introduce new shiny pattern of mocking static methods other developers may follow you. That means more and more static methods.
However, there is something else that strikes me. It’s the acrobatics around the test code in order to test a class. It should be other way around: if a class is difficult to test then stop hacking the test code and refactor the class. The best approach is obviously TDD – you always end up with testable classes.
I’m not talking about static methods any more? Good. I’m not really against static methods. I love them, we should all love them and keep them safe on 3.5 floppies among other turbo pascal code.
This supposed to be an intro to more interesting stuff but ragging static methods gave me weird and unexpected pleasure. Oh right, I’m not that zealous to treat all static methods with a flame thrower. Stuff like utility libraries – they’re fine and I’ve never needed to mock them. Tomo defends static methods bravely (see comment below). He is right but mocking static methods still smells funny… If the class is difficult to test I just wouldn’t challenge the test code. I’d rather try very hard to make the class under test easy to test.
I rant about it here.