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");
ffunc_t fMyFunc = (ffunc_t) GetProcAddress(hB, "MyFunc");
(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.