One-liners vs lisibilité: quand arrêter de réduire le code? [fermé]


14

Le contexte

Je me suis récemment intéressé à produire un meilleur code formaté. Et mieux je veux dire "suivre des règles approuvées par suffisamment de gens pour le considérer comme une bonne pratique" (car il n'y aura jamais une "meilleure" façon unique de coder, bien sûr).

Ces jours-ci, je code principalement en Ruby, j'ai donc commencé à utiliser un linter (Rubocop) pour me fournir des informations sur la "qualité" de mon code (cette "qualité" étant définie par le projet de style communautaire ruby-guide-style ).

Notez que j'utiliserai la «qualité» comme dans la «qualité de la mise en forme», pas tant sur l'efficacité du code, même si dans certains cas, l'efficacité du code est en fait affectée par la façon dont le code est écrit.

Quoi qu'il en soit, en faisant tout cela, j'ai réalisé (ou du moins, je me suis souvenu) quelques choses:

  • Certains langages (notamment Python, Ruby et autres) permettent de créer de grandes lignes de code
  • Suivre certaines directives pour votre code peut le rendre beaucoup plus court et pourtant très clair
  • Pourtant, suivre ces directives trop strictement peut rendre le code moins clair / facile à lire
  • Le code peut respecter presque parfaitement certaines directives et être toujours de mauvaise qualité
  • La lisibilité du code est principalement subjective (comme dans "ce que je trouve clair peut être complètement obscur pour un collègue développeur")

Ce ne sont que des observations, pas des règles absolues bien sûr. Vous remarquerez également que la lisibilité du code et les directives suivantes peuvent sembler sans rapport à ce stade, mais ici, les directives sont un moyen de réduire le nombre de façons de réécrire un morceau de code.

Maintenant, quelques exemples, pour rendre tout cela plus clair.

Exemples

Prenons un cas d'utilisation simple: nous avons une application avec un Usermodèle " ". Un utilisateur a une adresse facultative firstnameet surnameobligatoire email.

Je veux écrire une méthode " name" qui retournera alors le nom ( firstname + surname) de l'utilisateur si au moins son firstnameou surnameest présent, ou sa emailvaleur de repli sinon.

Je veux aussi que cette méthode prenne un " use_email" comme paramètre (booléen), permettant d'utiliser l'email de l'utilisateur comme valeur de secours. Ce use_emailparamètre " " devrait par défaut (s'il n'est pas passé) comme " true".

La façon la plus simple d'écrire cela, en Ruby, serait:

def name(use_email = true)
 # If firstname and surname are both blank (empty string or undefined)
 # and we can use the email...
 if (firstname.blank? && surname.blank?) && use_email
  # ... then, return the email
  return email
 else
  # ... else, concatenate the firstname and surname...
  name = "#{firstname} #{surname}"
  # ... and return the result striped from leading and trailing spaces
  return name.strip
 end
end

Ce code est le moyen le plus simple et le plus facile à comprendre de le faire. Même pour quelqu'un qui ne "parle" pas Ruby.

Essayons maintenant de raccourcir cela:

def name(use_email = true)
 # 'if' condition is used as a guard clause instead of a conditional block
 return email if (firstname.blank? && surname.blank?) && use_email
 # Use of 'return' makes 'else' useless anyway
 name = "#{firstname} #{surname}"
 return name.strip
end

C'est plus court, toujours facile à comprendre, sinon plus facile (la clause de garde est plus naturelle à lire qu'un bloc conditionnel). La clause Guard la rend également plus conforme aux directives que j'utilise, donc gagnant-gagnant ici. Nous réduisons également le niveau de retrait.

Maintenant, utilisons un peu de magie Ruby pour le raccourcir encore:

def name(use_email = true)
 return email if (firstname.blank? && surname.blank?) && use_email
 # Ruby can return the last called value, making 'return' useless
 # and we can apply strip directly to our string, no need to store it
 "#{firstname} #{surname}".strip
end

Encore plus court et en suivant parfaitement les directives ... mais beaucoup moins clair car le manque de déclaration de retour le rend un peu déroutant pour ceux qui ne connaissent pas cette pratique.

C'est ici que nous pouvons commencer à poser la question: cela en vaut-il vraiment la peine? Faut-il dire "non, rendez-le lisible et ajoutez return" "(sachant que cela ne respectera pas les directives). Ou devrions-nous dire "ça va, c'est la façon Ruby, apprends la putain de langue!"?

Si nous prenons l'option B, alors pourquoi ne pas la raccourcir encore plus:

def name(use_email = true)
 (email if (firstname.blank? && surname.blank?) && use_email) || "#{firstname} #{surname}".strip
end

Le voici, le one-liner! Bien sûr, il est plus court ... ici nous profitons du fait que Ruby retournera une valeur ou l'autre en fonction de celle qui est définie (puisque l'email sera défini dans les mêmes conditions qu'auparavant).

On peut aussi l'écrire:

def name(use_email = true)
 (email if [firstname, surname].all?(&:blank?) && use_email) || "#{firstname} #{surname}".strip
end

C'est court, pas si difficile à lire (je veux dire, nous avons tous vu à quoi peut ressembler un laid), bon Ruby, il est conforme à la directive que j'utilise ... Mais quand même, par rapport à la première façon d'écrire ça, c'est beaucoup moins facile à lire et à comprendre. Nous pouvons également affirmer que cette ligne est trop longue (plus de 80 caractères).

Question

Quelques exemples de code peuvent montrer que le choix entre un code "pleine taille" et bon nombre de ses versions réduites (jusqu'au fameux one-liner) peut être difficile car, comme nous pouvons le voir, les one-liners ne sont pas si effrayants mais encore, rien ne battra le code "full-size" en termes de lisibilité ...

Voici donc la vraie question: où s'arrêter? Quand est court, assez court? Comment savoir quand le code devient "trop ​​court" et moins lisible (en gardant à l'esprit qu'il est assez subjectif)? Et encore plus: comment toujours coder en conséquence et éviter de mélanger des lignes simples avec des morceaux de code "pleine taille" quand j'en ai envie?

TL; DR

La principale question ici est la suivante: quand il s'agit de choisir entre un "morceau de code long mais clair, lisible et compréhensible" et un "puissant, plus court mais plus difficile à lire / comprendre", sachant que ces deux sont le top et le bas d'une échelle et pas les deux seules options: comment définir où est la frontière entre "assez clair" et "pas aussi clair qu'il devrait être"?

La question principale n'est pas le classique "One-liners vs lisibilité: lequel est le meilleur?" mais "Comment trouver l'équilibre entre ces deux?"

Modifier 1

Les commentaires dans les exemples de code sont censés être "ignorés", ils sont là pour clarifier ce qui se passe, mais ne doivent pas être pris en compte lors de l'évaluation de la lisibilité du code.


7
Trop court pour une réponse: continuez le refactoring itérativement jusqu'à ce que vous ne soyez pas sûr que ce soit mieux que l'itération précédente, puis arrêtez et inversez la dernière refactorisation.
Dom

8
Je préfère la variante 3 avec le returnmot - clé ajouté . Ces sept personnages ajoutent un peu de clarté à mes yeux.
cmaster

2
Si vous vous sentez vraiment horrible, vous pouvez écrire le tout comme [firstname,surname,!use_email].all?(&:blank?) ? email : "#{firstname} #{surname}".strip... car false.blank?retourne vrai et l'opérateur ternaire vous enregistre quelques caractères ... ¯ \ _ (ツ) _ / ¯
DaveMongoose

1
OK, je dois demander: quelle clarté le returnmot clé est-il censé ajouter?! Il ne fournit aucune information . C'est du fouillis pur.
Konrad Rudolph

2
La notion selon laquelle la brièveté engendre la clarté souffre non seulement de la loi des rendements décroissants, mais s'inverse lorsqu'elle est poussée à l'extrême. Si vous réécrivez pour raccourcir une fonction courte, vous perdez votre temps, et il en va de même pour essayer de justifier la pratique.
sdenham

Réponses:


26

Quel que soit le code que vous écrivez, la lisibilité est la meilleure. Court est le deuxième meilleur. Et lisible signifie généralement assez court pour que vous puissiez comprendre le code, les identificateurs bien nommés et adhérer aux idiomes communs de la langue dans laquelle le code est écrit.

Si cela était indépendant de la langue, je pense que ce serait certainement basé sur l'opinion, mais dans les limites de la langue Ruby, je pense que nous pouvons y répondre.

Tout d'abord, une fonctionnalité et une façon idiomatique d'écrire Ruby consiste à omettre le returnmot - clé lors du retour d'une valeur, à moins de revenir tôt à partir d'une méthode.

Une autre fonctionnalité et idiome combinés utilise des ifinstructions de fin pour augmenter la lisibilité du code. L'une des idées directrices de Ruby est d'écrire du code qui se lit comme un langage naturel. Pour cela, nous allons au Poignant Guide to Ruby de _why, chapitre 3 .

Lisez à haute voix ce qui suit.

5.times { print "Odelay!" }

Dans les phrases en anglais, la ponctuation (comme les points, les exclamations, les parenthèses) est silencieuse. La ponctuation ajoute du sens aux mots, aide à donner des indices sur ce que l'auteur entend par une phrase. Alors lisons ce qui précède: Cinq fois, imprimez «Odelay!».

Compte tenu de cela, l'exemple de code # 3 est le plus idiomatique pour Ruby:

def name(use_email = true)
  return email if firstname.blank? && surname.blank? && use_email

  "#{firstname} #{surname}".strip
end

Maintenant, quand nous lisons le code, il dit:

Renvoyez l'e-mail si le prénom est vide et le nom de famille est vide et utilisez l'e-mail

(retour) prénom et nom de famille supprimés

Ce qui est sacrément proche du code Ruby actuel.

Il ne s'agit que de 2 lignes de code réel, il est donc assez concis et adhère aux idiomes du langage.


Joli point. Il est vrai que la question n'était pas censée être centrée sur Ruby, mais je suis d'accord qu'il n'est pas possible d'avoir ici une réponse indépendante de la langue.
Sudiukil

8
Je trouve l'idée de faire sonner le code comme un langage naturel largement surestimée (et parfois même problématique). Mais même sans cette motivation, j'arrive à la même conclusion que cette réponse.
Konrad Rudolph

1
Il y a un autre ajustement que je voudrais apporter au code. C'est-à-dire, mettre use_emailavant les autres conditions car c'est une variable plutôt qu'un appel de fonction. Mais là encore, l'interpolation de chaîne submerge la différence de toute façon.
John Dvorak

Structurer le code en suivant les structures du langage naturel peut vous faire tomber dans les pièges linguistiques. Par exemple, lorsque vous lisez les exigences do send an email if A, B, C but no Dsuivantes, suivre votre prémisse serait naturel de taper 2 blocs if / else , ce qui serait probablement plus facile à coder if not D, send an email. Soyez prudent au moment de lire le langage naturel et transformez-le en code car cela peut vous faire écrire une nouvelle version de "l'histoire sans fin" . Avec des classes, des méthodes et des variables. Ce n'est pas grave après tout.
Laiv

@Laiv: Rendre le code lu comme un langage naturel ne signifie pas traduire littéralement les exigences. Cela signifie écrire du code afin que, lu à haute voix, il permette au lecteur de comprendre la logique sans lire chaque bit de code, caractère pour caractère, construction de langage pour construction de langage. Si le codage if !Dest meilleur, c'est bien aussi london qu'un Dnom significatif. Et si l' !opérateur se perd parmi les autres codes, alors avoir un identifiant appelé NotDserait approprié.
Greg Burghardt

15

Je ne pense pas que vous obtiendrez une meilleure réponse que "utilisez votre meilleur jugement". En bref, vous devez viser la clarté plutôt que la brièveté . Souvent, le code le plus court est également le plus clair, mais si vous vous concentrez uniquement sur la réalisation de la brièveté, la clarté peut en souffrir. C'est clairement le cas dans les deux derniers exemples, ce qui nécessite plus d'efforts pour comprendre que les trois exemples précédents.

Une considération importante est l'audience du code. La lisibilité dépend bien sûr totalement de la personne qui lit. Les personnes que vous attendez de lire le code (à côté de vous) connaissent-elles réellement les idiomes du langage Ruby? Eh bien, cette question n'est pas quelque chose que les gens au hasard sur Internet peuvent répondre, c'est seulement votre propre décision.


Je suis d'accord avec le point d'audience, mais cela fait partie de ma lutte: comme mon logiciel est souvent open-source, le public peut être composé de débutants ainsi que de "Ruby gods". Je pourrais rester simple pour le rendre accessible à la plupart des gens, mais cela ressemble un peu au gaspillage des avantages offerts par la langue.
Sudiukil

1
En tant que personne qui a dû reprendre, étendre et maintenir un code vraiment horrible, la clarté doit gagner. Rappelez-vous le vieil adage - Écrivez votre code comme si le responsable est un Hell's Angel vengeur qui sait où vous vivez et où vos enfants vont à l'école.
u

2
@Sudiukil: C'est un point important. Je vous suggère de vous efforcer d'obtenir du code idiomatique dans ce cas (c'est-à-dire de supposer une bonne connaissance de la langue), car il est peu probable que les débutants contribuent de toute façon au code open source. (Ou s'ils le font, ils seront prêts à faire l'effort d'apprendre la langue.)
JacquesB

7

Une partie du problème ici est «ce qu'est la lisibilité». Pour moi, je regarde votre premier exemple de code:

def name(use_email = true)
 # If firstname and surname are both blank (empty string or undefined)
 # and we can use the email...
 if (firstname.blank? && surname.blank?) && use_email
  # ... then, return the email
  return email
 else
  # ... else, concatenate the firstname and surname...
  name = "#{firstname} #{surname}"
  # ... and return the result striped from leading and trailing spaces
  return name.strip
 end
end

Et j'ai du mal à lire car il est plein de commentaires "bruyants" qui ne font que répéter le code. Retirez-les:

def name(use_email = true)
 if (firstname.blank? && surname.blank?) && use_email
  return email
 else
  name = "#{firstname} #{surname}"
  return name.strip
 end
end

et c'est maintenant beaucoup plus lisible. En le lisant ensuite, je pense "hmm, je me demande si Ruby supporte l'opérateur ternaire? En C #, je peux l'écrire comme:

string Name(bool useEmail = true) => 
    firstName.Blank() && surname.Blank() && useEmail 
    ? email 
    : $"{firstname} {surname}".Strip();

Est-ce que quelque chose comme ça est possible en rubis? En parcourant votre message, je vois qu'il y a:

def name(use_email = true)
 (email if (firstname.blank? && surname.blank?) && use_email) || "#{firstname} #{surname}".strip
end

Toutes les bonnes choses. Mais ce n'est pas lisible pour moi; tout simplement parce que je dois faire défiler pour voir toute la ligne. Corrigeons donc cela:

def name(use_email = true)
 (email if (firstname.blank? && surname.blank?) && use_email) 
 || "#{firstname} #{surname}".strip
end

Maintenant je suis content. Je ne suis pas complètement sûr du fonctionnement de la syntaxe, mais je peux comprendre ce que fait le code.

Mais c'est juste moi. D'autres personnes ont des idées très différentes sur ce qui fait un morceau de code agréable à lire. Vous devez donc connaître votre public lors de l'écriture de code. Si vous êtes un débutant absolu, vous voudrez rester simple et éventuellement l'écrire comme votre premier exemple. Si vous travaillez parmi un ensemble de développeurs professionnels avec de nombreuses années d'expérience ruby, écrivez du code qui tire parti du langage et restez court. Si c'est quelque part entre les deux, visez quelque part entre les deux.

Une chose que je dirais cependant: méfiez-vous du "code intelligent", comme dans votre dernier exemple. Demandez-vous, [firstname, surname].all?(&:blank?)ajoute-t-il autre chose que de vous faire sentir intelligent parce que cela montre vos compétences, même si c'est maintenant un peu plus difficile à lire? Je dirais que cet exemple est probablement complet dans cette catégorie. Si vous compariez cinq valeurs, je le verrais comme un bon code. Encore une fois, il n'y a pas de ligne absolue ici, gardez juste à l'esprit d'être trop intelligent.

Donc, en résumé: la lisibilité nécessite que vous connaissiez votre public et cibliez votre code en conséquence et que vous écriviez un code succinct mais clair; n'écrivez jamais de code "intelligent". Soyez bref, mais pas trop court.


2
Eh bien, j'ai oublié de le mentionner, mais les commentaires étaient censés être "ignorés", ils ne sont là que pour aider ceux qui ne connaissent pas bien Ruby. Point valable cependant sur le public, je n'y ai pas pensé. Quant à la version qui vous fait plaisir: si c'est la longueur de ligne qui compte, la troisième version de mon code (celle avec une seule déclaration de retour) fait un peu ça et est encore un peu plus compréhensible, non?
Sudiukil

1
@Sudiukil, n'étant pas un développeur ruby, j'ai trouvé que le plus difficile à lire et qu'il ne correspondait pas à ce que je cherchais (du point de vue d'une autre langue) comme la "meilleure" solution. Cependant, pour quelqu'un qui connaît le fait que ruby ​​est l'une de ces langues qui renvoie la valeur de la dernière expression, il représente probablement la version la plus simple et la plus facile à lire. Encore une fois, tout tourne autour de votre public.
David Arno

Pas un développeur Ruby, mais cela a beaucoup plus de sens pour moi que la réponse la plus votée, qui se lit comme "Voici ce que je vais retourner [note de bas de page: sous une condition longue spécifique]. En outre, voici une chaîne qui est arrivée en retard à la fête." La logique qui n'est essentiellement qu'une déclaration de cas doit être écrite comme une seule déclaration de cas uniforme, et non pas répartie sur plusieurs déclarations apparemment sans rapport.
Paul

Personnellement, j'irais avec votre deuxième bloc de code, sauf que je combinerais les deux déclarations dans votre branche else en une seule:return "#{firstname} #{surname}".strip
Paul

2

C'est probablement une question où il est difficile de ne pas donner de réponse basée sur une opinion, mais voici mes deux cents.

Si vous trouvez que raccourcir le code n'a pas d'impact sur la lisibilité, ni même l'améliore, allez-y. Si le code devient moins lisible, vous devez vous demander s'il existe une assez bonne raison de le laisser ainsi. Le faire simplement parce qu'il est plus court, ou cool, ou simplement parce que vous le pouvez, sont des exemples de mauvaises raisons. Vous devez également vous demander si le raccourcissement du code le rendrait moins compréhensible pour les autres personnes avec lesquelles vous travaillez.

Quelle serait donc une bonne raison? C'est vraiment un jugement, mais un exemple pourrait être quelque chose comme une optimisation des performances (après des tests de performances, bien sûr, pas à l'avance). Quelque chose qui vous procure un avantage que vous êtes prêt à payer avec une lisibilité réduite. Dans ce cas, vous pouvez atténuer l'inconvénient en fournissant un commentaire utile (qui explique ce que fait le code et pourquoi il a dû être rendu un peu cryptique). Encore mieux, vous pouvez extraire ce code dans une fonction distincte avec un nom significatif, de sorte que ce soit juste une ligne sur le site d'appel qui explique ce qui se passe (via le nom de la fonction) sans entrer dans les détails (cependant, les gens ont des différences opinions à ce sujet, c'est donc un autre jugement que vous devez faire).


1

La réponse est un peu subjective, mais vous devez vous demander avec toute l'honnêteté que vous pouvez rassembler, si vous pouviez comprendre ce code lorsque vous y reviendriez dans un mois ou deux.

Chaque changement devrait améliorer la capacité de la personne moyenne à comprendre le code. Pour rendre le code compréhensible, il est utile d'utiliser les directives suivantes:

  • Respectez les idiomes de la langue . C #, Java, Ruby, Python ont tous leurs façons préférées de faire la même chose. Les constructions idiomatiques aident à comprendre le code que vous ne connaissez pas.
  • Arrêtez-vous lorsque votre code devient moins lisible . Dans l'exemple que vous avez fourni, cela s'est produit lorsque vous avez atteint vos dernières paires de code de réduction. Vous avez perdu l'avantage idiomatique de l'exemple précédent et introduit de nombreux symboles qui nécessitent beaucoup de réflexion pour vraiment comprendre ce qui se passe.
  • N'utilisez des commentaires que lorsque vous devez justifier quelque chose d'inattendu . Je sais que vos exemples étaient là pour expliquer des constructions à des gens moins familiers avec Ruby, et c'est OK pour une question. Je préfère utiliser des commentaires pour expliquer des règles commerciales inattendues et les éviter si le code peut parler de lui-même.

Cela dit, il y a des moments où le code étendu aide à mieux comprendre ce qui se passe. Un exemple avec cela vient de C # et LINQ. LINQ est un excellent outil et peut améliorer la lisibilité dans certaines situations, mais j'ai également rencontré un certain nombre de situations où il était beaucoup plus déroutant. J'ai eu des commentaires lors de l'examen par les pairs qui ont suggéré de transformer l'expression en une boucle avec des instructions if appropriées afin que d'autres puissent mieux la maintenir. Quand j'ai obéi, ils avaient raison. Techniquement, LINQ est plus idiomatique pour C #, mais il y a des cas où il dégrade la compréhensibilité et une solution plus verbeuse l'améliore.

Je dis tout ça pour dire ceci:

Améliorez lorsque vous pouvez améliorer votre code (plus compréhensible)

N'oubliez pas que vous ou quelqu'un comme vous devrez conserver ce code plus tard. La prochaine fois que vous rencontrerez, cela pourrait prendre des mois. Rendez-vous service et ne poursuivez pas la réduction du nombre de lignes au détriment de la compréhension de votre code.


0

La lisibilité est une propriété que vous souhaitez avoir, ce n'est pas le cas de la présence de plusieurs lignes . Donc, plutôt que "one-liners vs readability", la question devrait être:

Quand les monolignes augmentent-ils la lisibilité et quand la nuisent-ils?

Je pense que les monolignes sont bonnes pour la lisibilité lorsqu'elles remplissent ces deux conditions:

  1. Ils sont trop spécifiques pour être extraits d'une fonction.
  2. Vous ne voulez pas interrompre le "flux" de lecture du code environnant.

Par exemple, disons que ce namen'était pas un bon ... nom pour votre méthode. Que combiner le prénom et le nom de famille, ou utiliser l'e-mail à la place du nom, n'était pas naturel. Donc, au lieu de namela meilleure chose que vous pourriez trouver, cela s'est avéré long et lourd:

puts "Name: #{user.email_if_there_is_no_name_otherwise_use_firstname_and_surname(use_email)}"

Un nom aussi long indique que c'est très spécifique - s'il était plus général, vous auriez pu trouver un nom plus général. Donc, l'envelopper dans une méthode n'aide ni à la lisibilité (c'est trop long) ni à DRYness (trop spécifique pour être utilisé ailleurs), il est donc préférable de simplement laisser le code là-dedans.

Pourtant - pourquoi en faire une doublure? Ils sont généralement moins lisibles que le code multiligne. C'est là que nous devons vérifier ma deuxième condition - le flux du code environnant. Et si vous avez quelque chose comme ça:

puts "Group: #{user.group}"
puts "Title: #{user.title}"
if user.firstname.blank? && user.surname.blank?) && use_email
  name = email
else
  name = "#{firstname} #{surname}"
  name.strip
end
puts "Name: #{name}"
puts "Age: #{user.age}"
puts "Address: #{user.address}"

Le code multiligne lui-même est lisible - mais lorsque vous essayez de lire le code environnant (en imprimant les différents champs), cette construction multiligne interrompt le flux. C'est plus facile à lire:

puts "Group: #{user.group}"
puts "Title: #{user.title}"
puts "Name: #{(email if (user.firstname.blank? && user.surname.blank?) && use_email) || "#{user.firstname} #{user.surname}".strip}"
puts "Age: #{user.age}"
puts "Address: #{user.address}"

Votre flux n'est pas interrompu et vous pouvez vous concentrer sur l'expression spécifique si vous en avez besoin.

Est-ce votre cas? Définitivement pas!

La première condition est moins pertinente - vous l'avez déjà jugée suffisamment générale pour mériter une méthode, et vous avez trouvé un nom pour cette méthode qui est beaucoup plus lisible que son implémentation. De toute évidence, vous ne l'extrayeriez plus dans une fonction.

Quant à la deuxième condition - interrompt-elle le flux du code environnant? Non! Le code qui l'entoure est une déclaration de méthode, que choisir le nameest son seul but. La logique de choisir le nom n'interrompt pas le flux du code environnant - c'est le but même du code environnant!

Conclusion - ne faites pas de l'ensemble du corps de fonction une ligne

Les lignes simples sont bonnes lorsque vous voulez faire quelque chose d'un peu complexe sans interrompre le flux. Une déclaration de fonction interrompt déjà le flux (de sorte qu'elle ne sera pas interrompue lorsque vous appelez cette fonction), ce qui fait que le corps de la fonction dans son intégralité n'aide pas la lisibilité.

Remarque

Je fais référence aux fonctions et méthodes "complètes" - pas aux fonctions en ligne ou aux expressions lambda qui font généralement partie du code environnant et doivent s'adapter à son flux.

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.