GTK+ 3.0, enabling incrementalism
This is a reply to some comments on Kris blog post about our vision of GTK+ 3.0.
First off, as I said in my reply there, I think it’s important that we do not make GTK+ 3.0 into a holy grail of all the features we would like to see in GTK+. There will always be features lined up that would make sense to push in, some which will change fundamental things in the core.
The way I see it (which Havoc seem to as well) is that a change of the Widget core to a scene graph is a project that will take place outside of the GTK+ tree and at some point get endorsed and included. This is a process that is likely to take several years and I do not see any reason to put GTK+ on hold, waiting for it.
There are still things that can be done on the GTK+ 2.x tree without breaking ABI. However, it is getting harder and harder (in some cases already impossible) to do it in a compatible way. A tremendous effort is put on figuring out all the places that can possibly break external ABI due to an internal change.
Mind though that this is not only the case when it comes to new features but also day-to-day maintenance is suffering from this with several bugs that can’t even be fixed today.
GTK+ currently exposes a huge amount of internal implementation details which blocks cleaning up of internal code, something that is much needed. This is not only for code beautification, in fact, the reason is that it’s a necessity in order to maintain the toolkit.
Why do we propose to break ABI now and not after features X, Y and Z? Because we want to do the break at a point where users will not have to make any logical changes to their code (as long as they are not using deprecated widgets or functions).
For applications being fairly up to date it will be a matter of recompiling with the right set of flags and then let the compiler do its work and fix the places where it breaks. Our plan for this is the introduction of the GSEAL macro that will let you compile your application with:
CFLAGS="-DGSEAL_ENABLE -DDISABLE_DEPRECATED" ./configure
This will make the compiler catch all uses of direct access to the object fields so that you can go through them one by one and replace them with a call to an accessor function instead. This can even be automated in many cases and Johan tried it with some nifty regexps yesterday which seemed to work fine.
The changes will in a majority of the cases be:
Bar *bar = foo_get_bar (foo);
instead of:
Bar *bar = foo->bar;
After we have done this we will have an API consisting only of functions which means that any compatibility glue code we need to write can be done without the risk of variables being accessed directly and circumvent the compatibility layer. This is in the fundamentals of OOP practices and I believe that it’s a price well worth paying.
More over, since 3.0 is not going to be a feature release there is no need for applications to jump on it right away, they can use that period to do any transitions needed and be in position to reap the benefits with the ABI compatible 3.2 feature release.
Will we have to break again in the future? Of course! That’s what 4.0 is for and we propose that we already at the release of 3.0 decides when 4.0 is planned to be released so people know when deprecated code will be removed.
Michael wrote in Kris blog that we shouldn’t discard incrementalism, and this is the exact same feeling we have. We need to do things incrementally, but that doesn’t mean things can or have to always stay 100% compatible, only that the changes are small to ease the effort of following them.
In summary our proposed solution is an enabler for incrementalism.