I am a huge fan of developing and employing shared libraries across the enterprise regardless of objective, be it third party WebPart interface components or exclusively containing common method implementation. I really enjoy the fact that code base refinement and adjustment can happen so effortlessly with minimal friction when a common baseline of libraries used (very important when using third party components since release cycles are not locally owned). I find myself doing this recurrently during SharePoint development because there are so many gaps within the current API it makes for a lucrative environment to develop cyclic components (i.e. building existence testing for proxy objects that don’t have it OOB) and common code base standards (i.e. when doing something remedial like root SPWeb reference executing corporate exception handling practices in a static method).
One principal issue, and one that I recently had to deal with, is intentional meager checking for globally referenced assemblies within the solution build and malformed solution builds. The SharePoint solution framework does not respect referenced assemblies, nor should it because it is developer accountability (much as it pains me to say).
What I mean by not respecting references is if you have two solutions that use an arbitrary shared library, each specifying the library as a deployment target within the solution manifest, during retraction for the first solution effectively the shared library will be removed, thereby breaking the secondary solution reference to that library resulting in a File Not Found exception. More granularly, each SharePoint solution will have within the solution manifest, in the Assemblies node, DeploymentTarget and location attributes that reference said shared assembly. This is a huge problem, but is working as intended (otherwise the solution framework wouldn’t be very effective would it?) and just requires diligence to correct.
Fundamentally, this is what the problem looks like:
So while the SharePoint solution framework allocates deployment ease and aggregate management; it places an exceptional quantity of power within the user that is responsible for package deployment (who may or may not be a developer). Therefore when using shared libraries that have multiple callers, you have two options. One I like, and the other one I find overcomplicated and a poor approach.
Package and deploy the shared library mutually exclusive from any specific component. Developers are allowed to assume that they can reference that assembly locally during build phases and it will exist in later cycles regardless of where code is moved / deployed.
Within any number of events and receivers, use Reflection, more specifically GetReferencedAssemblies() in order to build an array of all assemblies referenced and inspect whether the retraction should execute. While this seems like a fun option, it doesn’t offer the managerial aspects that the above does.