We've been doing a fair bit of rearchitecture to support plugins, using OSGi as our plugin architecture. It's been a great experience, and has brought up a few issues that many of us would have never considered.
One of them is code reuse. We've all been taught how important code reuse is, and that copying and pasting code is one of the most terrible sins one could commit. I've come to believe that we shouldn't always think that way.
The trade off with code reuse is maintainability, and it cuts both ways. Generally, the belief is that by reusing code, we make the code more maintainable... make a fix to a core library, and all of the client code gets the fix. But I think that's a bit of an idealistic situation. In reality, changing a core function means that you have to test that any client that is using it still works. And that can be so much work that a developer isn't likely to go through the effort. Instead, they just hope that no client breaks - an often incorrect assumption. Certainly if the core function is carefully specified and clearly documented, these problems can be alleviated, but how often is this the case? Even unit tests can't account for all of these problems.
Instead, what if you just copied and pasted the code into a local class in your plugin? Any changes made would now be isolated. When you make the change in one place, you no longer have to worry that it will break a plugin somewhere else. You've also reduced the maintenance costs of your code by not requiring you to maintain the API. If, at some point, you decide that you no longer need that functionality, you can safely remove it, knowing that no other modules depend on it.
The downside is that if you really do need to make a fix that all of the users of that code need, it's more work. But I find that happens less than we think, and it's much more common that a change to a core function breaks other clients. Most of the time, I find that I'm making a fix for a specific problem with a specific client, and the lack of isolation of this change impacts the quality of the software.
Now certainly I am not advocating giving up on shared code. But it's important to realize that any shared code increases the maintenance costs of that code, so you have to be sure that the cost savings of sharing the code outweighs the costs of making sure that any client that uses the code is re-tested when making a core change. We've all been on projects where it seems like every bug fix causes 2 new bugs... perhaps developers aren't copying and pasting enough?