One Hundred and Fifty-Three

  • Random
  • Archive
  • RSS
  • Ask me anything

On the GNOME Shell JavaScript Style Guide

GNOME Shell’s Style Guide encourages extension developers to write classes along the lines of:

function ClassName(arg1,arg2) {
    this._init(arg1,arg2);
}
ClassName.prototype = {
    _init: function(arg1,arg2) {
        // initialisation goes here
        this._privateMember = arg1;
        this.publicMember = arg2;
    },
    _privateFunction: function() {
    },
    publicFunction: function() {
    }
}

I would contend that this is terrible for a number of reasons.

Le raison numero un: Putting an underscore in front of a method’s name doesn’t make it private. It just puts an underscore in front of the name. Although: it’s well known that JavaScript developers can’t see something when the name is prefixed with underscore. To break this class, it’s a simple matter of writing Classname.prototype._privateFunction = function(){}. Boom.

Le raison numero deux: Separating “function ClassName” and “ClassName._init” is just plain stupid. It add another layer of abstraction for whoever’s reading the code and trying to find out what actually happens when a new ClassName is created.

Le raison numero trois: This kind of “class” has to be instantiated with JavaScript’s “new” keyword. Except… it’s not a class. Nine times, out of ten, it’s not used like a class (at least in the shell, and extensions thereto). It’s an object with an initialiser and some methods and should never be treated otherwise.

So: How else should it be done? How can private methods actually be hidden? How can initialisation logic be integrated? How can “new” be avoided? Like this:

function ClassName(arg1,arg2) {
    var privateMember = arg1, self = {};
    self.publicMember = arg2;
    function privateFunction() {
    },
    self.publicFunction = function() {
    };
    return self;
}

With this formulation, private members can’t be touched; the don’t exist outside of the closure. The implementor can control exactly which methods get exported, by adding members to self. And it can be instantiated using var instance = ClassName(“a”,”b”);.

Simples.

  • 11 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Recent comments

Blog comments powered by Disqus
← Previous • Next →

About

Avatar 153 Ways That Things Can Go Wrong and Then Awesomely Right, or Inventive Solutions to Problems That Don't Exist

Me, Elsewhere

  • Facebook Profile
  • quartertotomorrow on Flickr
  • mattyb1000 on Last.fm
  • Google
  • quarterto on github

Following

Cool Shit

See more →
  • RSS
  • Random
  • Archive
  • Ask me anything
  • Mobile

Effector Theme by Carlo Franco.

Powered by Tumblr