Skip to content

Commit 838c445

Browse files
author
Wassim CHEGHAM
committed
french translation (100%)
1 parent 2b49a8d commit 838c445

File tree

1 file changed

+317
-6
lines changed

1 file changed

+317
-6
lines changed

i18n/README-fr-fr.md

Lines changed: 317 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -833,31 +833,342 @@ Ce patron est également connu sous le nom de publish/subscribe (ou producteur/c
833833

834834
Pour les bonnes pratiques concernant ce patron, voir [Le patron Observer en tant que Service externe](#observer-pattern-as-an-external-service)
835835

836-
#### Chain of Responsibilities
836+
#### Chaîne de responsabilité
837837

838+
> le patron de conception Chaîne de responsabilité permet à un nombre quelconque de classes d'essayer de répondre à une requête sans connaître les possibilités des autres classes sur cette requête.
838839
840+
![Chain of Responsibilities](https://rawgit.com/mgechev/angularjs-in-patterns/master/images/chain-of-responsibilities.svg "Fig. 5")
841+
842+
Comme cité précédemment, les `$scopes`dans AngularJS forment une hiérarchie connue sous le nom de chaîne de scope. Certains d’entre eux peut être isolés, ce qui signifie qu’ils n’héritent pas des prototypes de leurs parents ; cependant, chaque `$scope`connait son parent direct grâce à la propriétés `$parent`qu'il contient.
843+
844+
Lorsque les méthode `$emit`et `$broadcast`sont appelées, les `$scope`deviennent alors comme un bus d’événement, ou plus précisément, une chaine de responsabilité. Une fois l’événement est a été déclenché, que ce soit vers les parents ou les enfants, chaque `$scope`peut :
845+
846+
- traiter l’événement et le passer au `$scope`suivant dans la chaîne.
847+
- traiter l’événement et stopper sa propagation.
848+
- passer directement l’événement au `$scope`suivant sans le traiter.
849+
- stopper directement la propagation de l’événement.
850+
851+
Dans l’exemple suivant, nous pouvons constater que `ChildCtrl` déclenche un événement, qui est propager vers le haut de la chaîne. Chaque `$scope`parent - celui créé par `ParentCtrl` et l’autre créé par `MainCtrl`- traite l’événement en affichant dans la console `"foo received"`. Si un `$scope`considère qu’il doit stopper la propagation de cet événement, il doit appeler la méthode `stopPropagation()`sur l’événement en question.
852+
853+
Voici l’exemple de code :
854+
855+
``` JavaScript
856+
myModule.controller('MainCtrl', function ($scope) {
857+
$scope.$on('foo', function () {
858+
console.log('foo received');
859+
});
860+
});
861+
862+
myModule.controller('ParentCtrl', function ($scope) {
863+
$scope.$on('foo', function (e) {
864+
console.log('foo received');
865+
});
866+
});
867+
868+
myModule.controller('ChildCtrl', function ($scope) {
869+
$scope.$emit('foo');
870+
});
871+
```
872+
873+
Les `Handler`figurant dans le diagramme UML correspondent aux différents `$scope`injectés dans les contrôleurs.
839874

840875
#### Command
841876

877+
> Ce patron emboîte une demande dans un objet, permettant de paramétrer, mettre en file d'attente, journaliser et annuler des demandes.
878+
879+
![Command](https://rawgit.com/mgechev/angularjs-in-patterns/master/images/command.svg "Fig. 11")
880+
881+
882+
883+
Avant de rentrer dans les expliquation de ce patron de conception, étudions comment AngularJS implémente le `data biding`(ou liaison de données).
884+
885+
Pour associer un modèle à une vue, nous utilisons la directive `ng-bind`, pour une liaison uni-directionnelle, et `ng-model`pour une liaison bi-directionnelle. Par exemple, si nous souhaitons que tous les changements du modèle soient reflétés dans la vue automatiquement :
886+
887+
``` html
888+
<span ng-bind="foo"></span>
889+
```
890+
891+
A chaque fois que le modèle `foo` subit un changement, le contenu de la balise `span` sera mis à jour **automagiquement**. Voici un exemple avec une expression AngularJS :
892+
893+
``` html
894+
<span ng-bind="foo + ' ' + bar | uppercase"></span>
895+
```
896+
897+
Dans cet exemple, le contenu de la balise `span` sera le résultat de la concaténation des valeurs des modèles `foo`et `bar`. Mais que ce passe-t-il sous le capot ? Que fait AngularJS réellement ?
898+
899+
Chaque `$scope`possède une méthode `$watch`. Lorsque le compilateur d'AngularJS traverse le DOM est rencontre une directive `ng-bind`, il créé un observateur (`watcher`) basé sur l’expression rencontrée : ion `foo + ' ' + bar | uppercase` comme ceci :
900+
901+
``` Javascript
902+
$scope.$watch("foo + ' ' + bar | uppercase", function update() { /* body */ });
903+
```
904+
905+
La callback `update`sera déclenchée à chaque fois que la valeur de l’expression vient à changer. Dans notre exemple, la callback met à jour le contenu de la balise `span`.
906+
907+
Voici un aperçu du début de l’implémentation de la méthode `$watch`:
908+
909+
``` javascript
910+
$watch: function(watchExp, listener, objectEquality) {
911+
var scope = this,
912+
get = compileToFn(watchExp, 'watch'),
913+
array = scope.$$watchers,
914+
watcher = {
915+
fn: listener,
916+
last: initWatchVal,
917+
get: get,
918+
exp: watchExp,
919+
eq: !!objectEquality
920+
};
921+
//...
922+
```
923+
924+
Nous pouvons considérer l’objet `watcher` comme une commande. L’expression de la commande est évaluée à chaque itération de la boucle de digestion ou [`"$digest"`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest). Lorsque AngularJS détecte un changement dans l’expression, la fonction `listener` est invoquée. La commande `watcher `encapsule tout le nécessaire pour observer une expression donnée, et déléguer l’exécution de la commande à la fonction `listener`, le `receiver` dans le diagramme UML. Le `$scope`quant à lui est l’équivalent du `Client` et la boucle de `$digest`est le `Invoker`.
925+
842926
### Controllers
843927
844-
#### Page Controller
928+
#### Contrôleur de page
929+
930+
> Un objet qui traite la requête d’une page ou une action. — [Martin Fowler](https://en.wikipedia.org/wiki/Martin_Fowler)
931+
932+
![Page Controller](https://rawgit.com/mgechev/angularjs-in-patterns/master/images/page-controller.svg "Fig. 8")
933+
934+
D’après le point [4](#references) un contrôleur de page est :
935+
936+
> Le patron de conception Contrôleur de page, ou Page Controller, accepte une entrée depuis la requête, invoque l’action demandée d’un modèle, puis détermine la vue à utiliser pour la construction de la page finale.
937+
938+
Il peut exister une certaine hiérarchie au sein des contrôleurs de page, puisqu’une page peut être construite en assemblant plusieurs blocs, tels que les headers, les footers, les blocs d’informations de session, etc. Dans AngularJS, nous avons des contrôleurs, mais avec beaucoup moins de responsabilités. Ils ne traitent pas les requêtes des utilisateurs, c’est la responsabilité des services `$router`ou `$state`et le rendu de la page est à la charge des directives `ng-view`ou `ui-view`.
939+
940+
De la même manière que les Contrôleurs de page, les contrôleurs d’angulaires traite les interactions des utilisateurs, expose et mettent à jour les modèles. Le modèle est exposé à la vue, lorsqu’il est attaché au `$scope`; et toutes les méthodes invoquées dans les vues, en réponse aux interactions de l’utilisateur, sont également attachées au `$scope`. Une autre similitude avec les Contrôleurs de page, se situe au niveau de la hiérarchie qu’ils forment. Ces hiérarchie correspond à celle formée par la chaine des `$scope`. Ainsi, il est possible d’isoler des actions dans certains contrôleurs, ceux situés tout en haut de la chaîne.
941+
942+
Voici un exemple illustrant cette hiérarchie :
943+
944+
``` HTML
945+
<!doctype html>
946+
<html>
947+
<head>
948+
</head>
949+
<body ng-controller="MainCtrl">
950+
<div ng-controller="ChildCtrl">
951+
<span>{{user.name}}</span>
952+
<button ng-click="click()">Click</button>
953+
</div>
954+
</body>
955+
</html>
956+
```
957+
958+
``` JavaScript
959+
function MainCtrl($scope, $location, User) {
960+
if (!User.isAuthenticated()) {
961+
$location.path('/unauthenticated');
962+
}
963+
}
964+
965+
function ChildCtrl($scope, User) {
966+
$scope.click = function () {
967+
alert('Cliqué !');
968+
};
969+
$scope.user = User.get('123abc');
970+
}
971+
```
972+
973+
Cet exemple (à ne pas utiliser dans un code en production !) a pour but d’illustrer l’utilisation d’un contrôleur de base `MainCtrl` dans lequel nous isolons la logique qui sera utilisée par les sous-contrôleur. Le contrôleur `ChildCtrl` est responsable de gérer les actions de l’utilisateur tel que la gestion des cliques sur le bouton, ainsi que d’exposer le modèle `user`à la vue en l’attachant au `$scope`.
845974
846975
### Others
847976
848977
#### Module Pattern
849978
979+
Ce patron de conception ne figure ni dans le catalogue des [Gang of Four](http://c2.com/cgi/wiki?CategoryPattern), ni dans celui du [P of EAA](http://www.martinfowler.com/eaaCatalog/index.html). Par contre, c’est un patron de conception classique en JavaScript, dont le rôle est d’apporter une certaine forme d’encapsulation.
980+
981+
En se basant sur le patron Module, il est possible de tirer avantage de la puissance des fermetures ([`closure`](http://wassimchegham.com/blog/javascript-pour-les-jedis-episode-2-attaque-des-closures-ou-fermetures)) et de la portée lexicale qui limite la visibilité des variables aux fonctions dans lesquelles elle ont été déclarées.
982+
983+
Chaque module peut avoir zéro ou plusieurs membres privés, accessible uniquement dans la portée locale de la function. Cette fonction retourne un objet qui expose une API publique du module en question. Voici un exemple :
984+
985+
``` javascript
986+
var Page = (function () {
987+
988+
var title;
989+
990+
function setTitle(t) {
991+
document.title = t;
992+
title = t;
993+
}
994+
995+
function getTitle() {
996+
return title;
997+
}
998+
999+
return {
1000+
setTitle: setTitle,
1001+
getTitle: getTitle
1002+
};
1003+
1004+
}());
1005+
```
1006+
1007+
Dans cet exemple, nous avons déclaré une IIFE (Immediately-Invoked Function Expression), une fonction auto-invoquée qui, une fois invoquée retourne un objet avec deux méthodes : `setTitle()` et `getTitle()`. Cet objet est ensuite affecté à la variable `Page`.
1008+
1009+
L’entité manipulant la variable `Page`n’a pas accès à la variable `title` par exemple, qui est définit dans la IIFE.
1010+
1011+
Ce patron est également très intéressant lorsque nous devons définir des services en AngularJS. Nous pouvons rendre privée, une partie de la logique :
1012+
1013+
``` javascript
1014+
app.factory('foo', function () {
1015+
1016+
function privateMember() {
1017+
//body...
1018+
}
1019+
1020+
function publicMember() {
1021+
//body...
1022+
privateMember();
1023+
//body
1024+
}
1025+
1026+
return {
1027+
publicMember: publicMember
1028+
};
1029+
});
1030+
```
1031+
1032+
Une fois le service `foo` injecté dans un composant, il ne nous sera pas possible d’utiliser directement les méthodes privées, mais uniquement celles exposées par l’objet retourné. Cette solution est extrêmement puissante surtout si nous développons une librairie.
1033+
8501034
### Data Mapper
8511035
852-
### Observer Pattern as an External Service
1036+
> Un Data Mapper est une couche d’accès au données qui réalise un transfert bi-directionnel entre la persistence de données (souvent une base relationnelle) et une représentation des données en mémoire (la couche métier). Le but de ce patron est de garder ces deux couches indépendantes les unes des autres, ainsi que du Data Mapper lui-même.
1037+
1038+
![Data Mapper](https://rawgit.com/mgechev/angularjs-in-patterns/master/images/data-mapper.svg "Fig. 10")
1039+
1040+
Comme cité dans la définition, le Data Mapper est utilisé pour le transfert bi-directionnel de données entre la couche de persistence et la couche métier. Dans AngularJS, l’application communique avec un serveur exposant une API RESTFul. AngularJS propose le service `$resource`qui permet de communiquer avec le serveur dans un style [Active Record](#active-record). Souvent, les entités retournées par l’API ne correspondent toujours pas formatées de la façon qui nous arrange pour être directement exploitées.
1041+
1042+
Prenons par exemple ce cas de figure, supposons que l’on dispose d’un modèle `User` avec les attributs suivants :
1043+
1044+
- un nom.
1045+
- une adresse.
1046+
- une luiste d'amis
1047+
1048+
Voici l’API exposant les ressources suivantes :
1049+
1050+
- `GET /users/:id` : retourne le nom et l’adresse d’un utilisateur.
1051+
- `GET /friends/:id` : retourne la liste d’amis d’un utilisateur.
1052+
1053+
Une première solution naïve consisterait à avoir deux services, un pour la première ressource et une autre pour la seconde. Mais ce serait mieux si nous avions qu’un seul et unique service, `User `par exemple :
1054+
1055+
``` javascript
1056+
app.factory('User', function ($q) {
1057+
1058+
function User(name, address, friends) {
1059+
this.name = name;
1060+
this.address = address;
1061+
this.friends = friends;
1062+
}
1063+
1064+
User.get = function (params) {
1065+
var user = $http.get('/users/' + params.id),
1066+
friends = $http.get('/friends/' + params.id);
1067+
$q.all([user, friends])
1068+
.then(function (user, friends) {
1069+
return new User(user.name, user.address, friends);
1070+
});
1071+
};
1072+
return User;
1073+
});
1074+
```
1075+
1076+
Avec cette solution, nous avons crée un pseudo Data Mapper, qui a pour rôle d’adapter l’API en fonction des contraintes de notre SPA.
1077+
1078+
Nous pouvons utiliser le service `User` comme ceci :
1079+
1080+
``` javascript
1081+
function MainCtrl($scope, User) {
1082+
User.get({ id: 1 }).then(function (data) {
1083+
$scope.user = data;
1084+
});
1085+
}
1086+
```
1087+
1088+
Et la vue :
1089+
1090+
``` html
1091+
<div>
1092+
<div>
1093+
Name: {{user.name}}
1094+
</div>
1095+
<div>
1096+
Address: {{user.address}}
1097+
</div>
1098+
<div>
1099+
Friends with ids:
1100+
<ul>
1101+
<li ng-repeat="friend in user.friends">{{friend}}</li>
1102+
</ul>
1103+
</div>
1104+
</div>
1105+
```
1106+
1107+
1108+
1109+
### Le patron Observer grâce à un Service Commun
1110+
1111+
L’exemple de code a été récupéré depuis [ce projet](https://github.com/greglbd/angular-observer-pattern). Cet une factorie AngularJS qui créé un service implémentant le patron Observer. Ce patron fonctionne très bien avec la syntaxe `ControllerAs` et sert comme une alternative à `$scope.$watch()`ou encore `$scope.emit()`et `$scope.broadcast()`.
1112+
1113+
Ce patron est utilisé pour faire communiquer plusieurs contrôleurs utilisant le même modèle.
1114+
1115+
Voici un exemple démontrant comment attacher, notifier et détacher un événement grâce un Service Commun :
1116+
1117+
``` javascript
1118+
angular.module('app.controllers')
1119+
.controller('ObserverExample', ObserverExample);
1120+
1121+
ObserverExample.$inject= ['ObserverService', '$timeout'];
1122+
1123+
function ObserverExample(ObserverService, $timeout) {
1124+
var vm = this;
1125+
var id = 'vm1';
1126+
1127+
ObserverService.attach(callbackFunction, 'let_me_know', id)
1128+
1129+
function callbackFunction(params){
1130+
console.log('now i know');
1131+
ObserverService.detachByEvent('let_me_know')
1132+
}
1133+
1134+
$timeout(function(){
1135+
ObserverService.notify('let_me_know');
1136+
}, 5000);
1137+
}
1138+
```
1139+
1140+
Alternative way to remove event
1141+
1142+
``` javascript
1143+
angular.module('app.controllers')
1144+
.controller('ObserverExample', ObserverExample);
1145+
ObserverExample.$inject= ['ObserverService', '$timeout', '$scope'];
1146+
1147+
function ObserverExample(ObserverService, $timeout, $scope) {
1148+
var vm = this;
1149+
var id = 'vm1';
1150+
ObserverService.attach(callbackFunction, 'let_me_know', id)
1151+
1152+
function callbackFunction(params){
1153+
console.log('now i know');
1154+
}
1155+
1156+
$timeout(function(){
1157+
ObserverService.notify('let_me_know');
1158+
}, 5000);
1159+
1160+
// Cleanup listeners when this controller is destroyed
1161+
$scope.$on('$destroy', function handler() {
1162+
ObserverService.detachByEvent('let_me_know')
1163+
});
1164+
}
1165+
```
8531166
854-
##### About
8551167
856-
##### Controller Example
8571168
8581169
## References
8591170
860-
1. [Wikipedia](https://en.wikipedia.org/wiki). The source of all brief descriptions of the design patterns is wikipedia.
1171+
1. [Wikipedia](https://en.wikipedia.org/wiki). Toutes les définition des patrons de conception viennent de Wikipedia.
8611172
2. [AngularJS' documentation](https://docs.angularjs.org)
8621173
3. [AngularJS' git repository](https://github.com/angular/angular.js)
8631174
4. [Page Controller](http://msdn.microsoft.com/en-us/library/ff649595.aspx)

0 commit comments

Comments
 (0)