In my previous post I started talking in more coherent words about feelings I’ve had lurking in the past year. This post is an expansion of that, after having some great twitter conversations in the past few days with some great people. Treat this as a stream of consciousness.
before that, here’s a short highlight summary of responses to my post in other blogs:
- Steve Freeman thinks I’m pulling the wrong way
- So does Ayende (in a way)
- A goof thread on this in the alt.net mailing list
there are also plenty of people who picked up the ball (some of them have already done that before I started mumbling on my blog) and continue to make better attempts at bringing knowledge to the masses, in more coherent, newbie friendly manner.
- Rhys shares some hints and gotchas
- Ian Cooper gets it (even if he doesn’t think he does – I’ll explain later)
- Jeremy is asking important questions
- Jimmy has good tips
and the comments on that post are… interesting (some are very expected, though).
Let’s make another interesting statement, and this one is indeed product related.
To reach the masses, we need to decouple S.O.L.I.D Design Principles from Unit Testing and TDD
I’m not saying throw out design. I’m saying – it’s important enough to be learnt on its own, and not in the context of tests. in fact, in that context, it inhibits too many people to be practical as a learning tool. so we need to separate forces.
The wall to start unit testing is too high (for most devs) and will always be too high if you have to know your SOLID in order to even start writing your first test or refactor your code for testability. This problem only exists in static languages like Java, C# and VB.NET, where in order to replace something you need to have a way to do polymorphism on that class (interface, or inheritance with virtual methods).
The reason people love Test Driven design so much is because the technique, aided by most of today’s leading mock frameworks, squeezes out all the problematic static coupling that exists in the current design, before it will even let you test something. Can’t decouple that web service dependency from your class? you’re screwed. Redesign and only then you can test it. Have a static method that gets called? you’ll need to jump hoops to override the calls to that method, let alone the method itself. Feel the burn, baby!
TDD existed before mocking frameworks existed. what did people do then? SmallTalk was one of the first languages that had people doing TDD with it. SmallTalk is testable by default in that you can re-define anything to do anything else at runtime. People just thought about their design as they wrote the tests first, and they had no real constraint on what specific design to follow. It still holds today in Ruby, for example.
Now, the reason today’s “hardcore” Test Driven Design is even possible is because current mocking frameworks rely on static language (and compiler) to tell the developer what can and cannot be done in terms of replacing objects and implementations. That forces a specific design methodology that closely matches what SOLID principles stand for, and it’s great. you get great code out of it, and nice designs.
I repeat – I love the idea of SOLID design and I practice it.
So, why do I think that these things should be decoupled? At the end of the day it is a constraint that is put upon each developer that wants to start unit testing (not even talking about legacy code right now). That means that each developer that starts tests will hit a brick wall and will have to start reading up on all things SOLID, patterns, or just buy my book. There is no “easy” way. and that’s fine and dandy for most of the people reading this blog. And for the past four or five years, it’s been just as fine and dandy for me too.
BUT, The adoption rate for TDD and unit testing at all is low, and I suspect that it is indeed this learning curve that makes that possible. And it will continue to be low as long as doing great (not OK, great!) designs is a prerequisite to doing proper unit testing (or at all). The current mock frameworks (most) enable this notion and embrace it.
Today we live in our own little echo chamber where everyone is happy with their “pure” designs and consultant fees, because we are part of a very elite group: those you need to pay in order to learn the “hard stuff” to do something which many people want to do but just can’t. It’s almost like knowing Regular Expressions, except a much larger scope. We’re making it harder on purpose to start doing unit testing, because we believe that it’s someone’s best interest (and in a way, in our best interest) to learn SOLID first.
The people I know from the mocking community are amazing, passionate and smart people. They would never do anything they don’t fully believe in, and their value system is almost radically pure. And I love that. but we cannot play judge here. people learn in different ways, and the low adoption rate tells us that it’s not working as well as expected.
Why would decoupling work?
If we were able to decouple the requirement of knowing SOLID and just get people to start testing today and learn SOLID later or in parallel, adoption would be much higher. Why?
- People who get test infected soon want to learn SOLID anyway
- People who succeed doing one thing, will be more open to adopting other things from the same source of knowledge
- It’s less scary, and less time consuming to start doing things. We reduce the barrier to entry into the agile world.
- It allows developers in a non-agile environment to do little,incremental steps on the road to a better way of working, without needing to chow down the whole meal in one big bite.
- Sucky tests are better than no tests. They also lead to better tests and better understanding of design as people learn and get better at it.
What’s stopping us?
But with the current set of mock frameworks, you can’t do all those things. you technically are not allowed to do that. and that’s why solutions like Rhino, Moq, and NMock will not appeal to the masses, and why solutions that support other types of design decisions (JMockit, Typemock Isolator) will continue to gain popularity as people strive to become more agile under non-agile conditions. they provide that needed stepping stone to learn unit testing without needing to learn SOLID as a requirement. That’s the difference. But the community is actively depressing thoughts about using such tools today because of the belief that TDD and design have to go hand in hand at ALL times.
Many of them that will read this are scared that I’m even suggesting this, because they fear a return to darker ages where people didn’t have a clue, and there was nothing to stop them from screwing up the design. But as you’ll see later on, the plan is to get people on board the design stuff, just not as a prerequisite to the unit testing stuff. that’s all.
Of course, the big problem here is that I actually work at Typemock, and thus, many people feel that every word that comes out of my mouth is a sales pitch. but the reality is that if Typemock had been an open source project, those people would have read the words that I write, and not try to find a hidden meaning in them. and the truth is I’d write something like this even if I didn’t work there today. I’d quit to say these words with more credibility but I want to have an impact on how those products work and feel, so I’m not going to do that, sorry.
What does the industry need to do?
Direct people who are reluctant to go through that big learning curve or have a problem with the current frameworks to tools that mitigate those fears (Typemock, JMockit). One is open source, the other has an open source free license. so they are both achievable to use and play with.
When doing so, learning better design techniques should be on the horizon. but it’s important not to discourage use of these frameworks on existing non SOLID design notions. people have a hard time with change as it is. They need to learn one step at a time and we have to let them have the time to grok things separately if they want to.
Decouple the task of teaching unit testing from the task of teaching design. They are both important but are not a requirement of each other. We need more Design material out there with a simple way to reach and find it (we’re on the way today). Unit testing information is already out there and more is going out every day.
Realize that tools that enable different designs are not a problem, but a way to get a foot in the door with developers who wouldn’t walk through that agile door in other ways. it’s a bigger net to catch more fish. These tools allow people to have a bridge to the agile world with less pain involved.
This is something that we need to continue talking about, since it can change the future for most devs today. If we shy away from talking about this, and stay in our cozy little submarine underwater, we will sail right beneath all those people lying on the beach, wondering what’s up with all those people in the water, or afraid to take a swimming lesson. (yeah, the world’s worst analogy)