2010.08.19

Stop writing plugins, start writing components

Why the fuck is that a jQuery Plugin?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.


Comments

Nice post Miller and I totally agree. It would be nice to see a simple example just to get a clearer idea of what you are talking about.

On a side note, are other traditionally Flash developers at Firstborn (Mathieu, Zeh, Eric and Francis) learning HTML/CSS and Javascript, or does everyone have their own discipline they focus on?

Good approach Miller. I think that the big problem in the most cases is that the programmers that write plugins, don't have the concern of write of a OO way. Modularity generally are concepts that coming together with the OO.

This is a guessing and maybe i can be wrong, but i guess that "pluginers" are structured programmers.

Congratulations, the topic is great!

I agree that recognizing the difference between a plugin and component can be very useful. However, I disagree with your specific examples. I can definitely see an argument for not considering UI controls plugins since they're high level and stateful. But there is zero chance for a name collision with the core library and if there were no file size concerns these plugins would likely ship "by default."

The main reason I would argue that these controls should be plugins is because that is the basis for the jQuery model. The average jQuery user would probably find it awkward to use these controls outside of the plugin syntax. For better or worse, part of jQuery's design is to never force the user to think in terms of constructors and prototypes or classes.

However, in terms of technical design, modularity, extensibility, etc., I agree that the component model works much better. This is why under the hood, all of jQuery UI is implemented as components and then wrapped as a plugin. To see this in action, you can do:

var bar = new $.ui.slider( { value: 20 }, '#lorem' ); ... bar.disable(); ... bar.destroy();

At least in the case of jQuery, I think it makes sense to build such plugins as components for all the reasons you've listed and then decide if there is any benefit to exposing those components through the standard plugin syntax.

I really disagree almost completely with this article. I can agree that the one-dimensional namespace of a library like jQuery can potentially be a problem, but in practice I doubt it's a problem that actually causes anybody any real headaches.

Your example of what to do with widget plugins is deeply flawed. You ask, "How would you do it in the plugin way?" Well, I'll tell you: you'd do it by providing a way to pass the plugin some parameters to tell it what you want it to do: disable its behaviors, remove its behaviors, or whatever. That's what plugins do today. The argument holds no water whatsoever.

Plugins a la jQuery are modular. You've written nothing to suggest otherwise, yet you claim that there's some fundamental difference. There is not.

Great post.

Mike, I think you're getting a little carried away. At minimum we should think about the difference between a component/ui widget and a plugin if only to identify highly reusable code. I think this article is about structuring how we think about code. Too much great code is trapped in components b

Agreed ! Never thought about this so detailed. Thanks.

+1 on an approach akin to the jQuery UI widget factory in a jQuery situation where functionality needs to be, somehow, attached to a DOM element; creating components, exposing them as a method that can be called on a DOM element if that's appropriate. You get your statefulness, and expose it in a familiar way. However, there are plenty of situations where a piece of functionality has nothing to do with the DOM at all, or the connection with the DOM is incidental, not imperative. In those cases, I agree that it doesn't at all make sense to be calling a method on a selection; rather, the component should receive the incidental DOM elements as arguments, or gather them itself after instantiation.

Thanks for writing a post that I hope will get people thinking more about how to organize their code :)

First.. Plugins, most plugins are actually decorators and whilst wrongfully catgorised, it's not bad practise to enhance jQuery with decorator methods. You are indeed pluging in more options to the jQuery namespace.

As for components... jQuery offers you a API to delegate and enhance already existing components, the components being HTML Elements. HTML offers you a very flexible way to design and style your components with CSS.

Introducing more "components" with JS should actually be considered extremely bad practise as you are polluting memory with needless stateful objects.

Take for example the Button widget present in nearly every componental framework. I could create 20 buttons each with a state that interact with an HTML element that also has a state. Or I could simply add the behaviour directly to the HTML elements and let them store the state without needing 20 more objects. Better yet, I could delegate the behaviour to a top element and create a decoupled abstraction to handle my clicks reducing the ammount of listeners I need to create by 19... Using a Button widget/component is extremely stupid in that respect.

Thats something people need to start realizing, you already have your components, it's called HTML and it's more flexible than any component implementation out there can offer.

Forward to jQuery, if you look at it from a componental point of view, say for example if you where used to ExtJS, then yes, you will have some severe annoyances. But are they justified really?

jQuery offers an API to delegate and compose rather then using instantiation and inheritance. This will ring the bell of anyone who read Design Patterns from the gang of four.

You can and are encouraged to enhance jQuery more by adding decorators that interact directly with your HTML components adding more presentation and behaviour through augmentation.

Everyone should avoid introducing more needless stateful objects and keep it to the bare minimum. You can do this very easily with jQuery and most 'plugins' are written that way by default without much thought behind it. It's just the way.

I agree with you if we where dealing with a single language environment, but we're dealing with at least 3 languages each with their own responsibilities. HTML, CSS and JS. Confining yourself to only one aspect is a grave mistake and will encourage bad practises and poorly written applications simply due to the missing the fact that your components reside in HTML/DOM, NOT JavaScript.

Write JS well, and you will only have singleton objects controlling HTML components through tiny state objects containing only the data vital for your application(s) leaving the stateful data of your components in the DOM. Write JS poorly and you basically copy/re-implement the DOM... DRY should mean something here ;)

@Super Duper: I think that the most important is to understand the problem and not a specific implementation...

Most of the developers at Firstborn knows how to program in more than 1 language and most of the time everyone works on what they are best at... this blog doesn't reflect Firstborn opinion BTW.

@Scott González: good points and I agree that jQuery users are used to plugins, I just don't think it's the best approach in some cases. Underscore.js is a good example of something that isn't an UI widget and that shouldn't be coded as a jQuery plugin as well (the guys did it on the "right way").

@Mike McNally: I think you got it wrong, I wasn't talking about configuring a plugin on the instantiation, I was talking about changing a plugin state afterwards (see examples again)... It's not because name collisions doesn't happen often that we shouldn't care about it.

@Ben Gerrissen: Don't be mad with me but I think you misunderstood many concepts... the most important concept of the gang of four book is exactly to "program to the interface and not to the implementation", they really emphasize the component-driven approach and also that each Object should have a specific use - an object shouldn't be a swiss-army knife but a surgeon-knife - the Decorator pattern doesn't fit in this case since you're not affecting a single instance of the "Class" but you are altering the "Class" itself...

The example of the Button widget doesn't apply since you could code a component in a way that you have a centralized controller and a single listener.. - using HTML to store logic most of the times isn't the best approach - it's like using text files instead of a database to store content - that's why we have JS (HTML is for content, CSS for styling, JS for logic).

Depending on the way you code a plugin you will end-up with many variables, functions and objects that will never be garbage collected... so the case here is not about a specific implementation (as I said before), the important is to understand the problems so you can think about solutions...

I've never said that we should re-implement the DOM, just that extending an Object that doesn't belong to you is a bad practice, I should talk more about that in the future... but since we are talking about DOM and extending an Object that doesn't belong to you this might be useful: What's wrong with extending the DOM.

Cheers.

Hehe, not mad at you ;) I know where you're comming from, did some ExtJS recently myself and am fully aware of OO programming paradigms. JS however.. is a mind opener once you really dive deep down inside and you see other implementation possibilities for the Design Patterns.

Consider for example an jQuery.accordion() "plugin", it's in fact a decorator, not for the jQuery constructor, but for your HTML components. You in fact use a new method to decorate HTML Element instances so it IS a decorator very much like the jQuery standard .css() method is.

Sure, some "plugins" look like they really should be components, buts that just because they are written poorly. jQuery plugins should really be decorators that only add and enhance existing DOM elements.

Extending jQuery has nothing to do with extending the DOM, so not sure why you linked me that article. Though I do understand why you would feel that extending jQuery (an object you dont own) would feel icky, but I would argue, don't use jQuery at all then, since it IS a toolkit that is powerful because of it's easy mechanics to 'plug in' more enhancers/decorators.

And there we come to the jest of it, there must be a reason why you where using (or forced to use) jQuery over say Dojo/ExtJS/YUI/etc, all of which are more componental in nature, especially ExtJS which is imo. component madness.

Anyways, your beliefs are right and just, though peer over the fence of what you know and where tought. Is it bad practises your fighting against or a new programming paradigm you are ignoring completely ;)

jQuery is just a JS toolkit, but I can''t think of a framework, toolkit or library thats more popular, in ANY language... Stop and ponder that for a while, perhaps you can explain THAT better then me eventually, because not too long ago I had the same opinions you had. ;o)

[...] Stop writing plugins, start writing components Tags: amd, javascript, opensource, requirejs, resources Comments (0) [...]

[...] for me is a huge mistake. I said it before and I will say it again STOP WRITING PLUGINS!. Even if all the tasks are indeed related to a common goal (helping the dev/deploy/test automation) [...]

[...] Stop writing plugins, start writing components Tags: amd, best practices, javascript, requirejs Comments (3) [...]

Once you stop working on a project alone, it pays off to have comments, documentation and modularity. Only, when you're doing simple things, you can get away with sloppy code. The notion of code-modularity and reuse itself, however, is older than OOP: here's some comments from 1989 (rather late, IMO) on code-reuse in OOP. You can also search (e.g. on scholar.google.com) for older papers. One of the few things that we have learned (again and again) over the last 40 years of programming is that the hard part isn't getting code fragments to work. The hard part is getting them to work together. The name of the game, particularly when it comes to code reuse, is integration at scale.

[...] Chrome Canary suporta <input type=date /> e <input type=time /> [9:53] Components — Post do Miller Medeiros — Como foi a Conferência [...]

[...] not a huge fan of plugins, in fact I think most people should not be writing plugins at all. If the this keyword is already confusing inside a simple code snippet, now think about a jQuery [...]

Thanks man ;)

Preface: I'm not a JS developer, so this is written from the perspective of other languages.

I think the only point I disagree with here is the one about frameworks. There are very few good frameworks out there, and what's being talked about in this article is closely related to why most are so bad. Most frameworks push you into doing things their way. The moment you want to move beyond what they thought of when they designed the framework, the framework starts getting in your way and becoming a hindrance rather than an asset. This is why people write plugins. A framework simply can't foresee every need or functionality, and trying to go outside the bounds the framework imposes on you makes your life incredibly difficult. So people write plugins as a way of shoehorning the unforeseen functionality they need into the framework. A truly good "framework" isn't really a framework at all; it's a large component that you can tie together with other components. Sure, you might have to do a little bit more work up front sewing the components together, but it really pays off in the end when you have to go outside the bounds of what the tools you have were intended to do.

Leave a Comment

Please post only comments that will add value to the content of this page. Please read the about page to understand the objective of this blog and the way I think about it. Thanks.

Comments are parsed as Markdown and you can use basic HTML tags (a, blockquote, cite, code, del, em, strong) but some code may be striped if not escaped (specially PHP and HTML tags that aren't on the list). Line and paragraph breaks automatic. Code blocks should be indented with 4 spaces.