Just a reminder to everyone who is interested in WebAppSec and hasn't done so already to try PHPIDS, the Intrusion Detection System. (more...)
Posts by: Boy Baukema
PHP Intrusion Detection System (PHPIDS) August 3, 2009
Backward compatibility, bane of the developer February 7, 2008
Recently 'A List Apart' posted an article about the new X-UA-Compatible switch that Microsoft will be implementing in Internet Explorer 8.
In short, you can target versions of the IE renderer with the switch; you can say: I want this page to be rendered like IE7 would render it and then IE8 (and IE9 and IE10 presumably) would render it similarly to IE7.
Now this provoked a lot of reactions, and it got me thinking about one of the most painful subjects among developers (PHP and in general): backward compatibility.
Why backward compatibility is a problem
APIs are rarely perfect at first. They require time to mature. Sometimes APIs are just plain flawed when they get used. Anyone who has done webdevelopment for IE is painfully aware of this fact. In new versions we would like to fix these flaws and imperfect APIs; however, if a lot of other sites/applications depend on your initial flawed API, fixing the API will break their functionality.
Why we MUST HAVE backward compatibility
Reasons for this depend on the product: for instance IE must have backward compatibility because a large part of the web is old and no longer being maintained; getting these websites to migrate is unrealistic.
With PHP projects, we can't change the code in products we use in multiple projects (for instance, the ATK Framework or the Zend Framework) without taking into consideration all other projects that make use of that component.
Having to fix your project every time a new version of the underlying framework comes out is unrealistic and would be very frustrating.
What can be done about it?
- Think hard about your API
"To prevent is better than to cure" - Dutch proverb
First of all, remember when you create something that is meant to last that it should be built to last.
I have found that unit testing helps iron out the initial imperfections: be the first to use your code in as much ways as you can, before you release it.
Positive: If it is done right the first time, backward compatibility is not a problem.
Negative: Utopian; APIs will change, but striving for a perfect API is recommended.
I like the approach of the Zend Framework: make the functionality available in a special way, marking it as 'unstable' and once it has matured, integrate it with the rest of the functionality.
Positive: APIs can mature at their own pace.
Negative: If you use incubator functionality for your project, you still have to patch your application once the functionality migrates to the trunk. And even though an API may have survived the incubator, it may still need to be changed at a future date.
Mark old API/functionality as deprecated (and warn users that they are using something that is deprecated) so that hopefully, in the future once no one uses the functionality, you can remove it.
Positive: Your application will support both the new API as well as the old one for some time, easing transition.
Negative: Not all changes lend themselves to this approach (all changes to a particular method would require a completely new method), your API gets 'bloated' with deprecated methods and upgrading very old projects will still require an upgrade path.
Version x of product y works with version x of product z. The approach that IE took in the given example.
Positive: Full backward compatibility.
Negative: Increases complexity and maintenance dramatically, every time you make a change in your API and release it you are creating a new version you have to maintain. Only works for products which have very few releases.
- Upgrade paths
Break backward compatibility but notify the user who wants to upgrade what needs to be changed.
Positive: Easier for the developer.
Negative: Makes upgrading projects an (often arduous) chore.
The developer favorite, abandon the old code and start again, without promises of backward compatibility.
Positive: No more problems associated with backward compatibility.
Negative: Users/projects can't migrate any more; causes animosity among users and clients.
Unfortunately there is no one way to keep a product backward compatible, you usually end up using a combination of the above mentioned methods: Striving for the best possible API from the get go, but easing transition from the old to the new API if you do have to make changes.
For more info about backwards compatibility a good starting point is the English Wikipedia article.
- Think hard about your API