La lisibilité est-elle une raison valable pour ne pas utiliser const dans les paramètres (de référence)?

24

Lors de l'écriture de certaines fonctions, j'ai trouvé un mot clé const dans des paramètres comme celui-ci:

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

provoque souvent le fractionnement d'une ligne en 2 lignes dans IDE ou vim, donc je veux supprimer tous les mots clés const dans les paramètres:

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

est-ce une raison valable pour ne pas utiliser const? Peut-on maintenir les objets paramètres inchangés manuellement?

ggrr
la source
110
"Hé, je veux changer fonctionnellement mon programme" pour le rendre plus lisible est une mauvaise mauvaise raison.
Pieter B
37
Le programme ne devient pas plus lisible de toute façon - Une fois que vous voyez quelque chose être remis car constvous avez un indice fort que vous n'avez pas besoin de vous soucier de la façon dont il pourrait être changé dans la fonction.
tofro
43
Une meilleure façon d'améliorer la lisibilité consiste à réduire le nombre d'arguments.
5gon12eder
15
'const' améliore sans doute la lisibilité. Cette déclaration indique clairement que obj ne peut pas changer!
Charles
14
Ce qui aiderait la lisibilité est d'ajouter un espace après chaque virgule.
sam hocevar

Réponses:

182

La lisibilité est une raison valable pour apprendre à utiliser les espaces blancs:

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

Situés là-bas, les paramètres ne seront pas confondus avec le corps de la fonction. En les localisant sur une ligne différente, vous n'aurez pas à les repositionner lorsque vous changez le nom de myFunctionen quelque chose de plus descriptif. Ne pas modifier la position des paramètres lorsqu'ils n'ont pas changé est quelque chose que les utilisateurs de l'outil de contrôle de source apprécieront.

constsignifie quelque chose. Ne le jetez pas simplement parce que vous manquez d'espace et d'idées. La lisibilité est primordiale, mais casser des choses en son nom est simplement abandonner.

candied_orange
la source
6
"vous n'aurez pas à les repositionner lorsque vous changez le nom de myFunction" - bien que dans ce cas, il semble qu'ils aient été positionnés pour s'aligner approximativement avec l'ouverture (, et si c'est le cas, vous devrez peut-être repositionner les si la longueur du nom de la classe + fonction change de plus de 4 caractères environ. Donc, si vous ne voulez pas avoir à le faire, ajoutez un nombre fixe de niveaux d'indentation, pas un nombre qui dépend de la longueur du nom de la fonction. Je recommanderais 1 niveau, cette réponse utilise 6, mais tout nombre fixe atteint l'objectif déclaré :-)
Steve Jessop
6
@CandiedOrange Je suis surpris que vous n'ayez pas utilisé "forme 6" dans cette réponse ... c'est clairement moins moche!
svidgen
6
Formulaire 6 pour la victoire. Un espace de tabulation pour un niveau d'indentation. Simple et efficace. Problème résolu :)
Courses de légèreté avec Monica
2
Ok ok forme 6 c'est. C'est la variante mentionnée par JeffGrigg sur c2.
candied_orange
4
@ random832 Je pense que nous sommes maintenant fermement sur le territoire du garage à vélos. Voici la bonne façon de résoudre ce problème: recherchez des exemples dans votre base de code, consultez le guide de style de votre boutique, demandez aux développeurs de votre boutique, et si rien de tout cela ne donne une réponse faisant autorité, utilisez-le. Résolvez les différends qui pourraient aller dans les deux sens avec un quart. Une fois le trimestre prononcé, soyez cohérent!
candied_orange
52

En fait, le problème de lisibilité va certainement dans l'autre sens. Tout d'abord, vous pouvez résoudre trivialement votre run-on line en utilisant des espaces . Mais la suppression constne fait pas que raccourcir la ligne, elle change complètement la signification du programme.

Herb Sutter fait référence à la constréférence constcomme étant la plus importanteconst car une référence à constpeut se lier à un temporaire et prolonger sa durée de vie. Une référence lvalue à non- constne peut pas, vous avez besoin d'une variable distincte.

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

Cela signifie pour la convivialité que vous devrez introduire toutes ces variables temporaires juste pour pouvoir appeler votre fonction. Ce n'est pas génial pour la lisibilité, car ces variables n'ont pas de sens et n'existent que parce que votre signature est incorrecte.

Barry
la source
6
Votre deuxième paragraphe me donne des maux de tête en essayant de comprendre si constse réfère à constou à l'autre constet ce qui constest en effet le plus importantconst
Mindwin
3
@Mindwin Je pense que l'ironie est que mon deuxième paragraphe est clair et sans ambiguïté, et je n'ai aucune idée de quoi vous parlez.
Barry
2
@Barry C'est certainement sans ambiguïté, mais il m'a fallu quelques lectures de ce paragraphe pour essayer de comprendre ce que cela signifiait. Je pense qu'une partie du problème est qu'il peut être analysé "Herb Sutter fait référence au const (en référence à const) comme le plus important const ..." ou "Herb Sutter fait référence à const in (référence à const) comme le plus important const ... "Je crois que ce dernier est le seul regroupement valide des mots, mais il faut un peu de temps pour le traiter. Peut-être existe-t-il un moyen d'utiliser des guillemets pour lever l'ambiguïté?
Cort Ammon - Reinstate Monica
1
Je pense que certains composés coupés pourraient éclaircir ce point.
shawnt00
2
ou spécifiquement utiliser const&plutôt que faire référence à constun nom (-phrase) là
Caleth
21

La réponse simple est "non".

La réponse longue est que le constmot-clé fait partie du contrat proposé par la fonction; il vous indique que l'argument ne sera pas modifié. Dès que vous retirez la constgarantie, celle-ci disparaît. Rappelez -vous que vous ne pouvez pas maintenir raisonnablement constness (ou toute autre propriété) de quelque chose grâce à une documentation, conventions ou directives - si le constness est pas appliquée par le compilateur, quelqu'un va penser qu'ils peuvent rendre leur travail plus facile si elles tripoter le paramètre "juste un peu". Considérer:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

Outre le fait que cette dernière version est plus concise, elle fournit également un contrat plus solide et permet au compilateur de vous aider à maintenir vos intentions. Le premier ne fait rien pour empêcher la fna(Foo&)fonction de modifier le paramètre que vous lui passez.

Comme dans la réponse @CandiedOrange, vous pouvez utiliser des espaces pour disposer le code et améliorer la lisibilité.

Mael
la source
14

La suppression du constmot clé supprime la lisibilité car constcommunique des informations au lecteur et au compilateur.
Réduire la longueur horizontale du code est bien (personne n'aime faire défiler latéralement) mais il y a plus constque du texte. Vous pouvez le réécrire:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

Ce qui ne change pas le contrat mais répond au besoin de réduire la longueur de ligne. Vraiment, je considérerais l'extrait ci-dessus comme moins lisible et opterais pour l'utilisation de plus d'espace comme déjà mentionné dans la réponse de CandiedOrange.

constest une fonctionnalité du code lui-même. Vous ne feriez pas de la fonction un non-membre pour supprimer la MyClass::section de la déclaration, alors ne supprimez pas leconst

Erdrik Ironrose
la source
4
J'accepte que l'extrait que vous fournissez soit moins lisible. Cela oblige le lecteur à aller découvrir ce qui est MObjet ce qui strsoulève certainement les sourcils. Il est particulièrement étrange pour les types dont les noms que vous avez déjà le contrôle sur: Par exemple , pourquoi ne pas vous nommer que MyObjectcomme MObjpour commencer?
Jason C
3

La lisibilité est-elle une raison valable pour ne pas utiliser const dans les paramètres?

Non. L'omission constpeut modifier les fonctionnalités, perdre les protections constet peut potentiellement créer du code moins efficace.

Peut-on maintenir les objets paramètres inchangés manuellement?

Plutôt que de passer du temps à formater manuellement le code

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

Utilisez des outils de formatage automatique . Écrivez la fonction selon ses exigences fonctionnelles et laissez la mise en forme automatique gérer la présentation. L'ajustement manuel de la mise en forme n'est pas aussi efficace que l'utilisation de la mise en forme automatique et l'utilisation du temps gagné pour améliorer d'autres aspects du code.

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}
chux - Réintégrer Monica
la source
-1

Aussi longtemps que possible, il est préférable de garder const visible. Cela améliore beaucoup la maintenance du code (pas de supposition pour voir si cette méthode modifie mes arguments).

Si je vois beaucoup d'arguments dans une méthode, cela m'oblige à envisager la création d'un jaron basé sur un projet (Matrice, Employé, Rectangle, Compte) qui serait beaucoup plus court, plus facile à comprendre (élimine la longue liste d'arguments des méthodes).

Stylo noir
la source
D'accord. J'hésitais à le signaler. Ainsi, "cas extrême".
blackpen
@cmaster Cela dit, parfois dans certains contextes, avec certains programmeurs, cela peut rester lisible. Par exemple, dans le cas très spécifique d'un programme jusque dans les appels de l'API Windows, avec un lecteur qui est habitué à cet environnement, des choses comme par exemple typedef Point * LPPOINTet typedef const Point * LPCPOINT, bien que super désagréables, ont toujours une signification implicite, car elles sont conformes aux attentes immédiates Dans le contexte. Mais jamais dans le cas général; c'est juste une exception bizarre à laquelle je peux penser.
Jason C
1
Oui, quand j'ai vu la question, "const unsigned long long int" m'est venu à l'esprit, mais ce n'est pas un bon candidat pour tirer profit d'être "const" ou "référence". Le typedef résout le problème général du raccourcissement des noms; mais cela ne semble pas être une bonne conception pour cacher le but même des constructions de langage (comme "const") derrière.
blackpen