Android, Intents, Binding

After I recently stuck out my neck and all but accused Google of implementing a broken solution for code re-use, I really need to follow up on a discussion that started. I’m too cold and tired to do that today, though.

Today, I’d like to warm up to that discussion by spending some time on the meta-subject of late vs. early binding. In a way, that’s a topic for the unfinished series on programming interfaces, but that’s been unfinished for so long now that I might as well not bother with it any longer.

I have a character trait that sometimes annoys people, and that’s that I tend to see the similarities between two quite different things more easily than the differences. That is, I do see the differences quite well, but they don’t weigh as much to me as the similarities. I find that trait useful, as it easily leads me to try and apply lessons learned in one topic to the other — sometimes with great results, sometimes less so.

So to me, the ruckus I raised about how Intents are used in Android is not so much about Intents or Android, but about how to handle code re-use in general. Apologies to those for whom the following seems obvious.

Back in the early days, if you wrote a piece of software that had substantial similarities to another piece of software, you might have copied code from the first to the second. When you do that sort of thing, it quickly becomes apparent that code is shared more easily — that is, with fewer or no modifications — the more it tries to solve generic problem classes as opposed to very specific problems.

I’m not going to go into the merits and problems of that approach here, but if you’ve got suitably generic code, that is code that does not require modifications to be re-used, then you’ve got the beginnings of a software library. Or module. Or component. Call it whatever you want.

There are a ton of different ways for making such a library available to other programs, and they all depend very strongly on the programming language, compiler and operating system used. I think looking at how C/C++ handles this on a suitably modern operating system gives a good overview of the options, though:

  • You can distribute the source code. To use the library, the simplest way is for each program to treat the library’s source code as it’s own. It’ll get compiled into object code as part of the program, and the library’s object code will then form an integral part of the finished program.
  • You can distribute the object code. Typically each C/C++ source file gets translated into an object code file of the same name, and those object files get combined into an executable program. You could distribute those object files separately, or combine several of them into an archive file. The latter is usually called a statically linked library.
  • You can distribute the object code in a different form of archive, called a dynamically linked library.
  • There’s also the option of providing your library as a plugin. Depending on the platform you’re targetting, the library file may or may not be identical to a dynamically linked library, and only it’s use may differ.
  • Many people would not consider this to be a similar form of code re-use, but you can always distribute your library as a service, using e.g. CORBA or XML-RPC to expose their functionality.

Seasoned programmers will notice that I’ve tried to avoid a lot of details in the above examples. For example, I’ve avoided mentioning that compiling C code for inclusion in a dynamically linked library tends to require the code to be compiled slightly differently from the first two examples. I don’t think such details matter in this discussion.

What matters, as far as I am concerned, is that the above examples can be grouped into two categories.

In the first category, the library’s code is copied into each program that uses it. Aside from the obvious downside that copying code means using disk and memory space twice or more for what’s essentially the same thing, it also means that once a program is created, it cannot benfit from improvements to the library any longer — that is, until it is recompiled. Statically linking libraries, or including a library’s source code in your program fall into this category.

In the second category, the library’s code is referred to in each program that uses it, but not copied. Once the program is loaded, it falls to the language runtime — which in the C/C++ case is often part of the operating system — to resolve these referrals to an actual library file. The runtime then loads the library, and creates all the appropriate links between it and the program that allow the program to run library functions.

All the other examples fall into this category, but there are differences between them.