Stop writing plugins, start writing components
I’ve been doing a lot of JavaScript development lately and one thing that always bothered me is that most of the people misunderstand the plugin concept and uses it on the wrong way. In my opinion, the main reason is because JavaScript frameworks/libraries like jQuery, Mootools, Prototype.js and blog/CMS systems like WordPress, Joomla, Drupal encourages plugin development… – Let’s start with the basics…
What is a plug-in?
In computing, a plug-in is a set of software components that adds specific capabilities to a larger software application. If supported, plug-ins enable customizing the functionality of an application. For example, plug-ins are commonly used in web browsers to play video, scan for viruses, and display new file types. (source: Wikipedia)
What is a component?
A component in the Unified Modeling Language “represents a modular part of a system, that encapsulates its content and whose manifestation is replaceable within its environment. A component defines its behavior in terms of provided and required interfaces” (source: Wikipedia)
What is the difference?
The difference isn’t just on the semantic but also on the concept and way that the code is structured and used… The first is used to add new functionalities to existing code and the other is used to create reusable modules. In my opinion, that is a HUGE difference…
The Wikipedia entry for plug-in has a more detailed explanation about the difference between a plugin and a extension/add-on that is also valuable..
What is wrong?
For me the major problem is the misuse of the concept but another big issue is that you are modifying an Object which doesn’t belong to you and that you don’t have control… it can lead to conflicts with other plugins and even with the actual framework in the future in case they decide to add a new method/property that uses the same name and does something different, it is less future-proof and less compatible with 3rd party code. – This problem is also known as namespace cluttering, but that is for another post.. – Another big issue is that it defeats the single responsibility principle making your code harder to maintain and to understand.
The misunderstanding of the plugin concept also helps to increase the number of available plugins making it really hard to sort the ones that are actually useful and well-coded.
What should I do?
The first thing is to identify which approach is better for the specific case; the best way to define that is understanding what is the original purpose of the code/framework and what you want to achieve, it sounds stupid but sometimes it’s hard to decide what is the best approach for the task - since usually there are multiple ways of achieving a similar result and you could also be doing something that is in the “gray area” between what should be a plugin and what should be a component – my rule of thumb is that if you are not sure, build as a component.
To demonstrate my point of view I’m going to use some jQuery examples because it’s a really popular library, has thousands of plugins available and also because it is the main reason why I decided to write this article… but you don’t need to have any jQuery knowledge to understand what is going on and it also applies to other frameworks/libraries… – For those who don’t know, the main purpose of jQuery is to help users to traverse and manipulate the DOM and to do XHR on a simpler way, it also contain a small set of helper/utility methods but that isn’t the major feature of the library.
What should be a plugin?
Things that are directly related with the original purpose of the software/framework and that could eventually in the future even be added to the framework/library by default.
On jQuery it would be: methods to traverse/modify the DOM tree, new selectors, new properties for the Ajax requests, helper methods that makes sense to use on this context… (e.g. delegate plugin that now is a native feature of jQuery, color animation, etc).
What shouldn’t be a plugin?
Everything that isn’t directly related with the original purpose of the tool.
Using jQuery as an example: everything related with user interface (scroll bar, tooltip, date picker, tabs, accordion, etc..), everything that extends the JavaScript native methods (arrays, functions, helper methods), your application namespace and methods, etc… shouldn’t be a plugin, it should be a component/widget/module. (e.g. jQuery UI shouldn’t be a plugin)
Example
Here is some pseudo-code to illustrate the difference between a plugin and a component/widget:
//Plug-in based $('.foo').accordion(); $('#lorem').slider(); //Component/Widget/Module based MyAccordion.create('.foo'); var bar = new MySlider('#lorem');
The main difference is that the plugin adds new properties and methods to the original object (in this case the $
object) and a component/widget is a separate object. The differences may seem small and the amount of code may be a little bit bigger but following this kind of structure helps a lot to keep things modular and structured on a organized way…
Just imagine that you have to block the slider interaction during a certain amount of time or that you may want to dispose the slider (remove all the event listeners, delete references, …), how would you do it on the plugin way? Create a new method polluting even more the namespace? Come up with some hack?… – If you have followed the component-based approach you could simply edit the MySlider
prototype, implement the new functionalities and call it on the instance that you want, on my opinion it’s way simpler and well organized, here is some pseudo code:
var bar = new MySlider('#lorem'); ... bar.block(500); ... bar.dispose();
Another reason for doing so is that I also find that passing parameters into functions is way more natural than using the method chain to define what is the element/parameter that should be used, I’m sure that jQuery users are used to it (including myself) but this is one of the things that I used to hate when I started using jQuery – “you write in the jQuery language and not in JavaScript” – it took me a while to get used to it… – but that is just my personal preference and not really a valid point..
Conclusion
Frameworks are a good way to save development time and to avoid problems, but we should be more selective about what should be coded as a plugin and what should be a component and/or widget built using the framework – “it isn’t just because you can, that you should do it” – it can help you keep your code organized, usually gives you more control and it can also help you to better understand what is exactly going on and how “expensive” a certain process may be – think modularly!
A good presentation about how to organize your code into modules and to think in a modular way: Programming to patterns – I’m not saying that you should switch to Mootools or Dojo, or that you should start writing code following the “classical class paradigm”, it’s just a good example on how to think in a granular way.
I hope I was clear enough…
PS: I was thinking in maybe coding something simple like a tooltip or tabbed navigation using a plugin structure and then code the same thing using a component structure to exemplify that the code isn’t that different, and that it doesn’t required any extra knowledge, but I figured out that the most important thing is to understand the concept and not a specific implementation…
Edit (2010/08/20): fixed small typos, improved some phrases.
Edit (2011/04/07): Added explanation about the single responsibility principle and also improved explanation about what shouldn’t be a plugin.