Servicing Dependencies, Part 1

Suppose you have a huge product (such as Windows) for which fix bugs daily. These fixes need to ship through some mechanism (download central, Windows Update, etc.). Of course you can't re-distribute the whole OS every time you fix a one-line bug. Therefore you define components, which are sets of closely-related binaries as per the architecture.

But what happens when, in order to fix a bug, you need to introduce new behavior or data in component A, and use that in component B? Let's say you add a new API MyFunc(). From B, you just call MyFunc(). But this is usually a bad idea. Why? In order to make this work, you now have to ship both components A and B so that this new behavior can be called and the bug fixed. That's inevitable. But: from now on(1), you will always have to ship those two components together!!

Consider what would happen if you fix a future bug in component B, unrelated to this one. You happily code it up, and to your horror verify nothing works. Uh-oh, we're trying to call MyFunc() which is supposed to live in A...but we didn't ship A for this bug...only B. That's a problem.

Breaking the dependency

One useful idiom, is attempting to substitute the direct API call with a dynamic invocation:

 typedef void (*ffunc_t) ();
HMODULE hB = LoadLibrary("LibraryB.dll");
if (hb)
{
   ffunc_t fMyFunc = (ffunc_t) GetProcAddress(hB, "MyFunc");
   if (fMyFunc)
   {
      fMyFunc();
   }
   else
   {
      previous_behavior();
   }
}

 

(1) Service Packs tend to fix these, since users will get both the new A and B, and the LoadLibrary/GetProcAddress idiom can be removed in favor of the new behavior.