Rodrigo Rosenfeld Rosas

Should we move forward or remain backward compatible?

Sun, 04 Mar 2012 12:30:00 +0000

This is just an article's title, not really a question with a right answer.

It is not always possible to both move forward and remain compatible with legacy code.

Usually, when a project starts there is no legacy code and every change is welcomed. Later on, when the project grows and the user's code base gets bigger, some people will start complaining about incompatible changes because they'll have to spend some time changing their code base when they decide to upgrade to a newer version.

When this time comes, the project has to make a decision. It should either keep moving forward and fixing badly designed API when they realize there is a better way of doing things or they should accept that an API change can be very painful for their framework/library users and decide to keep on with the bad API. Java definitely opted for the latter.

The Rails case

In the last weeks, I've been reading some articles complaining about Rails changing its API in incompatible ways too fast.

They're not alone and I've seen complaints about this from several other people. In the other side I'm constantly refactoring my own code base and I appreciate Rails doing the same. In the case of libraries and framewoks, when we're refactoring code, sometimes we come to the conclusion that some API should be better written even if it breaks old software. And I'm also not alone in thinking this way.

Unfortunately, I couldn't find an employer to pay me to work with Rails as much as I do as a Grails/Groovy/Java developer for the last 3 years. And that is really a pain with regards to API, stability and user experience. I don't remember complaining about anything in Ruby or Rails that I really missed since internationalization support was added to Rails in version 2.

The Groovy / Java case

This section has grown too fast, so I decided to split it in another article entitled How NokoGiri and JRuby saved my week.

You don't have to read the entire article if you're not curious enough, but the Groovy XML parsers API was so badly designed and documented that I could finish the logic with Ruby and NokoGiri in about 2 hours (with tests and setup included) while I spent the entire week trying to do the same in Groovy.

And the result in Ruby would take about the same time for the import to complete. I had to dig into Groovy's source code due to lack of documentation and do lots of experiments to understand how things worked.

You can fix documentation issues without changing the API, but you can't fix design issues with Groovy parsers without changing its API. So, is it worth keeping the API just for being backward-compatible and make XML parsing a pain to work with in Groovy?

Then what?

There is not a better approach to take when you decide for remaining backward compatible or keep forward. So, each project will adopt some philosophy and you need to know its philosophy before adopting it or not.

If you prefer API stability over consistency and easy of use, you should choose something like Java, C++, Perl, PHP or Grails. You shouldn't be really considering Rails.

In the other hand, if you like to be on the edge, then Rails is exactly the way to go.

Which one to choose will basically depend on these questions:

  1. Do you have a good test coverage of your code base?
  2. Do you have to respond really fast to changes?
  3. Will your code hardly change after it is finished?

If you answered "yes" to 3, than you should consider a framework that will avoid very hard to break its API, since no one will constantly maintaining your application to keep up with all the framework upgrades with fixed security issues, for example.

In the other hand, if you have answered "yes" to 1 and 2, using a fast pace changing framework like Rails shouldn't be an issue. In my case, I don't write tests for my views as they're usually very simple and doesn't contain logic. So, when Rails changed some rules about when to use "<%= ... %>" or "<% ... %>", I had to manually look at all of my views to fix them. And I had to do that twice between Rails 2 and Rails 3.1, for example because they did change this behavior back and forward and this is the kind of unnecessary change in my opinion.

Other changes I had to manually check because I don't test my views is due the change of the output of ERB tags being escaped by default. But that is a good change and I'm pretty sure I forgot to manually escape some of them before the upgrade. So, my application was probably safer against attacks after the upgrade, so this is a good move even so it took a while for me to finish the upgrade. There was no easy path for this change.

But other than that, it was just a matter of making the test suite pass after the upgrade, and if you valuate code refactoring as much as I do, you'll be writing tests for all code that could possibly break in some refactoring.

And this was a hard issue I have with Grails. I find it too time demanding to write tests for Grails applications and it was really a pain before Grails 2 was released. It is still not good, but I can already write most of my unit tests in Grails without much problem.

So, I would suggest you to answer the above questions first before choosing what web framework to adopt. It is not right to get a fast moving framework because its API is better designed and then later in the future ask their maintainers to stop changing because now you have a working application.

You should know how they work beforehand and accept this when you opt of it.

Powered by Disqus