Faire face à la soupe aux accolades

11

J'ai programmé à la fois en C # et en VB.NET pendant des années, mais principalement en VB. Je fais un changement de carrière vers C # et, dans l'ensemble, j'aime mieux C #.

Un problème que j'ai, cependant, est la soupe aux accolades. Dans VB, chaque mot-clé de structure a un mot-clé de fermeture correspondant, par exemple:

Namespace ...
    Class ...
        Function ...
            For ...
                Using ...
                    If ...
                        ...
                    End If
                    If ...
                        ...
                    End If
                End Using
            Next
        End Function
    End Class
End Namespace

Le même code écrit en C # se révèle très difficile à lire:

namespace ... {
    class ... {
        function ... {
            for ... {
                using ... {
                    if ... {
                        ...
                    }
                    if ... {
                        ...
                    }
                }
            }
            // wait... what level is this?
        }
    }
}

Étant tellement habitué à VB, je me demande s'il existe une technique employée par les programmeurs de style c pour améliorer la lisibilité et garantir que votre code se retrouve dans le "bloc" correct. L'exemple ci-dessus est relativement facile à lire, mais parfois à la fin d'un morceau de code, j'ai 8 niveaux ou plus d'accolades, ce qui m'oblige à faire défiler plusieurs pages pour déterminer quelle accolade termine le bloc qui m'intéresse dans.

JDB se souvient encore de Monica
la source
83
Je sais que cela peut sembler moralisateur, et peut-être que vous avez des conditions spéciales qui l'exigent (parce que oui, parfois c'est nécessaire - heureusement, ces temps devraient être rares), mais généralement "... 8 ou plusieurs niveaux d'accolades, m'obligeant à faire défiler plusieurs pages pour déterminer quelle accolade termine le bloc qui m'intéresse " signifie que le code a besoin d'une refonte et d'un nettoyage sérieux.
FrustratedWithFormsDesigner
7
Une chose que j'ai vu faire et que j'ai entrepris de faire, c'est à la fin d'une accolade, je vais ajouter un commentaire à ce sujet. Quelque chose comme // End's using X statement.
PiousVenom
14
@FrustratedWithFormsDesigner est au courant du fait que votre flux de contrôle est un gâchis et doit être refait. Cela dit, je pense que vous vous plaignez plus des accolades que de la portée et je dirais que vous avez juste besoin de vous y habituer. Apprendre une langue avec une syntaxe significativement différente de celle à laquelle vous êtes habitué ressemble définitivement à de la soupe pendant un certain temps, mais avec une pratique qui disparaît. Il vous suffit de vous attacher et de traiter jusqu'à ce que votre cerveau commence à traiter la syntaxe plus naturellement, vous y arriverez.
Jimmy Hoffa
2
@FrustratedWithFormsDesigner - J'ai besoin de nettoyer beaucoup d'objets COM dans une situation d'interopérabilité COM. J'utilise la technique suggérée dans cet article: jake.ginnivan.net/vsto-com-interop . Cela crée facilement deux ou trois couches. Lorsque vous empilez la boucle for, la fonction, la classe et l'espace de noms en plus de cela (avec une instruction if), vous accédez facilement à plusieurs couches d'accolades.
JDB se souvient encore de Monica
5
@TyrionLannister - Et ceux-ci peuvent être certains des commentaires les plus rapides à désynchroniser avec ce à quoi ils appartiennent ... Je pense que si j'allais avoir quelque chose comme ça, je préférerais qu'il soit généré automatiquement (à l'affichage -heure seulement, non persisté) par l'IDE.
Clockwork-Muse

Réponses:

39

Mettez votre accolade bouclée de départ dans le même "rang" que votre accolade de fin, comme ceci:

namespace ... 
{
    class ... 
    {
        function ... 
        {
            for ... 
            {
                using ... 
                {
                    if ... 
                    {
                        ...
                    }
                    if ... 
                    {
                        ...
                    }
                }
            }
            // It's the `function` level!
        }
    }
}
Robert Harvey
la source
15
Je suis d'accord. Les parenthèses égyptiennes me donnent mal à la tête.
PiousVenom
8
De plus, la plupart des IDE (probablement) mettent en évidence le partenaire d'une accolade lorsque vous cliquez dessus.
StuperUser
3
@TyrionLannister: Merci de m'avoir enfin donné un terme pour ce style! Je n'ai jamais eu un bon nom pour eux autres que des "accolades mal alignées".
FrustratedWithFormsDesigner
3
@ Cyborgx37: Votre IDE a-t-il une fonction "Aller à l'accolade correspondante"? Habituellement lié à un raccourci clavier qui déplace automatiquement votre curseur sur l'accolade qui correspond à celle actuellement mise en surbrillance.
FrustratedWithFormsDesigner
3
Je dois dire que je ne vois pas comment cela rend les choses plus faciles. Dans les deux cas, il vous suffit de rechercher l'écran au niveau du retrait de l'accolade jusqu'à ce que vous arriviez à un mot clé. Et avec toutes ces lignes supplémentaires, vous devez maintenant regarder plus loin.
Blorgbeard est sorti
14
  • En fonction de votre IDE: placez votre curseur sur l'accolade ouverte / fermée et il mettra en surbrillance à la fois cela et l'accolade correspondante.
  • Réduisez le bloc et il vous montre où il s'ouvre / se ferme.
  • Écrivez des blocs de code plus petits. Sérieusement. Vérifiez Clean Codeet ne rencontrez plus jamais ce problème (et ayez un code plus lisible / maintenable).

Une remarque, ce qui suit est une syntaxe c # valide qui pourrait aider votre situation particulière:

using (var type = new MyDisposable1())
using (var type2 = new MyDisposable2())
{
    /* do what you will with type2 and type2 */
}
Steven Evers
la source
La chasse au caractère unique mis en évidence est ce qui m'a poussé à publier cette question en premier lieu.
JDB se souvient encore de Monica
2
@ Cyborgx37: D'où le point 3. Si tout votre bloc de code tient à l'écran, vous n'avez jamais à chasser. Dans la plupart / toutes les classes que j'écris, les seules paires d'accolades qui ne tiennent pas à l'écran sont l'espace de noms / classe.
Steven Evers
Ce que vous suggérez aux points 1 et 2, c'est ce que je fais maintenant ... mais cela nécessite que je quitte l'endroit où je suis en train de coder et que je commence à manipuler ma vue du code pour savoir où mettre la ligne suivante. Le point 3 est bien pris, mais pas toujours possible, surtout si votre code nécessite plusieurs couches de usingblocs (voir jake.ginnivan.net/vsto-com-interop )
JDB se souvient toujours de Monica
@ Cyborgx37: Voir mon montage.
Steven Evers
1
@ Cyborgx37 Si vous choisissez une couleur qui se démarque de tout le reste (j'ai utilisé un fond violet et du texte blanc pendant un certain temps, IIRC), alors il n'est pas nécessaire de chasser l'accolade assortie - elle vous hurle pratiquement "Je suis ICI ! ".
un CVn
5

Une convention courante consiste à ajouter un commentaire après l'accolade fermante pour indiquer la structure qu'elle ferme:

if {
   ...
} // end if

while (condition) {
   ...
} // end while

etc. Je ne me suis jamais réchauffé à cette convention moi-même, mais certaines personnes la trouvent utile.

John Bode
la source
16
Je l' ai vu des gens le font, et quand ils échangent / changer le début du bloc (changer whileà un for, échange de ifdéclarations) ils presque jamais se rappeler de mettre à jour les commentaires de clôture, ce qui les rend pire qu'inutile. Cette convention ne sera probablement utile que si vous pouvez vous forcer à conserver les commentaires à chaque fois que la nature des correspondances {change.
FrustratedWithFormsDesigner
Oui, j'ai fait une partie de cela, mais c'est beaucoup de travail supplémentaire (et de bruit). J'espérais qu'il y aurait quelque chose de plus simple.
JDB se souvient encore de Monica
5
Les commentaires ne doivent expliquer que pourquoi jamais quoi ou comment comme le code fait les deux et en s'appuyant sur des commentaires pour expliquer l'un ou l'autre signifie que le code est difficile à lire, ce qui est un signe que le code doit être corrigé et non commenté.
Jimmy Hoffa
1
Cela me fait me demander pourquoi personne n'a écrit un éditeur qui affiche ces commentaires, mais ne les inclut pas réellement dans le code ..
Brendan Long
2
@JimmyHoffa: Je pense qu'une meilleure règle pour les commentaires est qu'ils devraient apporter de la clarté . Habituellement, cela signifie répondre «pourquoi», mais cela peut aussi signifier d'autres choses. Ne soyez pas tellement pris dans le dogme qu'il vous empêche de faire des choses qui vous aident réellement, comme ajouter occasionnellement un commentaire à une accolade de fermeture qui est loin de son accolade d'ouverture.
Bryan Oakley
5

En général, quand il devient difficile de faire correspondre les accolades dans n'importe quel style - cela signifie probablement que la méthode est trop longue et doit être refactorisée.

MaximR
la source
5

Je pense que vous devez endurer les accolades. Finalement, ils deviendront une seconde nature pour vous et vous vous demanderez comment vous avez pu vivre sans eux.

Assurez-vous cependant qu'ils sont en retrait de manière appropriée et que certaines conventions d'espacement sont respectées (peu importe laquelle).

MrFox
la source
Un an plus tard, et ce conseil sonne vrai. :)
JDB se souvient encore de Monica
4

Je supprime 2 niveaux d'imbrication en réduisant horizontalement l'espace de noms et les étendues de classe. Notez que les méthodes affleurent le bord gauche de l'écran. Je ne vois pas l'intérêt de perdre 2 niveaux d'indentation dans chaque fichier.

Après cela, il est rare que vous ayez jamais niché à plus de 4 niveaux.

namespace FooNameSpace {
class Foo {

public void bar()
{
    while(true)
    {
        while(true)
        {
            break;
        }
    }
}

public void fooBar()
{
    foreach(var item in FooList)
    {
        foreach(var b in item.Bars)
        {
            if(b.IsReady)
            {
                bar();
            }
            bar();
        }
        bar();
    }
}

}}//end class, namespace
mike30
la source
J'aime cette idée, mais Visual Studio ne semble pas la prendre en charge (au moins, 2008. Nous passons à 2012 d'ici la fin de l'année, alors j'espère)
JDB se souvient toujours de Monica
@ Cyborgx37. Je modifie le texte en externe dans VIM donc ce n'est pas un problème. Mais dans Visual Studio, faites: Control + A, puis appuyez sur le bouton "indent moins". Ne le faites que pour les nouveaux fichiers. Ne vous embêtez pas avec les fichiers existants car cela gâcherait les comparaisons de différences dans le contrôle de source.
mike30
La saisie des parenthèses / accolades fermantes lance un formatage automatique par VS, mais vous pouvez toujours appuyer sur CTRL + z pour refuser sa suggestion.
Alex à Paris
1

J'ai récemment décidé d'essayer de formaliser deux règles sur les constructions de contrôle de flux qui vont essentiellement comme ceci:

  • Vous ne devriez avoir que des constructions de flux de code nécessaires
  • Vous devez rendre les constructions de flux de code aussi petites que possible

Pour exactement les raisons que vous avez mentionnées et que vous connaissez clairement, je pense que ce sont d'excellentes règles à suivre. Il existe quelques techniques simples que vous pouvez utiliser pour les accomplir:

  • Quittez la portée dès que vous le pouvez (cela inclut la portée des boucles ainsi que les fonctions)
  • Surveillez les autres qui pourraient être atténués en quittant la fonction du précédent si et appliquez la technique de sortie de la portée comme je l'ai mentionné
  • Inversez vos vérifications conditionnelles lorsque le code à l'intérieur d'un if est supérieur à celui à l'extérieur
  • Factoriser le code à l'intérieur d'une boucle vers une autre méthode lorsque la taille de la boucle augmente pour masquer le reste de la méthode
  • Surveillez les étendues qui ne contiennent qu'une autre étendue, par exemple une fonction dont toute l'étendue est remplie par un if sans rien en dehors du if

J'ai détaillé ici des exemples de la façon dont ne pas les suivre peut vous obliger à faire comme vous l'avez dit et à mettre du code dans le mauvais bloc de code, ce qui est mauvais et une cause facile de bogues se reproduisant pendant la maintenance.

Jimmy Hoffa
la source
Merci, il pourrait y avoir un bloc ou deux que je pourrais refactoriser. Cela vous aidera, mais il est difficile de refactoriser plusieurs usingblocs imbriqués .
JDB se souvient encore de Monica
@ Cyborgx37 utilisant réellement des blocs peut être aligné s'ils sont des portées satisfaisantes imbriquées, regardez ici stackoverflow.com/questions/1329739/… cela fonctionne essentiellement comme des constructions de contrôle de flux sur une seule ligne comment vous pouvez si (true) doSomething (); vous pouvez également if (true) if (somethingElse) if (otherThings) {doThis (); doThat (); fais ce que tu veux(); } et les ifs se nichent comme vous vous y attendez (N'ÉCRIVEZ PAS DE CODE COMME CELA POUR L'AMOUR DE DIEU, FAITES-LE JUSTE AVEC LES UTILISATIONS ET RIEN D'AUTRE heh)
Jimmy Hoffa
Oui, je connais l'imbrication à l'aide de blocs, mais cela ne fonctionne que si vous avez une seule ligne en dessous. Dans la plupart de mon code, ce n'est pas le cas. Un article très utile dans l'ensemble ... j'ai appris quelques choses (+1)
JDB se souvient encore de Monica
@ Cyborgx37 ouais je me rends compte que l'imbrication de la portée ne fonctionne que si vous n'avez pas de bits supplémentaires, cela dit, y a-t-il un modèle dans la manière de vos utilisations? Serait-il peut-être viable de déplacer une partie de ce supplément dans le constructeur s'il est en haut ou de le mettre au rebut s'il est en bas? C'est si c'est à motifs; deviner cela pourrait être depuis que vous avez soulevé cela comme un problème, donc vous les rencontrez probablement en utilisant des nids souvent dans votre code.
Jimmy Hoffa
J'ai en fait commencé à travailler sur une implémentation Factory-pattern qui encapsule les objets COM dans une classe "AutoCleanup". J'utilise ensuite une seule usinginstruction sur la classe d'usine et, lorsqu'elle est supprimée, elle supprime automatiquement toutes les classes terminées. Cela fonctionne bien jusqu'à présent et a considérablement réduit le nombre de usingdéclarations dans mon code.
JDB se souvient encore de Monica
1

C'est malheureusement l'une des plus anciennes causes de guerre informatique. Des arguments raisonnables peuvent être avancés des deux côtés (meilleure économie immobilière verticale par rapport à une capacité plus facile de faire correspondre visuellement l'accolade ouvrante à l'accolade fermante), mais en réalité, un simple formateur de code source résoudra tout pour vous. MS Visual C # en a un intégré qui fonctionne bien.

Soyez averti cependant que si vous travaillez au sein d'une équipe, vous devrez vous conformer aux conventions utilisées par cette équipe, il est donc avantageux de se familiariser avec les deux styles et de s'abstenir de devenir religieux par rapport aux styles d'accolades.

Donc, pendant que vous apprenez, concentrez-vous sur le style qui vous facilite l'apprentissage, mais gardez un œil sur l'autre pendant que vous y êtes et vous irez bien.

Maximus Minimus
la source
1
Je ne sais pas si c'est le formateur par défaut ou quelque chose dans ReSharper, mais quand j'utilisais C #, nous avions un ensemble d'options qui reformatait le code dans le cadre de l'enregistrement. De cette façon, vous pouvez formater le code comme vous le souhaitez pendant que vous travaillez avec, mais il sera reformaté en "norme de projet" lors de l'enregistrement. Je pense que la seule vraie norme de formatage que nous ayons eu était d'utiliser des espaces au lieu des tabulations.
TMN
1

Utilisez Resharper, qui vous recommandera des moyens de réduire l'imbrication. Lisez également le livre Clean Code de Bob Martin , qui souligne qu'une fonction ne doit faire qu'une seule chose, et donc que chaque fonction ne doit comporter qu'une demi-douzaine de lignes, de sorte que vous n'aurez pas autant de niveaux d'imbrication à vous soucier.

lorddev
la source
1

Il existe un module complémentaire à l'éditeur qui peut vous aider à: C # Outline .

Le module complémentaire étend l'éditeur VS20xx pour C # en ajoutant des fonctionnalités pour réduire, développer et mettre en évidence des blocs de code imbriqués. Ces fonctionnalités permettent une édition et une lecture plus faciles du contenu imbriqué des blocs de code tels que if, while, etc.

Aucune chance
la source
0

Si vous écrivez votre code dans Visual Studio, il existe également un plugin qui vous montre des points verticaux entre le début et la fin de chaque structure que vous construisez.

Mais dans l'ensemble, je pense que cela prendra juste un peu de temps jusqu'à ce que vous soyez habitué à la "Curly-Braces-Soup". (Btw, j'aime vraiment cette expression. Cela ressemble un peu à un nom d'épisode pour The Big Bang Theory)

mhr
la source
0

L'indentation vous indique où vous êtes, dans les deux styles de syntaxe. Si vous écrivez un programme VB ou un programme C # sur une seule ligne, vous ne pourrez bientôt pas dire où vous vous trouvez dans la syntaxe imbriquée. La machine analyse les phrases de fin de bloc ou les accolades, mais les humains ont besoin d'indentation.

Les phrases de fin de bloc viennent d'une époque de cartes perforées et de bandes de papier, lorsque la programmation était beaucoup moins interactive et visuelle. Ou, vraiment, pas du tout interactif. Il était difficile d'entrer des programmes, et les programmeurs avaient donc besoin de compilateurs pour être très intelligents sur l'analyse syntaxique et la récupération d'erreurs.

À cette époque révolue, le cycle d'édition-compilation-exécution aurait pu impliquer la préparation de cartes perforées avec un perforateur de cartes, puis l'alignement sur une fenêtre de soumission de travail où un commis a pris les cartes perforées et les a soumises à la machine. Plus tard, le programmeur collecterait la sortie (imprimée sur papier) d'une autre fenêtre. Si le programme avait des erreurs, la sortie se composerait uniquement des diagnostics du compilateur. Lorsque les délais d'exécution sont longs, le coût supplémentaire de la frappeend if au lieu de simplement )est justifié s'il contribue à améliorer la qualité des diagnostics, car le programmeur doit corriger autant d'erreurs que possible en une seule itération pour réduire le nombre de pertes de temps itérations via la fenêtre de soumission des travaux.

Lorsqu'une accolade fermante est manquante, il est difficile de dire quelle accolade ouverte est celle qui n'est pas fermée. (Le compilateur peut devoir analyser l'indentation pour faire une supposition éclairée.) Si vous supprimez une accolade fermante à l'intérieur d'une fonction, il semble que le reste du fichier fasse partie de cette fonction, ce qui entraîne une multitude de messages d'erreur inutiles. Alors que si vous avez unend function syntaxe, le compilateur peut déduire où se termine la fonction erronée, récupérer et analyser correctement les fonctions suivantes, vous donnant des diagnostics supplémentaires, le cas échéant, qui sont significatifs.

Lorsque vous travaillez dans un éditeur de texte sensible au code qui indente et colorise automatiquement votre code, sur un écran haute résolution où vous pouvez voir soixante lignes ou plus, les arguments pour ces types de langages maladroits ne s'appliquent plus. Vous pouvez éditer et reconstruire de manière incrémentielle des programmes si rapidement que vous ne pouvez traiter qu'une seule erreur à la fois. De plus, en voyant simultanément de grandes sections du programme à l'écran et en conservant une indentation appropriée, vous pouvez réduire l'apparition de ces types d'erreurs d'imbrication en premier lieu. Et un bon éditeur de texte de programmation signalera même certains types d'erreurs de syntaxe lors de la frappe. De plus, il existe des éditeurs pliants qui réduiront les blocs d'un programme en fonction de sa syntaxe, donnant une vue "schématique" de sa structure.

Lisp a utilisé des parenthèses depuis le début et peut-être, pas par coïncidence, les pirates de Lisp ont lancé la programmation comme une expérience interactive en construisant des systèmes qui acceptaient les programmes en petits morceaux (expressions).

En fait, vous n'avez pas du tout besoin de symboles de fin, comme l'illustre le langage Python. L'identification ne peut être que la structure. Les humains utilisent déjà l'indentation pour masquer la structure du code, même dans les langues où la machine s'appuie sur des symboles ou des phrases de fin.

Kaz
la source
-1

Si vous utilisez un IDE, appuyez simplement sur Crtl+ k+ Det l'IDE fera le reste du travail.

Jagz W
la source
quelle éclipse IDE utilise ctrl-shift-i pour l'indentation et ctrl-shift-f pour le formatage
ratchet freak
check in visual studio
Jagz W