I have been writing Ruby for a long time, and Rails for almost as long. However MOST of my work has been Rails, something that I am VERY grateful to DHH for. His excellent ideas that became Rails changed my life, so:
“Thank you David, you can say what you want and write coupled code and not test first, you will always be a hero of mine for making it possible for me and all my geek friends to play with Ruby every day and make a living doing it!”
At first, I HATED TESTING. I fought it’s adoption arguing the position DHH has returned to, browser testing by humans. I hated it because I sucked at it. But I always have a mentor, and I ended up with one who was a XP’er and an old small talker. That changed my life.
But I was still testing too much, testing the wrong things, mocking too much and in the wrong place. I didn’t apparently REALLY know what a unit test was. I was using RSpec and everything I wrote was highly coupled to Rails and the database.
And these are the reasons why I hated testing and thought it sucked. I had code to write.
Why DHH cant TDD
Coupling is the amount of internal knowledge that “leaks” out of the objects you write. When objects start knowing about each other to the extent that you cannot change one without changing the other, or you can’t swap one out without changing the other. There are many other forms of coupling.
I am not the only who thinks this, and case in point, here is the GREAT Jim Weirich DECOUPLING his logic from Rails, something that DHH would have left alone or put into a concern: Decoupling Rails
Isolation is when your object has NO external dependencies. Isolation is where you want to be. Class A may know that it needs another class, but it doesn’t know it is Class B. If Class C follows the same interface as Class B, then Class A doesn’t care which it gets.
Most Rails testing code suffers from the same problem Rails suffers from:
- “Given a long enough time frame EVERY Rails app becomes a RESCUE app”
- “Given enough time EVERY Rails app becomes a LEGACY app”
Is this Rails’ fault? Indeed not. It is the programmers fault for building their app in Rails. Repeat after me. I do NOT have a Rails app. I have a RUBY app that happens to have an ActiveRecord database layer, and MVC abstraction for dealings with HTTP.
Back to the problem about testing Rails. It is hard. That is because it by nature is highly coupled. That is why you can “build a blog in 15 minutes”. And that works fine for awhile. And then it hits you. Features take LONGER to implement. Tests take LONGER to write and to run.
This is because you are building up database objects, and loading active support, and all the stuff Rails needs to do the awesome job it does.
So DHH thinks TDDing is dead and is hard, because he breaks shit at the wrong boundaries. See this talk from Gary Bernhardt.
Why I LOVE TDD and can do it
I write SMALL, SINGLE PURPOSE, STATELESS objects. I then combine them up in a style of functional programming to do the work that needs to get done. I DON’T write CONDITIONALS. My objects usually have ONE public method.
I DO NOT use ATTR_WRITER. When I have an object that needs “changing” I instead create a new object with the old values + the new value and I don’t do anything about the old one.
Not only does this allow me to write multi-core compatible Ruby, but it makes it SUPER easy to TDD up.
I follow SOLID and constantly try to find new ways of exploiting it. I also make use of LISPY constructs like CODE AS DATA, and I pass code into lists and then filter those lists.
So does this make me “better”. Nope. But I enjoy my job a lot more, I have fewer nightmares, and hell…. I LOVE LEGGO, and that is what I made my code into. Stateless Building Blocks.
I know that probably doesn’t make a lot of sense. Yet. But hang in there, and join me for my weekly free TDD workshop.
Also, seriously. Do some searches on “Functional Ruby” in Google videos and on confreaks!