J’étais très réfractaire à développer une solution full javascript puisque pour moi ce n’était pas vraiment un langage; Pas de notion de classe, interface, héritage …
Mais étant donné la tendance des applications je me suis tourné vers ce langage en utilisant le framework Angular qui pour moi est un framework assez complet. Très tourné injection de dépendance, je me suis dit je vais pouvoir faire une vraie application.
Je me suis rendu compte à l’utilisation qu’il était possible de faire le meilleur comme le pire. En maitrisant bien l’usage ce n’est plus un calvaire d’utiliser angular. Je vais donc essayer d’expliquer ma vision des choses dans cet article.
Factory/Service :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
(function () { angular .module('Module') .factory('Service', Service); Service.$inject = ['dependency1']; function Service(dependency1) { //Champs privés var field = null; var publicProperty = null; //Méthodes ou propriétés publiques var service = { exposedFn: exposedFn, property: publicProperty }; return service; //////////////// function exposedFn() { } //Méthode privée function nonExposedFn() { } } })(); |
Tout d’abord l’encapsulation la de la classe par (function() { }(); permet d’éviter les problèmes de conflit à la minification.
Afin de diminuer les portées et que cela soit plus claire, on initialise la factory (ou service) par une fonction non anonyme :
|
(function () { //A éviter angular .module('Module') .factory('Service', function() { }); //Bonne déclaration angular .module('Module') .factory('Service', Service); function Service() { } })(); |
De même pour les injections de dépendances, il est plus clair d’utiliser $inject :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
(function () { //A éviter angular .module('Module') .factory('Service', ['dependency1',function(dependency1) { }]); //Un peu mieux angular .module('Module') .factory('Service', ['dependency1', Service]); function Service(dependency1) { } //Bonne déclaration angular .module('Module') .factory('Service', Service); Service.$inject = ['dependency1']; function Service(dependency1) { } })(); |
Encore une fois préférer l’usage de fonction que l’on expose plutôt que de passer par des fonctions anonymes :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
(function () { //A éviter angular .module('Module') .factory('Service', Service); Service.$inject = ['dependency1']; function Service(dependency1) { return { method1: function() {}, method2: function() {} }; } //Bonne déclaration angular .module('Module') .factory('Service', Service); Service.$inject = ['dependency1']; function Service(dependency1) { var service = { method1:method1, method2:method2 } return service; function method1(){ } function method2(){ } } })(); |
De cette manière, on évite diminue considérablement le nombre de portées et on visualise très facilement les méthodes et propriété publiques et privées. Couplé à une ngDoc on a un code bien lisible et compréhensible de tous 🙂
Controller/Directive
Les conseils évoqués précédemment restent valables pour les controllers et directives néanmoins il y a quelques subtilités que je vais essayer de décrire ici.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
(function() { angular .module('Module') .controller('Controller', Controller); Controller.$inject = ['dependency1']; function Controller(dependency1) { var vm = this; vm.exposedMethod = exposedMethod; vm.exposedProperty = {}; var nonExposedField = {}; //////////////// function exposedMethod() { } function nonExposedMethod() { } } })(); |
Par convention dans un controller on écrit  : var vm = this (vm = ViewModel). Ce qui correspond donc à ce qui va être exposé côté vue.
Du coup dans un soucis de performance et de lisibilité, il faut absolument exposer uniquement les propriétés et méthodes que l’on souhaite utiliser côté vue.
J’espère que ces conseils vont vous aider à mieux organiser vos classes angular.
Dans un prochain article, j’aborderais la structure d’une application angular.
PS : Ces conseils sont inspirés de John Papa, évangéliste Angular : https://github.com/johnpapa/angular-styleguide