Partager du code JavaScript client/server

Update : Pour ceux ayant lu l’article avant le 15/05/2013, la solution n’était pas bonne. L’article est mis à jour avec une autre solution qui elle, fonctionne 😀
L’avantage d’utiliser le JavaScript (CoffeeScript dans mon cas) côté serveur  (avec nodejs) et côté client, est de pouvoir partager du code.

Seulement un petit problème se pose. En effet, côté client, afin de créer un système de module, la solution la plus connue est d’utiliser RequireJS. Celle-ci s’appuie sur l’AMD (Asynchronus Module Definition) alors que côté serveur, nodejs repose sur CommonJS qui a une structure différente.

La première solution est de créer deux fichiers ayant la même fonction métier mais avec une structure différente. Pas très avantageuse, on a de la redondance alors qu’on travaille avec le même langage…

La deuxième solution consiste à importer la librairie requirejs dans node puis de l’utiliser. Je ne m’étendrais pas plus sur celle-ci dans ce billet.

Une autre solution consiste à modifier un peu nos fichiers JavaScript(ou CoffeeScript) afin qu’il soit compatible CommonJS du côté serveur et AMD côté client. Alors comment procéder ? Voici l’exemple de deux fichiers ayant la même fonction métier. C’est une simple classe avec une dépendance.

serveur :


client :


Le premier problème que nous voyons est que la classe Dog n’est pas au même niveau(en terme de scope) dans les deux fichiers. Côté serveur elle se situe dans le scope du “fichier” tandis que côté client, elle se trouve dans le scope de la fonction define.

Donc dans un premier temps, nous allons changer la structure du fichier sous RequireJS afin de faire ressortir la classe Dog afin qu’elle soit dans le scope voulu.


Petite parenthèse, lorsque je dis que le scope sera au niveau du fichier, cela ne signifie pas que le scope est le fichier. En effet, si on regarde comment est compilé ce fichier en JavaScript, on voit que le tout est englobé dans une fonction dont le scope est this(passé en paramètre de la fonction call) :


Notre scope “au niveau du fichier” est ce qu’est this à la dernière ligne (window par exemple du côté client). Si vous ne comprenez pas bien la manière dont fonctionnent les scopes, revoyez les notions de this, de scopes et de closures, c’est indispensable de bien comprendre ces notions lorsqu’on fait du JavaScript 🙂

Passons maintenant à la deuxième étape qui est de fusionner nos deux fichiers en un seul. L’astuce consiste à tester quelque chose qui nous permettra de déterminer de quel côté nous sommes. Ici j’ai choisi de tester la variable window. En effet côté serveur, celle-ci n’existe pas. On aurait pu aussi tester la méthode define : si celle-ci n’existe pas, alors nous sommes côté serveur. Bref, voici au final ce que ça donne :


Notre fichier est maintenant compatible AMD et CommonJS 🙂 On voit qu’il y a trois parties : la première concerne la déclaration de Burd ainsi l’import des dépendances avec CommonJS, la seconde notre code métier et la troisième l’import/export d’AMD ainsi que l’export de CommonJS.

Je vous met également la version JavaScript(qui sera donc utilisée côté client) :

CoffeeScript

coffeescript-logo

Présentation

CoffeeScript est un langage qui, une fois compilé, donne du JavaScript. La règle d’or de CoffeeScript est d’ailleurs “it’s just JavaScript”. Créé par Jeremy Ashkenas, CoffeeScript a pour but d’écrire moins de code tout en étant plus lisible, plus compréhensible et plus facile à maintenir. Sa syntaxe s’inspire du Ruby.  Il est bien sûr possible d’utiliser des librairies JavaScript. Attention toutefois, il n’est pas possible d’écrire du JavaScript dans du CoffeeScript directement (contrairement à TypeScript). En effet afin d’écrire du JavaScript en CoffeeScript, il faut le délimiter par l’accent grave : ` .

Celui-ci est disponible ici  ou à installer avec le gestionnaire de packet node :

npm  install -g coffee-script

Pour écrire du coffeeScript, il suffit d’écrire un fichier en .coffee et de le compiler avec le compilateur coffeescript.

coffee -c fichier.coffee

Variables

Parce qu’un exemple est toujours plus parlant :


Que pouvons nous remarquer? CoffeeScript n’a pas besoin de déclarer une variable avec le mot clé “var”. De plus,nous n’avons pas besoin d’utiliser de point-virgule à la fin de la ligne.

Les commentaires en CoffeeScript sont définis par un “#”

Il est possible de placer une variable dans une chaine de caractère sans concaténation. Il suffit pour cela d’utiliser la syntaxe #{maVariable} :


 

Opérateurs

Voici un tableau comparatif des différents opérateurs existant en CoffeeScript.

CoffeeScriptJavaScript
==
is
===
!=
isnt
!==
not!
and&&
or||
true
yes
on
true
false
no
off
false

Comme on peut le voir dans ce tableau, certains opérateurs en JavaScript disparaissent tel que l’opérateur == ou !=. Pour expliquer ceci, il est important de revenir au JavaScript et d’expliquer  la différence entre == et ===. Avec l’opérateur ==, on vérifie uniquement la valeur de la variable tandis qu’avec l’opérateur ===, on vérifie également le type de la variable. Ainsi si on a deux variables : a = “2” et b=2. Le résultat a==b renverra true tandis que a===b renverra false. Les bonnes pratiques JavaScript veulent qu’on utilise l’opérateur ===. C’est pourquoi l’opérateur == n’existe pas en CoffeeScript.

D’autres on été rajouté tel que yes, on, off, no. Ces valeurs ont pour but de simplifier la lecture du code.

Conditions


Comme on peut le remarquer, en CoffeeScript on s’affranchit des parenthèses et des accolades. De plus, lorsque l’on veut tester qu’un nombre est situé dans un intervalle, inutile d’utiliser l’opérateur &&. Enfin, si il n’y a qu’une instruction, il est possible de l’écrire sur une seule ligne comment montrer ligne 13.

Une chose qui peut être troublante est l’absence d’accolades. Comment faire alors pour effectuer plusieurs opérations? En CoffeeScript, c’est l’indentation qui va déterminer ceci. Une indentation est représenté par une tabulation ou bien 2 espaces. C’est cette indentation qui va signifier un bloc d’instruction :


Il n’existe pas d’écriture ternaire en CoffeeScript, nous le remplaçons à la place par le mot clé then :


En CoffeeScript il est aussi plus facile de savoir si une variable est définis grâce au mot clé “?”:


Enfin voici la méthode pour créé un switch en CoffeeScript  :


 

Fonctions

Il existe 2 moyens de créer des fonctions en JavaScript mais qu’une en CoffeeScript :


Pour créer une fonction en CoffeeScript, nous utilisons “->”. Etant donné que nous avons qu’une seul instruction(la valeur de retour), il est possible de mettre tout sur la même ligne.

Voyons comment cela se passe lorsque la méthode reçoit un argument :


Comment nous le voyons ici, l’indentation est ce qui détermine le bloc concernant la fonction. La dernière instruction du bloc est sa valeur de retour(une fonction coffeeScript renvoie donc toujours quelque chose). Les argument de place entre parenthèses lors de la définition avant le ->. Cependant lors de l’appel de la fonction, si il y a des arguments, les parenthèses sont optionnelles. Il est également possible de rajouter des paramètres optionnelles comme le montre le deuxième argument.

Attention!

Regardons cet exemple :


On s’attend, à la fin du code, que a vaut toujours 3 et i vaut 10 car le sentiment qu’on a est qu’a la compilation, il y ait ce code JavaScript :


Et bien non, la compilation donnera ceci :


Je ne m’attarderais pas sur l’explication de ce fonctionnement dans ce billet, on est ici pour découvrir les bases de CoffeeScript. Cependant il me semblait important de souligner ce comportement. Je l’expliquerais dans un autre billet.

Nombre d’arguments variables

Il est possible d’avoir un nombre d’arguments grâce à l’emploi de “…” 


 

Tableaux

En ce qui concerne les tableaux, CoffeeScript suit toujours son leit motiv : écrire moins de code pour faire la même chose. Voici quelques exemples de création d’un tableau :


Chacune de ces façons d’écrire fournira un tableau contenant les chiffres 1, 2, 3, 4.  Reprenons chacune de ces lignes :

ligne 2 : C’est la même façon que la création de tableau en JavaScript
ligne 4 : les .. signifie de 1 jusqu’à 4 inclus
ligne 6 : les … signifie de 1 jusqu’à 5 exclus
ligne 8,9 et 10 : il est possible de créer un tableau à partir de variable. Si on inversait les variables a et b nous aurions un tableau égale à [4,3,2,1]

Afin de rendre plus lisible la création de tableau il est possible de le faire sur plusieurs ligne comme ceci :


De cette manière, c’est un peu plus lisible. Attention à l’indentation : si le premier élément n’est pas indenté correctement sur la ligne du dessous, le compilateur renverra une erreur.

CoffeeScript nous permet également de pouvoir de récupérer un tableau de valeurs à partir d’un autre tableau :


Simple non? 🙂

Passons à un comportement plus spécifique, regardons l’exemple ci-dessous :


Ici, nous nous attendons à ce que le compilateur nous renvoie une erreur. Et pourtant, la compilation se déroule bien et tableau2 contient [2,3,4,5]. En fait, le -1 va être traduit en tableau.length par le compilateur. C’est une sorte d’alias.


Il existe deux façons de parcourir un tableau en coffeeScript : avec une boucle foreach ou bien avec une boule for in :


 

Objets

Pour créer un objet en CoffeeScript, rien de plus simple :


Comme toujours en CoffeeScript, c’est l’indentation qui définit les “limites” de notre objet.

Il est possible de parcourir un objet grâce au mot clé “for of”  :

Les itérations

Arrêtons nous un peu sur les itérations. Tout comme en JavaScript, CoffeeScript utilise la boucle while :


Cependant, la boucle for n’existe plus et est remplacé par le parcours d’un élément appelé “compréhension”. Nous avons donc for in pour parcourir un tableau et for of pour parcourir un objet. Pour faire une boucle for classique, nous feront comme ceci en CoffeeScript :


Il est vrai que la “compréhension” d’un élément n’aurait pas grand intérêt si elle s’arrêtait là. Pour ceux venant de .net et utilisant linq, vous retrouverez quelques similitudes.En effet nous pouvons faire ceci par exemple :


Littéralement : lorsque le fruit contenu dans le tableau [“pomme”, “banane”, “poire”] n’est pas égale à “banane”, faire un alert de fruit. Etant donné que l’on ne fais qu’une opération, il est même possible d’écrire tout sur une seule ligne de cette manière :


La “compréhension” a également la possibilité de nous retourner une liste :


Cette ligne signifie :  sélectionne fruit pour fruit contenu dans [“banane”, “pomme”, “poire”] lorqu’il est différent de banane. Attention à ne pas oublier les parenthèses. Sans celles-ci, maListe contiendra uniquement le dernier résultat (poire).

CoffeeScript Orienté Objet

CoffeeScript simplifie beaucoup la partie Orienté Objet de JavaScript. Ainsi pour créer une classe il nous suffit d’utiliser le mot clé class :


Remplissons notre classe en lui fournissant des attributs, des fonctions et un constructeur :


Comme le montre l’exemple, afin de créer un attribut, il suffit de placer le sigle @ devant. Les méthodes sont comme de simples variables. Enfin le mot clé constructor indique la fonction qui sera exécuté lors de l’instanciation de la classe. Si un des arguments possède un @, le compilateur comprendra qu’il s’agit d’initialiser un attribut. A la compilation cela donne :


 

Il est également possible de mettre en place l’héritage grâce au mot clé extends :


Le mot clé super invoquera la méthode de la classe mère ayant le même nom que la méthode courante.

 

Voilà, ce billet touche à sa fin. Je n’ai pas tout expliqué sur CoffeeScript, il reste encore beaucoup de notions. Pour en apprendre plus, n’hésitez pas à vous rendre sur le tutoriel officiel . Celui-ci est très complet et très bien fait. 🙂