Doing things that scale

In the software world, and with internet, we can do a lot of things that scale.

Answering a user question on IRC doesn’t scale, only one person and a few lurkers will benefit from it. Answering a user question on a mailing list scales a little better, since the answer is archived and can be searched for. What really scales is instead to improve the reference manual. Yes, you know, documentation. That way, normally the question will not surface again. You have written the documentation once and N readers benefit from it, regardless of N. It scales!

Another example. Writing an application versus writing a library. Writing an application or end-user software already scales in the sense that the programmer writes the code once, but it can be copied and installed N times for almost the same cost as one time. Writing a library scales more, since it can benefit N programs, and thus N^2 users if we use the asymptotic notation. It’s no longer linear, it’s quadratic! The lower-level the library, the more it scales.

Providing your work under a free/libre license scales more, since it can be re-distributed freely on the internet. There are some start-ups in the world that reinvent the wheel by writing proprietary software and provide technical support in their region only. By writing a free software instead, other start-ups can pop up in other regions of the world, and will start contributing to your codebase (if it’s a copyleft license, that is). For the human being advancement, free software is better since it more easily permits to not reinvent the wheel. Provided that it’s a high-quality software.

This can go on and on. You get the picture. But doing something that scales is generally more difficult. It takes more time in the short-term, but in the long-term everybody wins.

API vs ABI

I repeatedly see other people doing the mistake, so a little reminder doesn’t hurt.

  • API: Application Programming Interface
  • ABI: Application Binary Interface

The difference can be easily explained by knowing what to do for some code when the API or ABI breaks in a library that the code depends on:

  • If only the ABI breaks, then you just need to re-compile the code.
  • If the API breaks, you need to adapt the code.
  • When the code doesn’t compile anymore, you need to adapt it, so it’s both an API and ABI break.
  • When the code still compiles fine but you need to adapt it, it’s only an API break.

Example of an ABI break only: when the size of a public struct changes.

Example of an ABI and API break: when a function is renamed.

Example of an API break only: CSS in GTK+ 3.20, or when a function doesn’t do the same as what was documented before (in an incompatible way).

That’s it.

Libtool convenience library to unit test private functions

Only the public API of a library is exported, so when a program is dynamically linked to the DSO (Dynamic Shared Object), it can only use the public functions.

So how do you unit test the private classes of your library?

There is a simple solution, having a Libtool convenience library that contains the whole code of the library, but without an -export linker flag, so that all functions can still be accessed. You then link that *.la file to your unit tests and also to the real library where you add the appropriate -export flag.

You can see that in action in GtkSourceView and gspell. For example in gspell:

When you run make in verbose mode with make V=1, you see that the libtool commands statically link the convenience static library (a file with the *.a extension) into the unit test programs and into the DSO.

That way the *.c files are compiled only once, and adding a unit test to the testsuite/Makefile.am is straightforward.