Je suis confus sur les fonctions min et max, dans certains contextes.
Dans un contexte, lorsque vous utilisez les fonctions pour prendre la plus ou moins grande des deux valeurs, il n'y a pas de problème. Par exemple,
//how many autographed CD's can I give out?
int howManyAutographs(int CDs, int Cases, int Pens)
{
//if no pens, then I cannot sign any autographs
if (Pens == 0)
return 0;
//I cannot give away a CD without a case or a case without a CD
return min(CDs, Cases);
}
Facile. Mais dans un autre contexte, je suis confus. Si j'essaie de fixer un maximum ou un minimum, je le récupère à l'envers.
//return the sum, with a maximum of 255
int cappedSumWRONG(int x, int y)
{
return max(x + y, 255); //nope, this is wrong
}
//return the sum, with a maximum of 255
int cappedSumCORRECT(int x, int y)
{
return min(x + y, 255); //much better, but counter-intuitive to my mind
}
Est-il déconseillé de créer mes propres fonctions comme suit?
//return x, with a maximum of max
int maximize(int x, int max)
{
return min(x, max);
}
//return x, with a minimum of min
int minimize(int x, int min)
{
return max(x, min)
}
Évidemment, utiliser les fonctions intégrées sera plus rapide, mais cela me semble être une microoptimisation inutile. Y a-t-il une autre raison pour laquelle cela serait déconseillé? Qu'en est-il dans un projet de groupe?
design
functions
readability
Devsman
la source
la source
std::clamp
fonction ou quelque chose de similaire.up_to
(pourmin
) etat_least
(pourmax
)? Je pense qu'ils expriment mieux la signification queminimize
etc., bien qu'il faille peut-être un instant pour comprendre pourquoi ils sont commutatifs.min
etmax
et aussiminimize
etmaximize
sont des noms totalement faux pour les fonctions que vous voulez écrire. Le défautmin
etmax
font beaucoup plus de sens. Vous avez en réalité presque les bons noms de fonctions. Cette opération s'appelle serrage ou recouvrement et vous avez écrit deux fonctions de recouvrement. Je suggèrecapUpperBound
etcapLowBound
. Je n'ai pas à expliquer à qui que ce soit qui fait quoi, c'est évident.Réponses:
Comme d'autres l'ont déjà mentionné: ne créez pas une fonction avec un nom similaire à celui d'une fonction intégrée, d'une bibliothèque standard ou généralement utilisée, mais modifiez son comportement. Il est possible de s’habituer à une convention de nommage même si cela n’a pas beaucoup de sens pour vous au premier abord, mais il sera impossible de raisonner sur le fonctionnement de votre code une fois que vous aurez introduit les autres fonctions qui font la même chose leurs noms ont été échangés.
Au lieu de «surcharger» les noms utilisés par la bibliothèque standard, utilisez de nouveaux noms qui traduisent précisément ce que vous voulez dire. Dans votre cas, un «minimum» ne vous intéresse pas vraiment. Au contraire, vous voulez plafonner une valeur. Mathématiquement, il s’agit de la même opération mais sémantiquement, ce n’est pas tout à fait. Alors pourquoi pas juste une fonction
cela fait ce qui est nécessaire et le dit de son nom. (Vous pouvez également mettre
cap
en œuvre cemin
qui est indiqué dans la réponse de timster ).Un autre nom de fonction fréquemment utilisé est
clamp
. Il prend trois arguments et "bloque" une valeur fournie dans l'intervalle défini par les deux autres valeurs.Si vous utilisez un nom de fonction aussi connu, toute nouvelle personne rejoignant votre équipe (y compris l'avenir, vous reviendrez au code après un certain temps) comprendra rapidement ce qui se passe au lieu de vous maudire de les avoir confondues en les brisant. attentes concernant les noms de fonction qu’ils pensaient connaître.
la source
clamp
est largement utilisé dans tous les types de traitement du signal et d’opérations similaires (traitement d’image, etc.), c’est donc certainement ce que je voudrais aussi. Bien que je ne dirais pas que cela nécessite des limites supérieure et inférieure: je l’ai souvent vu dans une seule direction également.clamp
aussi. Et si c'est écrit correctement, vous pouvez simplement utiliser une borne d'infini / infini négatif lorsque vous ne voulez que le lien lié dans un sens. Par exemple, pour vous assurer qu'un nombre n'est pas supérieur à 255 (mais pas de limite inférieure), vous utiliseriezclamp(myNumber, -Infinity, 255)
.Si vous créez une fonction comme celle-ci, où
minimize(4, 10)
renvoie 10 , alors je dirais que c'est déconseillé, car vos collègues programmeurs risquent de vous étrangler.(D'accord, peut-être qu'ils ne vous étrangleront pas littéralement à mort, mais sérieusement ... Ne faites pas ça.)
la source
DO NOT
(sur "NE PAS broyer, plier ou mutiler"). Quelqu'un qui implémenterait quelque chose comme ça recevrait une carte.Il est correct d'aliaser une fonction, mais n'essayez pas de changer le sens des termes existants
C'est bien de créer un alias de la fonction - les bibliothèques communes le font tout le temps .
Cependant, il est déconseillé d’utiliser des termes d’une manière contraire à l’usage courant, comme dans votre exemple où inverser max et min devrait être dans votre esprit. C'est déroutant pour les autres programmeurs, et vous vous rendrez un mauvais service en vous entraînant à continuer à interpréter ces termes de manière non standard.
Donc, dans votre cas, abandonnez le langage "mininum / maximum" que vous trouvez déroutant et créez votre propre code, facile à comprendre.
Refactoring votre exemple:
En prime, chaque fois que vous regarderez ce code, vous vous rappellerez comment min et max sont utilisés dans votre langage de programmation. Cela finira par prendre un sens dans votre tête.
la source
min
etmax
qui confond le PO. C'est quandmin
est utilisé pour définir une limite supérieure fixe sur une valeur.get_lower_value
serait tout aussi contre-intuitif dans cette application. Si je devais choisir un autre nom pour cette opération, je l'appellerais supremum , bien que je ne sache pas combien de programmeurs le comprendraient immédiatement.supremum
de la fonctionget_lower_value
définie ci-dessus pour simplement appelermin
. Cela pose le même problème au programmeur suivant que l’appelermaximise
. Je suggérerais de l'appelerapply_upper_bound
, mais je ne suis pas sûr que ce soit parfait. Cela reste étrange car cela fonctionne de la même manière, quel que soit le paramètre que vous définissez, mais le nom implique que l’un des paramètres est "la valeur" et que l’autre est "la borne" et qu’ils sont en quelque sorte différents.J'aime cette question. Décomposons cependant.
1: Faut-il envelopper une seule ligne de code?
Oui, je peux penser à de nombreux exemples où vous pourriez faire cela. Peut-être appliquez-vous des paramètres typés ou cachez-vous une implémentation concrète derrière une interface. Dans votre exemple, vous masquez essentiellement un appel de méthode statique.
De plus, vous pouvez faire beaucoup de choses en une seule ligne ces jours-ci.
2: Les noms 'Min' et 'Max' sont-ils déroutants?
Oui! Ils sont totalement! Un gourou du code propre les renommerait "FunctionWhichReturnsTheLargestOfItsParameters" ou quelque chose du genre. Heureusement, nous avons la documentation et (si vous êtes chanceux) IntelliSense et des commentaires pour nous aider afin que toute personne déroutée par les noms puisse lire ce qu’ils sont censés faire.
3: Devriez-vous les renommer vous-même?
Ouais, allez-y. Par exemple, vous pourriez avoir:
Cela ajoute du sens et l'appelant n'a pas à savoir ou veut savoir comment calculer la valeur.
4: Devriez-vous renommer "min" en "maximiser"
Non!! êtes-vous fou?! Mais oui, la question souligne le fait que différentes personnes lisent différentes significations dans les noms de fonctions et d'objets. Ce qu'une personne trouve clair et conventionnel, une autre trouve opaque et déroutant. C'est pourquoi nous avons des commentaires. Vous devriez plutôt écrire:
Puis quand quelqu'un lit
ils savent que vous avez commis une erreur.
la source
FunctionWhichReturnsTheLargestOfItsParameters
sont une bonne chose, je ne veux pas en faire partie.FunctionWhichReturns
au premier plan de chaque fonction (cela ne déclenche pas d'exception ni ne se termine). Vous pourriez finir avecgetMinimum
,getLarger
(ougetLargest
avec plus de 2 entrées) si, en suivant des conseils concrets sur les lignes qui (a) des fonctions pures et / ou « apporteurs » doivent utiliser la verrueget
, (b) les mots anglais ne doivent pas être abrégé noms. Clairement, c'est trop verbeux pour ceux qui décident d'appeler de telles fonctionsmax
.Non . Ne faites pas de fonctions avec des noms très similaires aux fonctions intégrées, mais qui fait le contraire . Cela peut sembler intuitif pour vous, mais cela va être très déroutant pour les autres développeurs, et même pour vous-même, dans le futur, lorsque vous aurez plus d'expérience.
La signification de
max
est "le maximum de", mais votre compréhension "intuitive" est quelque chose comme "au maximum de". Mais ceci est simplement une mauvaise compréhension de la fonction, et changer le nom demax
enmaximum
ne communique pas votre interprétation différente. Même si vous croyez fermement que les concepteurs de langage ont commis une erreur, ne faites pas quelque chose comme ça.Mais changer le nom pour dire,
cap(x, limit)
comme cela a été suggéré, conviendrait, puisqu'il indique clairement l'intention, même si cela ne fait que concluremin
.la source
Ce qui peut vous dérouter, c'est soit d'utiliser Capped dans le nom de votre fonction, soit de comprendre ce que signifie placer un cap. C'est un limiteur et ne nécessite pas un maximum de rien.
Si on vous demande le plus petit, le plus petit ou le plus ancien, avez-vous le sentiment que Max est la fonction appropriée?
Laissez min et max seuls. Ecrivez des tests pour que vous puissiez au moins le corriger une deuxième fois.
Si vous devez autant utiliser ces fonctions dans votre projet, vous obtiendrez un indice qui vous aidera à préciser laquelle utiliser. Un peu comme <ou>, la partie large de la bouche fait face à la plus grande valeur.
la source
max
fonction est plus appropriée, mais la logiquemin
est ce qu'il recherche réellement.Pour répondre à votre question: existe-t-il une autre raison pour laquelle cela serait déconseillé? Qu'en est-il dans un projet de groupe? Il est logique que vous vouliez vos propres fonctions, ce qui ne pose aucun problème. Assurez-vous simplement qu'ils sont dans votre propre classe d'assistance et qu'ils ne sont pas facilement appelables pour les autres, à moins qu'ils ne l'importent. (Joes.Utilitaires.)
Mais pour revoir votre problème, je penserais plutôt:
Vous êtes confus parce que vous essayez d'appliquer votre logique cérébrale à ces fonctions min / max. Au lieu de cela, parlez simplement en anglais.
if
leinput
estgreater than or equal to 255
then
return 255
autrementreturn
leinput
.Lequel est:
Mon avis. Vous utilisez les fonctions max \ min pour les mauvaises raisons, la vitesse de ces opérations est négligeable. Faites ce qui a du sens.
la source
Bien que je comprenne votre problème, je serais réticent à le faire. Il serait préférable de simplement percer dans votre crâne ce que font min () et max ().
La plupart des programmeurs savent ce que font les fonctions min () et max () - même si, comme vous, ils ont parfois du mal à utiliser leur intuition à un moment donné. Si je lis un programme et que je vois max (x, y), je sais immédiatement ce qu'il fait. Si vous créez votre propre fonction "alias", toute personne lisant votre code ne saura pas ce que fait cet alias. Ils doivent trouver votre fonction. Cela interrompt inutilement la lecture et oblige le lecteur à réfléchir plus avant pour comprendre votre programme.
Si vous avez du mal à déterminer laquelle utiliser à un moment donné, ajoutez un commentaire pour l'expliquer. Ensuite, si un futur lecteur est aussi confus, votre commentaire devrait l’éclaircir. Ou si vous le faites mal mais que le commentaire explique ce que vous tentiez de faire, la personne qui tente de le déboguer aura un indice.
Une fois que vous appelez une fonction parce que le nom se heurte à votre intuition ... est-ce le seul cas où cela pose un problème? Ou allez-vous alias d'autres fonctions? Peut-être que vous êtes dérouté par "lire" et que vous trouvez plus facile de le considérer comme "accepter", vous changez "append" en "StringTogether", "round" en "DropDecimals", etc., etc. Portez ceci à une extrême ridicule. et vos programmes seront incompréhensibles.
En effet, il y a des années, j'ai travaillé avec un programmeur qui n'aimait pas toute la ponctuation en C. Il a donc écrit un tas de macros pour lui permettre d'écrire "THEN" au lieu de "{" et "END-IF" au lieu de "}" et des dizaines d'autres substitutions de ce type. Ainsi, lorsque vous avez essayé de lire ses programmes, cela ne ressemblait même plus à C, c'était comme si vous deviez apprendre une nouvelle langue. Je ne me souviens pas maintenant si "AND" a été traduit par "&" ou "&&" - et c'est le but. Vous sapez l'investissement que les gens ont fait pour apprendre la langue et la bibliothèque.
Cela dit, je ne dirais pas qu'une fonction qui ne fait rien mais appelle une fonction de bibliothèque standard est nécessairement mauvaise. Si le but de votre fonction n'est pas de créer un alias, mais d'encapsuler un comportement qui se trouve être une seule fonction, cela pourrait être bon et correct. Je veux dire, si logiquement et inévitablement vous devez faire un max à ce stade du programme, alors appelez directement max. Mais si vous devez effectuer des calculs qui exigent aujourd'hui un maximum, mais qui pourraient être modifiés à l'avenir pour faire autre chose, une fonction intermédiaire est appropriée.
la source
Il est possible de renommer des fonctions intégrées à condition que les nouveaux noms rendent votre code très clair et ne soient pas compris par personne. (Si vous utilisez C / C ++, n'utilisez pas #define car il est difficile de voir ce qui se passe.) Le nom d'une fonction doit agir comme un commentaire expliquant ce que fait le code d'appel et pourquoi il le fait. .
Vous n'êtes pas la seule personne à avoir eu ce problème avec min et max, mais je ne vois pas encore de bonne solution générale qui fonctionne dans tous les domaines. Je pense qu'un problème avec la dénomination de ces fonctions est que les deux arguments ont des significations logiques différentes, mais sont présentés comme signifiant la même chose.
Si votre langue le permet, vous pouvez essayer
la source
Non.
Vous n'écrivez pas vos enveloppes. Les noms de ces enveloppes ne sont pas très significatifs.
Ce que vous essayez de faire, c'est une obfuscation de code aimable. Vous inventez une couche supplémentaire qui sert 2 objectifs:
En cachant des choses avec lesquelles vous n'êtes pas à l'aise, vous ne faites que nuire à votre code maintenant et à vous-même à l'avenir. Vous ne pouvez pas grandir en restant dans votre zone de confort. Ce dont vous avez besoin est d'apprendre à travailler
min
et àmax
travailler.la source
C’est bien, et ce n’est pas vraiment contre-intuitif d’utiliser Min, Max pour céder le pas à la vitesse supérieure. Ceci est également fait en utilisant:
Dans le firmware, il remonte plus loin que MMX, qui est antérieur aux graphiques 3D modernes qui reposent sur cette extension.
Remplacer une fonction standard de l'industrie même localement m'inquiéterait, un nom dérivé peut être préférable. Les étudiants C ++ pourraient peut-être surcharger leur obscure classe.
la source
Il est très bien dans certains cas, mais pas dans votre exemple, parce qu'il ya de bien meilleures façons le libeller:
saturate
,clamp
,clip
, etc.la source
Je créerais plutôt une fonction générique nommée 'bounded'
ou avec l'utilisation de 'min' et 'max'
la source
Qu'en est-il d'appeler vos fonctions:
atmost(x,255)
: retourne le plus bas de x ou 255 au plus.atleast(10,x)
: retourne le plus haut de x ou au moins 10.la source
min(x+y, MAX_VALUE);
porterait beaucoup plus de sens quemyCustomFunction(x, y);
Donc, la réponse est OUI, c'est déconseillé . Il ne sert que d'alias à votre langage cérébral.
la source