We know naming is hard, and it probably should be, but never has something so seemingly minor made me toil so frequently. It’s such an interesting topic that I just had to write some stuff down.
When I say naming, I mean something as simple as naming a variable, or more often: an API endpoint — the thing that the end-user-programmer-guy is going to use. It’s hard.
I think code should be readable, but I don’t think that means it should be readable to everyone, even non-programmers. So, if I show a non-programmer Java and then Perl and they say the former is much easier to understand, I don’t think that counts as a mark against Perl.
I also don’t think we should needlessly simplify things to cater to the amateur. In fact, I love the idea of writing code that I expect to only be read by programmers seasoned in that very language. When I write JS, I like to presume that the maintainer knows about hoisting, closures, prototypal inheritance, and truthy/falsyness. Pandering about trying to make your code avoid these inherent qualities is a waste of time.
Even with that opinion I still hugely value expression through language. I love method chains that flow like spoken sentences:
render('this').thenRun(function(){}); |
But at the same time I don’t like putting too much effort into making an API bend to this style.
It’s really tricky to pick a principle and stick to it. Some of us prefer hungarian notation. I say I hate it but I still use it quite often.
I think programming should have a barrier to understanding, and I think APIs should too. This sounds weird, even to me, but I think it makes sense nonetheless. Fundamentally, every API disguises complexity and, ideally, a very precise piece of functionality. Making the API dead-simple makes no sense if what it is disguising is actually quite complex and involved. An API or language should be crafted in such a way that by using it you’re not only learning how to use it but you’re learning how it works.
jQuery is a good example, because it neatly expresses the DOM. It doesn’t hide the DOM, believe it or not. You still need to append and prepend, bind event listeners and apply CSS classes. The great thing about jQuery is that it reduces the DOM down to it’s very essence, so that when you have gained an understanding of jQuery you have also gained an understanding of the core idea behind the DOM.
So, no, I guess APIs and languages shouldn’t be as simple as possible just for the sake of it. They should represent the functionality they seek to disguise.
I’m not happy with this conclusion though. I am sitting here thinking about that end-user-programmer-guy. I guess this holy API should seek to provide exactly what this guy wants. The trick is knowing what he wants. It would be lovely if we could create computers that just had one input device — a big green button, which, when pressed, made the computer do exactly the thing you want. We don’t have this (yet!), and our APIs can’t have this either. But maybe there’s a healthy compromise where we model the API based on how it’s going to be used, not how we want it to be used. We are meaningless in that our petty preferences make no difference. Our APIs must be predictive; modelled entirely on the potential use-cases presented by end-user-programmer-guy, not modelled on our preferences alone.
I still haven’t resolved this in my mind. It’s still hard to decide what to call some method that will only be used once in a blue moon. It’s not as easy as describing the method entirely in its name:
var namespaceContainingMethods = { methodThatTakesArgumentsAndJoinsWithSpecifiedString: function() { //... } } |
I’ve had to use stuff like this before and it sucks. It sucks so much. It was made for idiots. That’s another thing: APIs should not offend. Don’t patronise me with your “ur so stupid” naming. Make me feel good about using your API.
It’s not easy. It’s just not.
Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!
I once heard a teacher say something like, “Each domain of knowledge comes with a new vocabulary. It is expected that not everything can be expressed in elementary school vocabulary.” You shouldn’t make unnecessary vocabulary that is too complex, but can be represented with simpler ideas, but you should also not be afraid to create more descriptive vocabulary (new compound words for example) where it is useful.
API creation is very much about the language and vocabulary of a specific domain. You have CRUD in many APIs, but once you get into the nuance, it gets tricky because APIs shouldn’t change (See also the SOLID principles), but they should be extendable. This makes them more like a sky scraper than a spider web, hopefully.
This is good stuff and needs more attention within the programming community as a whole. Thanks for sharing your thoughts!
jQuery isn’t exactly the best example about a good API, so many method overloads, conflicting names (.is, .not, .bind, .add, etc), single namespace, etc… But it is still “better” than “plain DOM”.
I wrote a post a couple months ago about how to name things: http://blog.millermedeiros.com/2011/07/naming-methods-properties-and-objects/
Cheers.
I’m using a very simple and easy to maintain naming. It’s based in namespaces to identify where in the application is located any method. In brief this can be something like this:
Static methods grouped by functionality or entity (for example a given social network):
AppFooTools = {};
AppTools.getFormattedDate = function () {
...
};
Instantiable classes:
AppFooItem = function () {
this.att1 = '';
this.att2 = '';
};
AppFooItem.prototype.init = function (p1, p2) {
this.att1 = p1;
this.att2 = p2;
};
(...)
item = new AppFooItem();
item.init("hello", "world");
The APIs created by open source community and Google both seems to be very well documented and easy to understand and implement as compare to others, even facebook graphAPI is well documented and lots of help available over the net.
its not easy i agree with you 🙂
There is an art to writing docs. Writing API docs is a bit different, in that you offer a service, often at the expense of describing the innards of your program.
Often when I read API docs, I often find myself pondering where such things exist when you describe them.
For example:
Developer A writes: “Just include this module at the top of the document”
… My reaction is usually “What module?”
Simple as that. My advice when writing docs is; link everything together. Every word, or “term” you use, link it somewhere else, where you, the potential developer can read up more on that method / property.
Reading docs, at least for me, has always, and probably (sadly) will be a -Link-Hopping-Experience-
//”extend” can be confused with classical inheritance, you are not extending a class, you are simply copying properties from another object.
04 //”a”, “b”, “p” doesn’t describe what the parameters/variables are
05 function extend(a, b){
06 for(var p in b){
07 a[p] = b[p];
08 }
09 }
10
11 /* === descriptive names === */
12
13 //”mixIn” describes that properties are being copied from one object to another, other possible names: “aggregate”, “combine”, “merge”.
14 //”target” shows that base object is being augmented and that method doesn’t return/create a new object, using a name like “base” would be recommended if method returned a new object.
15 //”obj” is not really a good name but since “mixIn” and “target” already gives enough context and the function is so simple it is enough to understand that it is an object with properties that will overwrite `target` props. Other possible names: “extensions”, “extras”, “props”.
16 //”key” common abbreviation used for properties names in `for in` loops. “name” and “prop” are also common.
17 function mixIn(target, obj){
18 for(var key in obj){
19 target[key] = obj[key];
20 }
21 }