Du Javascript propre… Round #2

Suite à mon premier post dans ma quête de rendre plus simple, plus lisible et donc plus maintenable mon code JavaScript, voici donc le deuxième round, dans lequel je traiterai des « classes ».

Cela nous fait donc revenir sur le point numéro 5 du round #1 pour l’améliorer. Et pour cela, je vais comparer le pure Javascript et l’utilisation d’un plugin « class » pour jQuery !

 

Jquery Class est un plugin aidant grandement la lisibilité du code, bien qu’environ 3,5x moins rapide que du Javascript pure, j’ai beaucoup aimé sa syntaxe et sa lisibilité. Il permet une utilisation plus complète des classes Javascript. Nous éviterons donc ce plugin dès que la rapidité d’exécution sera importante.

Note : Pour tester les performances de différents frameworks vous pouvez vous rendre sur le site jsperf !

Ce plugin à pour fonctionnalités principales :

  1. L’héritage
  2. L’introspection
  3. Les espaces de noms
  4. Les méthodes de configuration et d’initialisation
  5. Les appels aux « CallBack » facilités

Voici un exemple simple d’utilisation :

$.Class("Animal",
// static properties
{
  _instance: null,
  GetInstance: function(){
     if(!_instance){
        _instance = new Monster();
     }
     return _instance;
  }  
},
// prototype properties
{
  // constructor function
  init : function(){
    //all i have to init
  },
  setProperties: function(new_power, new_fast){
    this.power = new_power;
  },
  //variables
  power : 0,
  fast : 0
}); //end class

//create an entity
var animal = new Animal();
animal.setProperties(10, 22);
//or call by instance
var animal = Animal.GetInstance();

1 – L’héritage

Pour faire hériter une classe d’une autre, il suffit de l’initialiser avec la classe de base en donnant en paramètres le nom et les propriétés de la classe dérivée.

Animal("SeaAnimal",{},{
  swimRapidity : function(streamForce){
    this._super.fast * (streamForce/10); //_super appel la propriété de la classe de base
  }
});

2 – L’introspection :

Nous pouvons accéder au nom complet et/ou simplifié de la classe.

$.Class("Model",{
  findAll : function(success){
    //utilise son nom de classe pour trouver les items
    $.get('/'+this.shortName.toLowerCase()+'s', success, 'json');
  }
},{});

//création du model task
Model('Task');

//a utiliser pour faire un requete sur Task
Task.findAll(function(tasks){
   alert(tasks.length);
});

3 – Les espaces de noms :

Ce qui est une bonne idée car cela va éviter les conflits éventuels avec d’autres librairies qu’on utilise dans nos projets !

$.Class("MyCompany.MyProject.MyClass");

MyCompany.MyProject.MyClass.shortName; //return -> MyClass

MyCompany.MyProject.MyClass.fullName; //return -> MyCompany.MyProject.MyClass

4 – Les méthodes de configuration et d’initialisation :

Lorsqu’une classe ou une instance de classe est créé, les méthodes de démarrage sont appelés. La fonction « setup » est appelée avant « init » et peut être utilisé pour normaliser les arguments dont « init » à besoin par exemple. la fonction « init » est le constructeur de l’instance.

$.Class("Controller",{
  setup : function(){
     //exécuté avant init
  },
  init : function(){
     //exécuté après setup
  }
});

 

5 – Les appels aux “CallBack” facilités :

Le plugin « Class » dispose d’une fonction statique et prototype de rappel qui renvoie « this » ou le contexte de la classe ou de l’instance.

$.Class("Task",{
  init : function(name){
    this.name = name;
  },
  get : function(){
    $.get('task',
         {name:this.name},
         this.callback('show'),
         'text');
  },
  show : function(instructions){
    alert(this.name+instructions);
  }
})

//exécute la fonction init puis la callback obtenue depuis la fonction get
new Task("dishes").get();

 

Vous trouverez la documentation sur javascriptmvc.com et vous pouvez télécharger la jquery.class.js ou la version minifiée jquery.class.min.js !

Note : Il faut jQuery en version 1.9 au minimum pour pouvoir utiliser ce plugin.

 

En pure JavaScript, le modèle restera simple mais efficace tout comme démontré rapidement dans le round #1 :

//variable globale (singleton)
var USER_MANAGER = null;
if (!USER_MANAGER) {
    //instanciation de la variable globale
    USER_MANAGER = new user_manager();
}

//classe
var user_manager = function () {
    //variable de user_manager
    this.userName = null;
    //fonction de user_manager
    this.checkUser = function () {
       /*...*/
    }
}

Au niveau de l’architecture, on pourra créer, dans un dossier « pages », un fichier JS qui porte le nom de chaque page qui aura besoin de JavaScript et qui initialisera tout ce dont cette page aura besoin.

Et à la racine du dossier « js », on pourra ajouter les classes spécifiques.

Voici donc mon round #2 terminé !