Skip to content

Why versioning your interfaces is always a good idea

Thursday, 9 December 2004  |  daniel molkentin

Today, a lot of people have voiced their opinion on wether or not it's a good idea to port the KDE plattform to Windows. In other news, I whitnessed another uncessary crash today, that was due to a stale library that had an old interface. On load, it crashed and teared the application down. Read on to learn how to avoid those problems.


"They should uninstall old libs!" some of you might say. Wrong approach. This doesn't cover the case where third party libs are shipped. the original program might not know about them and thus has no decent way to uninstall them

"But shouldn't happen, interfaces should stay binary compatible" you might say. No, because that particular one was private.



Now see people screaming "Gotcha!, private interfaces should have no 3rd party plugins!

Yes, that's true... In theory. In practice this breaks with our beloved KDEDIRs approach. Imagine a case where $KDEDIRS=/opt/kde3:/opt/kde-cvs. This is a wonderful scenario I use myself quite frequently, because I only need to compile the relevant part of KDE CVS and don't have to run bleeding edge with all KDE components.

Now if an application tells KTrader [kde:KTrader] to look for plugins it will search for service desktop files in both directories. Now say there is a desktop file pointing to a plugin that is BIC from an oder KDE release, there is little we can do. KTrader will find it, KLibraryLoader will load it and Booom - all is void. So how can we avoid those things?

Enter: Versioning constraints. I will demonstrate that using Kontact Parts as an example. In our definition of the new servicetype kontactplugin.dektop looks something like this.
[[Desktop Entry]]
Type=ServiceType
X-KDE-ServiceType=Kontact/Plugin
Name=Kontact Plugin
...
[[PropertyDef::X-KDE-KontactPluginVersion]]
Type=int
...
As you can see, we introduced a custom field X-KDE-KontactPluginVersion. This one can now appear in every service desktop file describing a Kontact/Plugin.
[[Desktop Entry]]
Encoding=UTF-8
Type=Service
Icon=kontact_summary
ServiceTypes=Kontact/Plugin,KPluginInfo

X-KDE-Library=libkontact_summaryplugin X-KDE-KontactPluginVersion=4 ...

Now when loading the plugins, we add an extra constraint in the KTrader Language that compares the current version with the version of the plugin:

...
  KTrader::OfferList offers = KTrader::self()->query(
      QString::fromLatin1( "Kontact/Plugin" ),
      QString( "[[X-KDE-KontactPluginVersion]] == %1" ).arg( KONTACT_PLUGIN_VERSION ) );
...

Tadaaa! Now we only load parts that should be safe the load. Of course you a free to add several versions here if you are sure your interface is still binary compatible.

PS: as you probably noticed, the parser for kdevelopers.org sucks. If someone tells me how to stop it from interpreting quare brackets as a link, I promise to fix things.

So, there are todays mantras. If you can't sleep tonight, try repeating them until you can sleep :)

  1. Always introduce versioning to your interfaces
  2. Always check versions
  3. Carefully evaluate which versions of your interfaces might still be compatible to the current version.