Des switch-case plus jolis

Article original : Prettier switch-cases | Belay the C++ (belaycpp.com)
Traductrice : Chlo√© Lourseyre

J’ai appris cette syntaxe au cours d’une pr√©sentation de la CppCon de 2021, donn√©e par Herb Sutter : Extending and Simplifying C++: Thoughts on Pattern Matching using `is` and `as` – Herb Sutter – YouTube. On peut aussi retrouver sa pr√©sentation sur son blog : Sutter‚Äôs Mill ‚Äď Herb Sutter on software development.

Contexte

Mettons que vous ayez un bloc switch-case sans plongeon1 (c’est important), comme ceci) :

enum class Foo {
    Alpha,
    Beta,
    Gamma,
};
 
int main()
{
    std::string s;
    Foo f;
 
    // ...
    // Do things with s and f 
    // ...
 
    switch (f)
    {
        case Foo::Alpha:
            s += "is nothing";
            break;
        case Foo::Beta:
            s += "is important";
            f = Foo::Gamma;
            break;
        case Foo::Gamma:
            s += "is very important";
            f = Foo::Alpha;
    }
     
    // ...
}

Rien de particuli√®rement compliqu√© ici : on ajoute un suffixe √† la cha√ģne en fonction de la valeur de f, parfois en modifiant f au passage.

Maintenant, mettons qu’on ajoute un litt√©ral Delta √† l’√©num√©ration Foo, qui fait exactement la m√™me chose que Gamma avec une petite diff√©rence dans la cha√ģne. Il y a une bonne chance pour qu’on √©crive ceci :

enum class Foo {
    Alpha,
    Beta,
    Gamma,
    Delta,
};
 
int main()
{
    std::string s;
    Foo f;
 
    // ...
    // Do things with s and f 
    // ...
 
    switch (f)
    {
        case Foo::Alpha:
            s += "is nothing";
            break;
        case Foo::Beta:
            s += "is important";
            f = Foo::Alpha;
            break;
        case Foo::Gamma:
            s += "is very important";
            f = Foo::Alpha;
        case Foo::Delta:
            s += "is not very important";
            f = Foo::Alpha;
    }
 
    // ...
}

Le nouveau bloc case est certainement du copier-coller. Mais avez-vous remarqu√© le bug qui s’est introduit ?

Comme dans premi√®re version, le d√©veloppeur n’a pas jug√© n√©cessaire de rajouter un break √† la fin du bloc Gamma (puisque c’√©tait le dernier √©l√©ment), quand on a copi√©-coll√© ce bloc on l’a laiss√© sans break. Du coup, quand on va passer dans le code de Gamma, on va toujours plonger dans le code de Delta.

Nouvelle syntaxe

La syntaxe présentée dans cet article permet (entre autre) de rendre ce genre de fautes moins fréquent, et de faire en sorte que le code soit un peu plus clair.

La voici :

switch (f)
{
    break; case Foo::Alpha:
        s += "is nothing";
    break; case Foo::Beta:
        s += "is important";
        f = Foo::Alpha;
    break; case Foo::Gamma:
        s += "is very important";
        f = Foo::Alpha;
    break; case Foo::Delta:
        s += "is not very important";
        f = Foo::Alpha;
}

Cela consiste √† mettre l’instruction break; juste avant chaque case.

Cela peut sembler √©trange au premier regard, car le tout premier break est inutile et il n’y en a pas √† la fin, mais cette syntaxe est fonctionnelle et surtout confortable.

En effet, si vous commencez tous vos blocs avec un break; case XXX:, vous êtes garantis de ne jamais faire de plongeon, même avec des hordes de copier-coller.

Avantages

Le premier avantage est celui d’√©viter le genre de bug que j’ai mentionn√© plus haut, o√Ļ on oublie un break ce qui cause un plongeon ind√©sirable. Et m√™me si vous ne faites pas de copier-coller, l’oubli du break sera visuellement √©vident puisque votre case ne sera pas align√© avec les autres.

Mais le r√©el avantage (d’apr√®s moi) est que cette syntaxe est, dans sa globalit√©, visuellement plus agr√©able. Pour chaque case, on √©conomise une ligne de code (o√Ļ devrait √™tre le break; normalement), et il sera √©vident pour quiconque regarde le code que ce switch-case ne contient aucun plongeon.

Bien s√Ľr, la beaut√© est subjective, y compris en programmation2. Cependant, des choses comme un meilleur alignement, des intentions plus claires et l’√©conomie de lignes3 sont, il me semble, des crit√®res plut√īt objectifs.

Avertissement

La premi√®re fois que j’ai vu cette syntaxe, j’ai rapidement compris son fonctionnement et son int√©r√™t. Je sais ceci dit qu’il y a plusieurs personnes qui ont d√Ľ se les faire expliquer.

Mais c’est presque toujours le cas quand on introduit une nouvelle syntaxe.

Gardez-donc √† l’esprit que si vous voulez l’utiliser dans un code partag√©, elle risque d’embrouiller vos coll√®gues. Soyez-s√Ľr¬∑e de bien l’expliquer (que ce soit en personne ou en commentaire) pour qu’elle soit rapidement prise en main.

En conclusion

√áa ne va certainement pas changer votre vie quotidienne ni m√™me votre vision du C++, mais je voulais la partager, car je l’aime beaucoup.

C’est une brique de plus dans la construction d’un code plus agr√©able √† lire.

Merci de votre attention et à la semaine prochaine !

Article original : Prettier switch-cases | Belay the C++ (belaycpp.com)
Traductrice : Chlo√© Lourseyre

Addendum

Notes

  1. Le terme ¬ę¬†plongeon¬†¬Ľ est utilis√© ici comme traduction de ¬ę¬†fallthrough¬†¬Ľ en anglais, qui dans le contexte d’un switch-case renvoie au fait qu’on peut se dispenser du mot-cl√© break pour qu’un bloc case ¬ę¬†plonge¬†¬Ľ dans un autre, comme dans l’exemple suivant :
switch (a)
{
    case 0:
        ++b; // Dans le cas o√Ļ a == 0, on fait ++b puis on plonge dans le cas 1
    case 1:
        ++b;
        break; // Ici il y a un break, donc on ne plonge pas dans le cas par défaut
    default:
        --b;
}
  1. Surtout en programmation, oserai-je même dire.
  2. L'¬†¬Ľ√©conomie de lignes¬†¬Ľ n’est une bonne chose que lorsqu’elle d√©fausse des expressions peu instructives, comme c’est le cas avec une ligne qui contient uniquement l’instruction break;. Jamais vous ne m’entendrez dire que les gros one-liners sont pr√©f√©rables √† un code plus d√©taill√©s (parce qu’ils ne le sont tout simplement pas). R√©unir le break et le case laisse le code respirer. De plus, vous pouvez toujours laisser une ligne vide √† l’endroit o√Ļ √©tait le break auparavant — votre code n’en sera que plus agr√©able.

Laisser un commentaire