IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

JavaScript - Apprendre les avantages du modèle RORO : fonction recevant et retournant un objet,
Par Bill Sourour et traduit par danielhagnoul

Le , par danielhagnoul

0PARTAGES

Auteur : Bill Sourour
Source : Elegant patterns in modern JavaScript: RORO

Ce billet résume, en français, les avantages du modèle RORO (recevoir un objet, retourner un objet) de Bill Sourour.

  • Paramètres nommés
  • Paramètres par défaut et requis plus propres
  • Valeurs de retour plus riche et composition de fonction plus facile


Paramètres nommés

Supposons que nous ayons une fonction qui renvoie une liste d'utilisateurs dans un rôle donné et supposons que nous devons fournir une option pour inclure les informations de contact de chaque utilisateur et une autre option pour inclure les utilisateurs inactifs, traditionnellement nous pourrions écrire : function findUsersByRole ( role, withContactInfo, includeInactive ) {...}.

Un appel à cette fonction pourrait ressembler à : findUsersByRole( 'admin', true, true ).

En passant un objet notre fonction semble presque identique sauf que nous mettons des accolades autour de nos paramètres : function findUsersByRole ( { role, withContactInfo, includeInactive } = {} ) {...}.

Cela fonctionne en raison d'une fonctionnalité JavaScript introduite dans ES2015 appelée la déstructuration (destructuring).

Déstructuration : const {x, y} = {x: 11, y: 8}; ce qui est pareil que : const {x: x, y: y} = {x: 11, y: 8};.
Vous pouvez également combiner des raccourcis de valeur de propriété avec des valeurs par défaut : const {x, y = 1} = {}; // x = undefined; y = 1.

Maintenant, nous devons appeler notre fonction comme ceci : findUsersByRole( { role: 'admin', withContactInfo: true, includeInactive: true } ).

Nous utiliserons cette méthode (RORO) lorsqu'elle ajoute de la valeur en rendant une liste de paramètres plus claire et flexible et en rendant une valeur de retour plus expressive. Bien entendu, si vous écrivez une fonction qui n'a besoin de recevoir qu'un seul paramètre, la réception d'un objet est trop lourde. De même, si vous écrivez une fonction qui peut communiquer une réponse claire et intuitive à l'appelant en retournant une valeur simple, il n'est pas nécessaire de retourner un objet.

Paramètres par défaut et requis plus propres

Code JavaScript : Sélectionner tout
1
2
3
4
5
function findUsersByRole ({ 
  role = kRequiredParam('role'), // fonction incluse dans dvjhUtilities-1.7.0.js, voir le billet précédent. 
  withContactInfo = true,  
  includeInactive = true 
} = {} ) {...}

Maintenant, nous pouvons appeler notre fonction comme ceci : findUsersByRole( { role: 'admin' } ) ou comme ceci : findUsersByRole( { role: 'admin', includeInactive: false } ) ou comme ceci : findUsersByRole( { includeInactive: true, role: 'admin' } ).

N'oubliez pas que l'on passe un objet, nous pouvons donc donner les propriétés dans un ordre aléatoire et omettre une propriété lorsqu'elle a une valeur par défaut.

La propriété "role" ne pouvant recevoir une valeur par défaut valide, on lui donne la valeur de retour (Error) de kRequiredParam('role'). On peut également utiliser la fonction kRequiredParamVerbose() (fonction incluse dans dvjhUtilities-1.7.0.js, voir le billet précédent). Exemple :

Code JavaScript : Sélectionner tout
1
2
3
4
5
function findUsersByRole ({ 
  role = kRequiredParamVerbose( { param : "role", type : "String", info : "rôle de l'utilisateur" } ), 
  withContactInfo = true,  
  includeInactive = true 
} = {} ) {...}

Si quelqu'un appelle findUsersByRole sans fournir de rôle, il obtiendra l'erreur suivante :
Required parameter is missing : param = role, type = String, info = role jouer par le personne
at findUsersByRole
.

Valeurs de retour plus riche et composition de fonction plus facile

Imaginez une fonction qui enregistre un utilisateur dans une base de données. Lorsque cette fonction renvoie un objet, elle peut fournir beaucoup d'informations à l'appelant. Lorsque nous insérons des lignes dans une table de base de données (si elles n'existent pas déjà) ou les mettons à jour (si elles existent), il serait utile de savoir si l'opération effectuée par notre fonction "Save" était un "INSERT" ou un "UPDATE". Il serait également bon d'obtenir une représentation exacte de ce qui était stocké dans la base de données, et il serait bon de connaître l'état de l'opération ; a-t-elle réussi, est-ce qu'elle est en attente dans le cadre d'une transaction plus importante, a-t-elle expiré ?

Lorsque vous renvoyez un objet, il est facile de communiquer toutes ces informations à la fois.

La composition de fonction est le processus consistant à combiner deux ou plusieurs fonctions pour produire une nouvelle fonction. Composer des fonctions ensemble, c'est comme assembler une série de tuyaux pour que nos données circulent ("Function composition is the process of combining two or more functions to produce a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.” — Eric Elliott).

Utiliser RORO lève la limitation de la composition de fonctions qui est que chaque fonction de la liste ne peut recevoir qu'un seul paramètre.

Nous utiliserons la fonction kFunctionPipe( ...funcs ) qui est incluse dans dvjhUtilities-1.7.0.js, voir le billet précédent. Cette fonction prend une liste de fonctions et renvoie une fonction qui peut appliquer la liste de gauche à droite, en commençant par un paramètre donné, puis en transmettant le résultat de chaque fonction de la liste à la fonction suivante de la liste.

Voici un exemple où nous avons une fonction saveUser qui canalise un objet userInfo à travers 3 fonctions distinctes qui traitent les informations de l'utilisateur en séquence.

Code JavaScript : Sélectionner tout
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
function validate ( { 
  id = kRequiredParam( "id" ), 
  firstName = kRequiredParam( "firstName" ), 
  lastName = kRequiredParam( "lastName" ), 
  email = kRequiredParam( "email" ), 
  username = kRequiredParam( "userName" ), 
  pass = kRequiredParam( "pass" ), 
  address = kRequiredParam( "addres" ), 
  ...rest 
} = {} ) { 
  // valider les données 
  
  return { id, firstName, lastName, email, username, pass, address, ...rest } 
} 
  
function normalize( { email, username, ...rest } = {} ){ 
  // "normaliser" les données 
  
  return { email, username, ...rest }; 
} 
  
function persist( { upsert = true, ...info } = {} ){ 
  // sauvegarder userInfo dans la base de données 
  
  return { operation : "INSERT", status : "Success", saved : info }; 
} 
  
function saveUser( userInfo = kRequiredParam( "userInfo" ) ) { 
  return kFunctionPipe( validate, normalize, persist )( userInfo ); 
} 
  
let userInfo = { 
  id : "id42", 
  firstName : "Daniel", 
  lastName : "Hagnoul", 
  email : "moi@ici.be", 
  username : "danielhagnoul", 
  pass : "motdepasse", 
  address : "adresse", 
  rue : "ma rue", 
  codePostal : 4242, 
  ville : "Les Mimosas en fleurs" 
}; 
  
let result = saveUser( userInfo ); 
  
for ( const key in result ){ 
  if ( key === "saved" ){ 
    for ( const key2 in result[ key ] ){ 
      console.log( key2, " = ", result[ key ][ key2 ] ); 
    } 
  } else { 
    console.log( key, " = ", result[ key ] ); 
  } 
} 
  
/* 
  * operation = INSERT 
  * status = Success 
  * email = moi@ici.be 
  * username = danielhagnoul 
  * id = id42 
  * firstName = Daniel 
  * lastName = Hagnoul 
  * pass = motdepasse 
  * address = adresse 
  * rue = ma rue 
  * codePostal = 4242 
  * ville = Les Mimosas en fleurs 
  */

Licence Creative Commons Attribution 2.0 Belgique

Une erreur dans cette actualité ? Signalez-nous-la !