Distance Debugging Logo

Everywhere I look nowadays I see yet another plugin architecture. I have nothing against plugins. I think that the concept of componentizing software is powerful and a good goal for a system. However, in the desire to become flexible and end-user extensible, I think that many projects have gone too far in their desire to piece things together via an aggregation of plugins rather than deciding to draw the line and refuse to allow change beneath a certain threshold.

Ultimately, plugins have to do with changepoints, and nothing will kill a piece of software faster than too many changepoints. I don't know where the term changepoint originated, although I hear it often in OO Design circles. Essentially, it is a place in your system where the design expects multiple possibilities. This could be because there might be multiple ways to accomplish something and you want to offer options, because end users might have their own solutions and want to extend the system themselves (i.e. via plugins), or it might be because you simply don't know at the time how things should be done so you are offering your future self some flexibility.

It is generally assumed that each changepoint that you build in has a cost in terms of system complexity and hence maintainability, programmer effort, and very likely performance. Often, these problems are easily offset by well-placed changepoints. For example, the Strategy pattern is about creating a change point to allow for different algorithms to be swapped in without requiring a design, or even code change. The benefits of the right algorithm can significantly outweigh the slight performance hit and code complexity that result from using a Strategy pattern.

On the other hand, we can be lured in by one or two successful tradeoff gambles and start putting in changepoints for less convincing reasons. Sometimes we put a changepoint in because we are lazy and don't feel like thinking about what the "correct" answer is and just offer some flexibility instead. Other times, while we only have a single clear system function in mind, we put in a changepoint because we think that someone somewhere might want to do it differently, despite the absence of any evidence to suggest this degree of flexibility. This is the kind of thing the extreme programming people are always yelling at us about, and I happen to agree with them on this point. Generally, the cost of software change is not as high as we think it is, and the amortized cost of paying for a changepoint that are not using can be very high in the aggregate.

That's where my main criticizism of plugin architectures comes in. Many plugin systems that I have worked with have somewhat grandiose notions of what people should be interested in changing and pay the cost in being brittle and hard to configure, even to do their primary function. It's too easy to accidentally disable a plugin, or fail to have the right ones installed, or have one of the plugins crash and take the whole thing down. Beyond the difficulty of properly trapping and reporting errors coming from code that you might never see, there is the problem of how you figure out where the problem is and who's "fault" it is. Is it the architecture's fault for not plugging things together correctly? Is it the plugin's fault for being flaky or not playing nicely? Is it my fault for botching the configuration? All of the above?  I am willing to put up with a certain amount of this from a system in exchange for power and configurability, but I often feel like I am just using an over-engineered system that does only one thing well despite the fact that it was designed to do much more.