Rails 2.3.9 was released this week. Rails 3.0 is already out, and the main purpose of this release is to smooth out the migration path a bit. This means we're watching for deprecation warnings, right? Okay. I installed it and ran my test suite. I got a whole bunch of this one deprecation warning:
DEPRECATION WARNING: Object#returning has been deprecated in favor of Object#tap.
I have been a fan of Object#returning, but Object#tap was a new one on me. I looked them both up. Here are their sources:
They clearly do exactly the same thing, one with an argument, the other with itself. It's the classic smell of duplication. Now they're fixing it. Their code is getting cleaner, and I have to change my code to stay in line and keep it from breaking in the future.
I have been developing software on the Microsoft stack for twenty years now. That is more than enough time for me to have based a few opinions about "how things are done" on their example. I have been developing in Ruby and in Rails for about three or four years now, and I see some very different ideas played out about "how things are done."
Among other things, I see two polar opposite approaches to breaking changes in tool sets, be they language or framework. Microsoft has always done everything they could to avoid introducing any breaking changes into their tools. This is a good thing, right? Who would not want to know that the code they wrote today will still work after they install the next update? In twenty years as a 'softie, the only major breaking changes I can remember being introduced came with the move from VB6 to .NET in early 2002, enough VB developers made enough noise that Microsoft went back and retroactively added backward compatibility with many legacy VB language constructs that had been removed in the 1.0 release.
On the other hand, new versions of Ruby and Rails often have some breaking changes. Not only do changes often break things, but they come much more frequently than they do in the Microsoft world. The standard update routine here is to read the release notes to see what to look for, install the update, run the test suite, see what broke, and get to making changes to fix things. This is a bad thing, right? Or is it?
Take a step back and look at the cumulative effect of these two approaches. In the Microsoft world, we have more of a sense of stability going forward. In the Ruby world, the tools have more freedom to change. If Microsoft allows any mistakes, bad design decisions, dangerous features, etc., out into the field and into the hands of developers, it is most likely going to be years before they can fix it, if they ever can. The problem might be there for the life of the platform. In the Ruby world, the same types of mistakes get made, but fixing them will usually involve a deprecation in one release and then a fix in the next.
So why can world afford to change things and the other not? Is it because they just don't care? Is it because there is no corporate entity afraid of making everyone mad enough to abandon their platform? Ruby and Rails are clearly thriving in this world of breaking changes. How? What is the difference? The difference is in the tests.
They have created an ecosystem that is dependent on test coverage. If I have a good test suite, I know where my breaks are as soon as they occur, whether they have come from a library update or from changes I've made myself. Change is no longer so dangerous. We can also have a sense of stability here, but it comes from testing rather than from the lack of movement. If I am not in the habit of keeping good test coverage, it is going to be difficult for me to survive in this culture. So Darwin keeps us test-covered and change-tolerant.
When change is no longer something to be avoided, we gain a new freedom to improve things. The Boy Scout rule of leaving code in better shape that you found it has long-term effects. Things get better. This is what refactoring is all about, right? Don't we spend more time maintaining a system than building it? I think most systems get built way before they get good. And if they can't be refactored, molded, tweaked, rearranged, nurtured, changed; they never will get good.
I think it is the cumulative effect of the freedom to improve things that has brought Ruby and Rails to place they are today. I find them thoroughly enjoyable tools to use. They're not perfect, but they're better than they were last year, and they're not as good as they will be next year. If that means I have to take a little time with each release to roll with the changes, that is a small price to pay.