Combien de paramètres sont trop nombreux? [fermé]


228

Les routines peuvent avoir des paramètres, ce n'est pas une nouveauté. Vous pouvez définir autant de paramètres que nécessaire, mais un trop grand nombre d'entre eux rendra votre routine difficile à comprendre et à maintenir.

Bien sûr, vous pouvez utiliser une variable structurée comme solution de contournement: mettre toutes ces variables dans une seule structure et la passer à la routine. En fait, l'utilisation de structures pour simplifier les listes de paramètres est l'une des techniques décrites par Steve McConnell dans Code Complete . Mais comme il le dit:

Les programmeurs prudents évitent de regrouper les données plus qu'il n'est logiquement nécessaire.

Donc, si votre routine contient trop de paramètres ou si vous utilisez une structure pour masquer une grande liste de paramètres, vous faites probablement quelque chose de mal. Autrement dit, vous ne laissez pas le couplage desserré.

Ma question est, quand puis-je considérer une liste de paramètres trop grande? Je pense que plus de 5 paramètres, c'est trop. Qu'est-ce que tu penses?


1
Il suffit de référencer ici cette question qui est un exemple pratique de combien de paramètres sont trop nombreux ...
Gideon

5
En JavaScript, les paramètres 65537 sont trop nombreux: jsfiddle.net/vhmgLkdm
Aadit M Shah

il suffit de regarder les composants Apache http, il est presque impossible d'en construire quelque chose de dynamique
Andrew Scott Evans

Réponses:


162

Quand quelque chose est-il considéré comme obscène au point d'être réglementé malgré la garantie du 1er amendement à la liberté d'expression? Selon le juge Potter Stewart, "je le sais quand je le vois." Il en va de même ici.

Je déteste créer des règles dures et rapides comme celle-ci, car la réponse change non seulement en fonction de la taille et de la portée de votre projet, mais je pense que cela change même au niveau du module. Selon ce que fait votre méthode ou ce que la classe est censée représenter, il est fort possible que 2 arguments soit trop et soit un symptôme de trop de couplage.

Je dirais qu'en posant la question en premier lieu, et en nuançant votre question autant que vous, vous savez vraiment tout cela. La meilleure solution ici n'est pas de s'appuyer sur un nombre fixe et rapide, mais plutôt de rechercher des revues de conception et des revues de code entre vos pairs pour identifier les zones où vous avez une faible cohésion et un couplage serré.

N'ayez jamais peur de montrer à vos collègues votre travail. Si vous en avez peur, c'est probablement le plus gros signe que quelque chose ne va pas avec votre code, et que vous le savez déjà .


Une bonne règle est le nombre de registres CPU, car plus et le compilateur sera obligé de les allouer sur la pile.
Michaelangel007

1
@ Michaelangel007 concernant la réponse que vous commentez, vous ne devriez pas dire cela, car cela indique qu'il n'y a pas de règle. De plus, le nombre de paramètres est une question de lisibilité, pas de performances.
clemp6r

1
@ clemp6r Incorrect - c'est les deux . Les compilateurs doivent tout le temps faire face aux «déversements enregistrés». La seule réponse faisant autorité est d'inspecter l'assemblage de ce que votre compilateur génère. Le nombre de registres ne change pas comme par magie sur la même plateforme. en.wikipedia.org/wiki/Register_allocation
Michaelangel007

124

Une fonction ne peut avoir trop de paramètres que si certains paramètres sont redondants. Si tous les paramètres sont utilisés, la fonction doit avoir le nombre correct de paramètres. Prenez cette fonction souvent utilisée:

HWND CreateWindowEx
(
  DWORD dwExStyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam
);

Cela fait 12 paramètres (9 si vous regroupez les x, y, w et h sous forme de rectangle) et il y a aussi les paramètres dérivés du nom de la classe. Comment réduiriez-vous cela? Souhaitez-vous réduire davantage le nombre au point?

Ne laissez pas le nombre de paramètres vous déranger, assurez-vous simplement qu'il est logique et bien documenté et laissez Intellisense * vous aider.

* D'autres assistants de codage sont disponibles!


37
Je vote ça. Je suis étonné de toutes les autres réponses disant "3" et "4"! La bonne réponse est: le minimum nécessaire, qui peut parfois être assez élevé.
Tony Andrews,

16
Si cette fonction était conçue aujourd'hui, elle serait probablement un peu différente. x, y, nWidth et nHeight peuvent être regroupés dans un objet Rectangle. style et xStyle peuvent être combinés en un ensemble d'énumérations ou de chaînes. Vous n'avez maintenant que 8 paramètres.
finnw

16
@finnw Si cette fonction avait été conçue aujourd'hui? Il a déjà été repensé. Formulaire f = nouveau Formulaire (); a 0 paramètre.
Nick

36
C'est C et winapi. Je ne peux pas penser à un pire exemple.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

17
Non non. Il s'agit d'un style procédural. Les fenêtres sont des objets, c'est donc obsolète maintenant. Aujourd'hui, cela serait résolu avec des classes agrégées, pas avec un tas de paramètres. La règle intuitive d'une bonne conception est que si vous ne pouvez pas décrire la fonction (y compris les paramètres) en une phrase simple, elle est mal conçue . Je pense que c'est le cas.
Jan Turoň

106

Dans Clean Code , Robert C. Martin a consacré quatre pages au sujet. Voici l'essentiel:

Le nombre idéal d'arguments pour une fonction est zéro (niladique). Vient ensuite un (monadique), suivi de près par deux (dyadique). Trois arguments (triadiques) doivent être évités dans la mesure du possible. Plus de trois (polyadiques) nécessitent une justification très spéciale - et ne devraient donc pas être utilisés de toute façon.


2
Je doute que cela comprenne "ceci" parce que c'est le contexte de l'exécution. En programmation fonctionnelle, le contexte est global et en oop, le contexte est l'objet sur lequel vous appliquez la méthode. De plus, si vous incluiez "ceci" dans la liste des paramètres, il serait impossible d'avoir 0 paramètre (idéal).
Tom

1
Non, cela n'inclut pas "ceci".
Patrick McElhaney

20
De plus, Martin devrait avoir un mot avec le comité standard C ++. La moitié de <algorithme> prend plus de 3 paramètres, car une seule plage d'itérateurs est déjà 2. C'est juste la nature de la programmation avec les itérateurs (c'est-à-dire la programmation générique avec les collections STL).
Steve Jessop

3
@SteveJessop: la faute de <algorithm> est qu'il fonctionne toujours sur une tranche. Si l'algorithme et la collection devaient être repensés, je ferais que les algorithmes prennent toujours une collection entière, et vous auriez un moyen de découper une vue d'une collection pour permettre aux algorithmes de travailler sur des parties; en variante, je définirais également un remplacement abrégé pour faciliter le travail sur le cas commun.
Lie Ryan

3
@LieRyan: alors que si je repensais, <algorithm>je le ferais agir sur un objet range. Les collections seraient des plages, mais toutes les plages ne seraient pas des collections. Et en effet, boost l'a déjà fait. Quoi qu'il en soit, mon point est qu'une bibliothèque utilisée massivement largement ignore ce conseil, de sorte que le pire qui est garanti pour vous arriver si vous le faites aussi, est que beaucoup de vos millions d'utilisateurs vont bricoler avec Simplifications mineures à votre interface ;-)
Steve Jessop

79

Certains codes avec lesquels j'ai travaillé dans le passé utilisaient des variables globales juste pour éviter de passer trop de paramètres.

Veuillez ne pas faire ça!

(Habituellement.)


Un code sur lequel je travaillais sur des membres de classe utilisés pour atteindre la même chose. À cette époque, j'étais programmeur C et j'ai demandé pourquoi il y avait tant de variables globales, pourquoi les entrées / sorties ne pouvaient-elles pas être des paramètres explicites?
user3528438

38

Si vous commencez à compter mentalement les paramètres de la signature et à les faire correspondre à l'appel, il est temps de refactoriser!


C’est une très bonne réponse. Si les paramètres sont organisés logiquement (x, y, w, h), il est facile de se souvenir de tous dans le bon ordre. Il est plus difficile de se rappeler où placer le pointeur FILE dans putc (qui n'a que deux paramètres), d'autant plus que fprintf est l'inverse.
user877329

La plus belle réponse. Très bien dit
Anwar

31

Merci beaucoup pour toutes vos réponses:

  • C'était un peu surprenant de trouver des gens qui pensent aussi (comme moi) que 5 paramètres est une bonne limite pour la santé mentale du code.

  • Généralement, les gens ont tendance à penser qu'une limite entre 3 et 4 est une bonne règle de base. Ceci est raisonnable car les gens ont généralement du mal à compter plus de 4 choses.

  • Comme le souligne Milan , les gens peuvent en moyenne garder plus ou moins 7 choses en tête à la fois. Mais je pense que vous ne pouvez pas oublier que lorsque vous concevez / maintenez / étudiez une routine, vous devez garder à l'esprit plus de choses que les paramètres.

  • Certaines personnes considèrent qu'une routine doit avoir autant d'arguments que nécessaire. Je suis d'accord, mais seulement pour quelques cas spécifiques (appels aux API OS, routines où l'optimisation est importante, etc.). Je suggère de cacher la complexité de ces routines en ajoutant une couche d'abstraction juste au-dessus de ces appels chaque fois que possible.

  • pseudo a quelques réflexions intéressantes à ce sujet. Si vous ne voulez pas lire ses commentaires, je résume pour vous: en un mot, cela dépend :

    Je déteste créer des règles dures et rapides comme celle-ci car la réponse change non seulement en fonction de la taille et de la portée de votre projet, mais je pense que cela change même au niveau du module. Selon ce que fait votre méthode ou ce que la classe est censée représenter, il est fort possible que 2 arguments soit trop et soit un symptôme de trop de couplage.

    La morale ici est de ne pas avoir peur de montrer votre code à vos pairs, de discuter avec eux et d'essayer de "d'identifier les zones où vous avez une faible cohésion et un couplage serré" .

  • Enfin, je pense que wnoise très d'accord avec Nick, et conclut sa contribution satirique avec cette vision poétique (voir commentaires ci-dessous) de l'art de la programmation:

    La programmation n'est pas de l'ingénierie. L'organisation du code est un art car elle dépend de facteurs humains, qui dépendent trop du contexte pour toute règle stricte.


16

Cette réponse suppose un langage OO. Si vous n'en utilisez pas - sautez cette réponse (ce n'est pas tout à fait une réponse indépendante de la langue en d'autres termes.

Si vous passez plus de 3 paramètres environ (en particulier les types / objets intrinsèques), ce n'est pas que c'est "Trop" mais que vous manquez peut-être une chance de créer un nouvel objet.

Recherchez les groupes de paramètres qui sont passés dans plusieurs méthodes - même un groupe passé dans deux méthodes garantit presque que vous devriez y avoir un nouvel objet.

Ensuite, vous refactorisez la fonctionnalité dans votre nouvel objet et vous ne croiriez pas à quel point cela aide à la fois votre code et votre compréhension de la programmation OO.


Veuillez nommer une langue qui n'utilise ni routines ni paramètres. Je ne peux pas penser à un, même l'assemblage pourrait être considéré comme ayant des routines (étiquettes).
Auron

L'assembly x86 a définitivement des routines (appel / retour). D'autres peuvent nécessiter des combos cmp / jmp.
Brian Knoblauch

Désolé, "ret", pas "return". Soupire. La journée a déjà été longue.
Brian Knoblauch

Désolé pour le libellé ambigu d'Auron, je crois que je l'ai corrigé. C'était ma réponse qui était spécifique à la langue, pas la question.
Bill K

1
Toutes les langues ne permettent pas de passer des structures. En outre, le passage d'une structure signifie que la méthode de réception doit avoir le code pour gérer la structure et peut, par conséquent, avoir besoin de plus de paramètres. De plus, dans une langue non oo, vous avez généralement besoin d'un paramètre supplémentaire - toutes les langues OO ont un paramètre "Hidden" de "this" qui devrait autrement être transmis (ou, dans un langage / design plus horrible, peut être globalement accessible)
Bill K

13

Il semble qu'il y ait d'autres considérations que le simple nombre, en voici quelques-unes qui me viennent à l'esprit:

  1. relation logique avec l'objectif principal de la fonction par rapport aux paramètres uniques

  2. S'ils ne sont que des indicateurs d'environnement, le regroupement peut être très pratique


12

L'une des épigrammes de programmation bien connus d'Alan Perlis (racontée dans ACM SIGPLAN Notices 17 (9), septembre 1982) déclare que "si vous avez une procédure avec 10 paramètres, vous en avez probablement manqué quelques-uns".



9

Pour moi, lorsque la liste croise une ligne sur mon IDE, c'est un paramètre de trop. Je veux voir tous les paramètres sur une seule ligne sans rompre le contact visuel. Mais c'est juste ma préférence personnelle.


C'est bien jusqu'à ce que vous avec des développeurs essayiez foo (int a, float b, string c, double d). Mieux vaut essayer d'éviter de travailler avec eux, je suppose. : D
Rontologue

4
Si quelqu'un d'autre a donné aux classes des noms ridiculement longs, je ne laisserais pas cette influence influencer la façon dont je définis ou appelle mes routines.
finnw

9
Puis-je vous présenter le "retour chariot"?

3
Lorsque la liste croise une ligne sur votre IDE, votre moniteur est trop petit pour l'utiliser avec ce code et vous devez clairement acheter un moniteur avec une résolution horizontale plus élevée. Un saut de ligne ou une réduction de la quantité de paramètres ne sont que des solutions de contournement qui ne résolvent pas le problème racine qui est que votre moniteur est trop petit pour cette base de code!
Kaiserludi

9

Je suis généralement d'accord avec 5, cependant, s'il y a une situation où j'ai besoin de plus et que c'est le moyen le plus clair de résoudre le problème, alors j'en utiliserais plus.


8

Sept choses dans la mémoire à court terme?

  1. Nom de la fonction
  2. Valeur de retour de la fonction
  3. But de la fonction
  4. Paramètre 1
  5. Paramètre 2
  6. Paramètre 3
  7. Paramètre 4

Bien. C'est une règle d'or. Lorsque vous codez le corps d'une fonction, vous ne vous souciez pas de son nom, et la valeur de retour et son achat sont étroitement liés.
Auron

7
8. ordre des paramètres
Eva

7

Dans les pires extraits de code 5 , vérifiez le second, "Est-ce un constructeur". Il a comme plus de 37 ⋅ 4 ≈ 150 paramètres:

Ici, un programmeur a écrit ce constructeur [...] Certains d'entre vous peuvent penser que oui, c'est un gros constructeur, mais il a utilisé des outils de génération automatique de code Eclipse [.] NOO, dans ce constructeur, il y avait un petit bug que j'ai découvert, qui m'a fait conclure que ce constructeur a été écrit à la main. (d'ailleurs, ce n'est que la partie supérieure du constructeur, ce n'est pas complet).

constructeur avec plus de 150 paramètres


C'est tellement triste ... Ne pas connaître les «enregistrements» ou les «structures» ou les «objets de valeur», qui regroupent plusieurs valeurs et leur donnent un nom commun afin que vous puissiez en représenter hiérarchiquement beaucoup de manière lisible, c'est comme se promener avec des chaussures sans dentelles depuis des années parce que personne ne vous a jamais dit que vous pouviez même faire ça 🙈
yeoman

6

Un de plus que nécessaire. Je ne veux pas être glib, mais il y a certaines fonctions qui nécessitent nécessairement pas mal d'options. Par exemple:

void *
mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset);

Il y a 6 arguments, et chacun d'eux est essentiel. De plus, il n'existe aucun lien commun entre eux pour justifier leur regroupement. Vous pourriez peut-être définir "struct mmapargs", mais ce serait pire.


Eh bien, protet flagsauraient pu être regroupés si le concepteur avait estimé que 5 était en quelque sorte un nombre magique bien meilleur que 6. Un peu comme la façon qui opencombine le mode lecture / écriture avec tous les autres drapeaux divers. Et peut-être toi pourriez débarrasser offseten spécifiant que la section mappée commence à la position de recherche actuelle de filedes. Je ne sais pas s'il existe des situations où vous pouvez mmapune région que vous n'êtes pas en mesure de lseekfaire, mais sinon, ce n'est pas strictement nécessaire.
Steve Jessop

... donc je pense que mmapc'est une bonne illustration du fait que certains concepteurs et utilisateurs préfèrent une longue liste de paramètres, tandis que d'autres préfèrent passer par quelques étapes pour préparer un plus petit nombre de paramètres avant de passer l'appel.
Steve Jessop

1
@Steve: Définir la position de recherche avec un appel séparé au préalable aurait introduit une condition de concurrence gratuite. Pour certaines API (OpenGL), il y a tellement de paramètres qui affectent un appel que vous devez vraiment utiliser l'état, mais normalement, chaque appel doit être autonome autant que possible. L'action à distance est le chemin vers le côté obscur.
Ben Voigt

5

Selon Perl Best Practices , 3 est correct, 4 est trop. C'est juste une directive, mais dans notre boutique, c'est ce que nous essayons de respecter.


5

Je fixerais moi-même la limite des fonctions publiques à 5 paramètres.

À mon humble avis, les longues listes de paramètres ne sont acceptables que dans les fonctions d'assistance privées / locales qui sont uniquement destinées à être appelées à partir de quelques endroits spécifiques dans le code. Dans ces cas, vous devrez peut-être transmettre de nombreuses informations sur l'état, mais la lisibilité n'est pas un problème majeur car vous seul (ou quelqu'un qui maintiendra votre code et devrait comprendre les principes fondamentaux de votre module) doit se soucier de appeler cette fonction.


C'est exactement pourquoi beaucoup de gens à ce stade feraient tout ce qui n'est pas un argument réel, mais un état transporté, juste l'état d'un objet sous la forme de champs (variables membres). Cet objet serait représenté comme une classe. Il serait instancié une fois ou pour chaque utilisation. Parfois, un tel objet n'aura qu'une seule méthode privée ou publique de package, qui déléguera ensuite les méthodes privées avec peu d'arguments chacune. Peu d'arguments sont désormais possibles car la configuration et l'état ont désormais leur place :)
yeoman

5

Une question connexe que vous devriez considérer est de savoir comment cohérence de la routine. Un grand nombre de paramètres peuvent être une odeur qui vous indique que la routine elle-même essaie d'en faire trop et que sa cohésion est donc suspecte. Je suis d'accord qu'un nombre difficile et rapide de paramètres est probablement impossible, mais je suppose qu'une routine à forte cohésion impliquerait un faible nombre de paramètres.



4

Je m'arrête à trois paramètres en règle générale. Plus et il est temps de passer un tableau de paramètres ou un objet de configuration à la place, ce qui permet également d'ajouter de futurs paramètres sans changer l'API.


Si l'API change, alors l'API devrait réellement changer, non seulement avoir un changement furtif où l'incompatibilité pourrait toujours se produire, mais être moins évident.
wnoise

cependant, si vous avez besoin d'un paramètre de plus pour configurer un cas de périphérie, il ne devrait pas se propager à des composants non liés à l'aide de l'API
Eran Galperin

4

Une restriction de longueur sur une liste de paramètres n'est qu'une restriction de plus. Et la restriction signifie la violence appliquée. Cela peut sembler drôle, mais vous pouvez être non violent même lors de la programmation. Laissez simplement le code dicter les règles. Il est évident que si vous avez de nombreux paramètres, le corps de la méthode fonction / classe sera assez grand pour les utiliser. Et les gros extraits de code peuvent généralement être refactorisés et divisés en petits morceaux. Ainsi, vous obtenez une solution contre le fait d'avoir de nombreux paramètres en bonus gratuit, car ils sont répartis entre les petits morceaux de code refactorisés.


4

Une chose que je voudrais souligner du point de vue des performances est que, selon la façon dont vous transmettez les paramètres à une méthode, le passage de nombreux paramètres par valeur ralentira le programme car chaque paramètre doit être copié puis placé sur la pile.

Utiliser une seule classe pour englober tous les paramètres fonctionnerait mieux car un seul paramètre transmis par référence serait élégant et plus propre, et plus rapide!


Je donne à cette réponse un +1 parce que c'est le seul qui discute autre chose que la propreté du code ou des limites arbitraires, qui sont toutes deux subjectives. Certaines personnes peuvent ne pas penser à ce que vous faites à la pile lorsque vous êtes dans une boucle et que vous poussez des dizaines d'arguments sur et hors de la pile. S'il est dans une boucle, vous devriez envisager d'utiliser le nombre d'arguments transmis par REGISTERS dans l'ABI pour lequel vous compilez. Par exemple, dans le MS x64 ABI, le nombre maximum d'arguments transmis via les registres est de 4. L'ABI "System V" (utilisé par un système d'exploitation non Windows) utilise plus de registres, donc l'utilisation de 4 arguments est assez portable
Lakey

3

Selon moi, il pourrait y avoir des cas où vous dépasseriez 4 ou un certain nombre fixe. Les choses à surveiller pourraient être

  1. Votre méthode en fait trop et vous devez refactoriser.
  2. Vous voudrez peut-être envisager d'utiliser une collection ou une structure de données.
  3. Repensez la conception de votre classe, peut-être que certaines choses n'ont pas besoin d'être transmises.

Du point de vue de la facilité d'utilisation ou de la facilité de lecture du code, je pense que lorsque vous devez "boucler" la signature de votre méthode, cela devrait vous faire réfléchir et vous arrêter, à moins que vous ne vous sentiez impuissant et que tous les efforts pour réduire la signature conduisent à pas de résultat. Certaines très bonnes bibliothèques dans le passé et le présent utilisent plus de 4 à 5 poussettes.


3

Ma règle de base est que je dois pouvoir me souvenir des paramètres assez longtemps pour regarder un appel et dire ce qu'il fait. Donc, si je ne peux pas regarder la méthode, puis basculer vers un appel d'une méthode et me rappeler quel paramètre fait quoi, alors il y en a trop.

Pour moi, cela équivaut à environ 5, mais je ne suis pas si brillant. Votre kilométrage peut varier.

Vous pouvez créer un objet avec des propriétés pour contenir les paramètres et le transmettre si vous dépassez la limite que vous définissez. Voir le livre Refactoring de Martin Fowler et le chapitre sur la simplification des appels de méthode.


1

Cela dépend fortement de l'environnement dans lequel vous travaillez. Prenez par exemple le javascript. En javascript, la meilleure façon de transmettre des paramètres est d'utiliser des objets avec des paires clé / valeur, ce qui signifie en pratique que vous n'avez qu'un seul paramètre. Dans d'autres systèmes, le sweet spot sera à trois ou quatre.

En fin de compte, tout se résume à un goût personnel.


1

Je suis d'accord avec 3, ça va, 4 c'est trop comme guide. Avec plus de 3 paramètres, vous effectuez inévitablement plus d'une tâche. Plus d'une tâche doit être divisée en méthodes distinctes.

Cependant, si je regardais le dernier projet sur lequel j'ai travaillé, les exceptions seraient nombreuses et la plupart des cas seraient difficiles à ramener à 3 paramètres.


1

Si j'ai 7 à 10 paramètres dans une routine, je cherche à les regrouper dans une nouvelle classe, mais pas si cette classe ne serait rien d'autre qu'un tas de champs avec des getters et des setters - la nouvelle classe doit faire autre chose que de mélanger les valeurs dans et en dehors. Sinon, je préfère accepter la longue liste de paramètres.


1
Je vais le regrouper avec une classe de données uniquement s'il est utilisé à plusieurs endroits, mais même alors, je crée généralement les deux constructeurs.
Leahn Novash

1

C'est un fait connu que, en moyenne, les gens peuvent garder 7 +/- 2 choses dans leur tête à la fois. J'aime utiliser ce principe avec des paramètres. En supposant que les programmeurs sont tous des gens intelligents au-dessus de la moyenne, je dirais que tout 10+ est trop.

BTW, si les paramètres sont similaires en aucune façon, je les mettrais dans un vecteur ou une liste plutôt que dans une structure ou une classe.


1

Je baserais ma réponse sur la fréquence à laquelle la fonction est appelée.

Si c'est une fonction init qui n'est appelée qu'une seule fois, laissez-la prendre 10 parms ou plus, peu importe.

Si cela s'appelle un tas de fois par image, j'ai tendance à créer une structure et à lui passer un pointeur car cela a tendance à être plus rapide (en supposant que vous ne reconstruisez pas la structure à chaque fois également).


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.