Designing APIs is no walk in the park. In many instances, when your API becomes popular, it can be difficult or even impossible to change. Whether it’s a programming language or framework, a good API makes a world of difference for developers who use it.
However, when not accompanied with good design principles, simplicity may lead to anti-patterns. For instance, the main strength of jQuery is perhaps one of its major weaknesses. The “kitchen sink” jQuery’s overloaded main method violates the single-responsibility principle of API design. It also violates another characteristic of good APIs; Self-documentation, though I’ll write a separate post on that at a later time. Consider the following use of jQuery’s main method below:
$(selector); //A string containing a selector expression. $(element); //A DOM element to wrap in a jQuery object. $(html); //A string defining a single, standalone, HTML element. $(elementArray); //A DOM elements array to wrap in a jQuery object. $(object); //A plain object to wrap in a jQuery object. $(jQuery object); //An existing jQuery object to clone. $(callback); //The function to execute when the DOM is ready.
$(argument); call to determine which execution path to take. Here is what’s happening in (simplified) pseudo-code:
- If argument is a “string”, then
- check if argument is a selector and execute path
- check if argument is html (regex) and execute path
- If argument is an HTML Node, then execute path to wrap in jQuery object.
- If argument is a function, then the “callback” path is taken for DOMReady.
Martin Fowler criticizes jQuery’s seemingly overloaded API for getters/setters for similar reasons.
The act of retrieving data is fundamentally different to that of setting a value, so the names should be more clearly different.
While it appears simple to use the same method name for two different behaviors, there are some negative implications in terms of using the API and maintaining it.