Perché gli sviluppatori C # newline aprono le parentesi quadre? [chiuso]


44

Ho trascorso la maggior parte degli ultimi anni lavorando principalmente con C # e SQL. Ogni programmatore con cui ho lavorato in quel periodo aveva l'abitudine di collocare la parentesi graffa di apertura di una funzione o di una dichiarazione del flusso di controllo su una nuova riga. Così ...

public void MyFunction(string myArgument)
{
     //do stuff
}

if(myBoolean == true)
{
    //do something
}
else
{
    //do something else
}

Sono sempre stato colpito da quanto sia dispendioso lo spazio, specialmente nelle dichiarazioni if ​​/ else. E so che esistono alternative nelle versioni successive di C #, come:

if(myBoolean == true)
    //do something on one line of code

Ma quasi nessuno li ha usati. Ognuno ha fatto la cosa da ricciolo su newline.

Poi sono tornato a fare JavaScript dopo una lunga assenza. Nella mia memoria, gli sviluppatori JavaScript erano soliti fare esattamente la stessa cosa tra parentesi graffe, ma con tutte le nuove fantasiose librerie e cose, la maggior parte degli sviluppatori ha messo la parentesi di apertura dopo la dichiarazione:

function MyJavaScriptFunction() {
    //do something
}

In questo puoi vedere il senso, perché da quando l'uso di chiusure e puntatori a funzioni è diventato popolare in JavaScript, risparmia molto spazio e rende le cose più leggibili. Quindi mi chiedevo perché non fosse visto come fatto in C #. In effetti, se provi il costrutto di cui sopra in Visual Studio 2013, in realtà lo riformatta per te, mettendo la parentesi graffa di apertura su una nuova linea!

Ora, ho appena visto questa domanda su Code Review SE: https://codereview.stackexchange.com/questions/48035/questions-responses-let-me-tell-you-about-you in cui ho appreso che in Java, un linguaggio che non conosco eccessivamente, è considerato de-rigore aprire le parentesi graffe subito dopo la dichiarazione, in modo JavaScript moderno.

Avevo sempre capito che C # era originariamente modellato su Java e rispettava molti degli stessi standard di codifica basale. Ma in questo caso, sembra di no. Quindi presumo che ci debba essere una buona ragione: qual è la ragione? Perché gli sviluppatori C # (e Visual Studio) applicano l'apertura di parentesi graffe su una nuova riga?


30
La convenzione è semplicemente questa.
Oded,

19
Visual Studio non applica nulla, lo stile del codice è configurabile. Qualcosa deve essere il valore predefinito. L'impostazione predefinita è "migliore" è il bikeshedding del massimo livello.
Phoshi,

23
Il tutore alla fine della linea è l'antico standard K&R C. Kernighan e Ritchie hanno inventato il linguaggio C quando i display dei computer avevano solo 25 righe (23 se si aggiungono intestazione e righe di stato). Non è più così, vero? Ciò che è importante è la coerenza durante un progetto. Ci sono anche studi scientifici che dimostrano che il tutore sulla propria linea (indentata allo stesso livello del codice, in effetti) migliora la comprensione del codice nonostante ciò che la gente pensa di pensare all'estetica.
Craig,

10
C # ha sempre supportato la valutazione di una singola riga di codice dopo un condizionale, tra l'altro. In effetti, questa è l' unica cosa che fa, anche adesso. Mettere il codice tra parentesi graffe dopo un'espressione di ramificazione rende quell'istruzione un goto (il compilatore crea l'ambito usando le istruzioni jmp). C ++, Java, C # e JavaScript sono tutti più o meno basati su C, con le stesse regole di analisi sottostanti, per la maggior parte. Quindi, in questo senso, C # non è "basato su Java".
Craig,

10
Come nota a margine, if(myBoolean == true)ha poco senso per me. Mentre ci siamo, mentre no if ((myBoolean == true) == true)?? Basta if (myBoolean)e basta. Mi dispiace, una mia piccola pipì.
Konrad Morawski,

Risposte:


67

Alla fine della linea c'è l'antico standard K&R C, tratto dal libro The C Programming Language di Brian Kernighan e Dennis Ritchie , che pubblicarono nel 1978 dopo aver co-inventato il sistema operativo UNIX e il linguaggio di programmazione C (penso che C fosse progettato principalmente da Ritchie), presso AT&T.

C'erano guerre di fiamma su "l'unico vero stile di parentesi graffe".

Ritchie inventò il linguaggio C e Kernighan scrisse il primo tutorial, quando i display dei computer mostravano solo poche righe di testo. In effetti, lo sviluppo di UNICS (in seguito UNIX) è iniziato su un DEC PDP-7, che ha utilizzato una macchina da scrivere, una stampante e un nastro di carta per un'interfaccia utente. UNIX e C sono stati completati sul PDP-11, con terminali di testo a 24 righe. Quindi lo spazio verticale era davvero un premio. Tutti oggi abbiamo schermi leggermente migliori e stampanti a risoluzione più elevata, giusto? Voglio dire, non ti conosco, ma al momento ho tre (3) display da 24 "1080p davanti a me. :-)

Inoltre, gran parte di quel piccolo libro Il linguaggio di programmazione C è costituito da esempi di codice che mettono le parentesi graffe alle estremità delle linee anziché sulle loro stesse linee presumibilmente risparmiando una notevole quantità di denaro sulla stampa.

Ciò che è veramente importante è la coerenza all'interno di un progetto, o almeno all'interno di un determinato file di codice sorgente.

Ci sono anche studi scientifici che dimostrano che il tutore sulla propria linea (indentata allo stesso livello del codice, in effetti) migliora la comprensione del codice nonostante ciò che la gente pensa di pensare all'estetica. Rende molto chiaro al lettore, visivamente e istintivamente, quale codice viene eseguito in quale contesto.

if( true )
    {
    // do some stuff
    }

A proposito, C # ha sempre supportato la valutazione di un singolo comando dopo un'espressione di ramificazione. In effetti, questa è l'unica cosa che fa, anche adesso. Mettere il codice tra parentesi graffe dopo un'espressione di ramificazione rende solo un comando un goto (il compilatore crea l'ambito usando le istruzioni jmp). C ++, Java, C # e JavaScript sono tutti più o meno basati su C, con le stesse regole di analisi sottostanti, per la maggior parte. Quindi, in questo senso, C # non è "basato su Java".

Riassumendo, questo è un po 'un problema religioso / guerra di fiamma. Ma ci sono studi che rendono abbastanza chiaro che organizzare il codice in blocchi migliora la comprensione umana . Al compilatore non potrebbe importare di meno. Ma questo è anche correlato al motivo per cui non ho mai inserito una riga di codice dopo un ramo senza parentesi graffe: è troppo facile per me o per un altro programmatore per schiaffeggiare un'altra riga di codice in un secondo momento e scivolare sul fatto che non lo farà eseguire nello stesso contesto con la linea immediatamente prima o dopo di essa.

EDIT : basta andare a guardare il bug di Applegoto fail per un esempio perfetto di questo problema esatto, che ha avuto conseguenze molto gravi nel mondo reale.

if( true )
    doSomething();

diventa ...

if( true )
    doSomething();
    doSomethingElse();

In questo caso, doSomethingElse()esegue ogni volta, a prescindere dal risultato del test, ma perché è rientrato allo stesso livello come il doSomething()comunicato, è facile perdere. Questo non è davvero discutibile; studi sostengono questo. Questa è una grande fonte di bug introdotti nel codice sorgente durante la manutenzione.

Tuttavia, ammetto che la sintassi di chiusura JavaScript sembra un po 'sciocca con parentesi graffe sulle loro stesse linee ... esteticamente. :-)


13
La parte sui blocchi nei condizionali è leggermente fuorviante. In C, il condizionale ha sempre una singola istruzione, ma un blocco (aka istruzione composta) è un tipo di istruzione . C # segue questo precedente. Comunque, la valutazione condizionale implica sempre una sorta di goto condizionale o istruzione di ramificazione, a causa della natura lineare di tutti i set di istruzioni comuni. Un condizionale senza blocco non è qualitativamente diverso da un condizionale con un blocco (tranne per quanto riguarda l'ambito).
amon

3
@Craig, ricorda, questo avveniva ai Bell Labs, quando Bell Labs fu incaricato di "fare cose interessanti" che non dovevano necessariamente essere pratiche per nulla. Metti le persone intelligenti in un edificio, dì loro di fare delle ricerche interessanti, allontanarle da ciò che fanno non è "interessante" e, cosa divertente, le cose INTERESSANTI (come i transistor e Unix) tendono a saltar fuori. DARPA ha avuto lo stesso obiettivo, all'inizio, e ha finanziato MOLTO buon lavoro, in nome della ricerca di base.
John R. Strohm,

3
@Craig: Ai vecchi tempi di Pascal / Delphi, di solito lo evitavo per i blocchi a riga singola, come utilizza Pascal begine endal posto delle parentesi graffe, il che rende tali errori davvero difficili da perdere, e anche più rigoroso per quanto riguarda il posizionamento del punto e virgola - ma avendo speso 4 giorni l'anno scorso il debug di un problema in C incorporato che alla fine era dovuto alla mancanza di posizionamento di parentesi graffe ..... Penso che dovrebbe esserci un'opzione di compilatore che rende le parentesi graffe obbligatorie per le dichiarazioni di controllo!
Mark K Cowan,

12
Fornisci riferimenti per "... studi scientifici che dimostrano che il tutore è sulla sua linea ...". Senza almeno due riferimenti (altrimenti sarebbe studio , non studi ), sta solo sparando a caso nell'aria.
ErikE,

2
@Craig, potresti fornire qualche indizio su come trovare gli studi di ricerca che hai citato?
Grzegorz Adam Kowalski

30

Il motivo per cui gli sviluppatori C # lo fanno è perché è l'impostazione predefinita del formatter automatico di Visual Studio. Mentre questa impostazione può essere modificata, la maggior parte delle persone non lo fa, e quindi tutti gli sviluppatori di un team devono andare con la maggioranza.

Per quanto riguarda il motivo per cui questo è il valore predefinito in Visual Studio, non lo so.


15
È l'impostazione predefinita in Visual Studio perché era lo stile di codifica generalmente accettato in Microsoft molto tempo fa, e in effetti in almeno alcuni team di Microsoft lo stile non era solo parentesi sulle proprie linee, ma parentesi sulle proprie linee e rientrato. Questa è un'opzione anche in Visual Studio (la preferisco personalmente).
Craig,

20
@Craig: Ewwwwwwwww
Lightness Races con Monica

5
@PreferenceBean Hmm. Personalmente non mi piace lo stile di K&R, perché le parentesi si perdono solo nel rumore alle estremità delle linee e il testo mi sembra scomodo, che non è solo una preferenza estetica, ma ha un impatto reale sulla leggibilità / comprensione. Mi piace lo spazio bianco verticale. Era un po 'diverso sui monitor da 12 "con 24 righe di testo ai vecchi tempi in cui lo spazio verticale era prezioso.
Craig

10
@Craig: questa non è una scusa per indentare le parentesi graffe: P
Lightness Races con Monica

2
@Craig Per rendere infelici i dipendenti Microsoft?
Mateen Ulhaq,

18

Come ho ipotizzato in questa risposta qui - https://softwareengineering.stackexchange.com/a/159081/29029 - Suppongo che la decisione di adottare il controvento di Allman potrebbe essere un segno dell'eredità di Pascal, dato che Hejlsberg ha creato Delphi prima di progettare C # . Lo stesso del caso Pascal per i nomi dei metodi.

Personalmente credo nel seguire il detto "a Roma fai come fanno i romani". Uso Allman's in C #, ma K&R in Java. Sono così abituato che cambiare la convenzione in entrambi i modi mi stenta.

Credo che una certa diversità delle convenzioni sia effettivamente vantaggiosa per uno sviluppatore "multilingue" in quanto aiuta a ricordare in quale lingua stanno codificando al momento e facilita la differenziazione delle varie abitudini. È un equivalente mentale della memoria muscolare, per così dire.


7
+1 per la linea "sviluppatore multilingue", in realtà. Preferisco seriamente le parentesi graffe sulla loro linea e rientrata. Tuttavia, lavorando ad esempio su progetti ASP.NET (MVC), trovo che mi piaccia C # con lo stile "giusto" e JavaScript con stile "JavaScript". È un po 'ironico, ma onestamente parte è che la sintassi di chiusura di JavaScript è più attraente con il tutore alla fine della linea. Quindi sono schiavo dell'estetica quanto chiunque altro ...
Craig,

PascalCase per i nomi dei metodi era uno standard per Microsoft molto tempo prima che Anders Hejlsberg lasciasse Borland per diventare un illustre ingegnere del software presso Microsoft.
Craig,

2
È interessante notare che uso Allman per tutti i linguaggi di parentesi graffe. Tuttavia, sto diventando sempre più interessato a come potrebbe essere una conversione pre-elaborazione dei rientri in blocchi di parentesi graffe in Java. Il codice "java" potrebbe avere un aspetto estremamente pulito, una volta avvolto la mia mente di riconoscimento del modello attorno ad esso. Penso che Python potrebbe davvero avere ragione: non c'è davvero un grande motivo per le parentesi graffe in una lingua.
tgm1024,

L'uso degli spazi bianchi per controllare il flusso del programma è una follia. Python è popolare in questi giorni, ma questo aspetto di Python è stato un po 'folle da quando è apparso per la prima volta.
Craig,

@Craig fan di Python qui, cercando di fare qualcosa in javascript. Guardare l'altra tua risposta e la tua modifica riguardo a goto fail, usando il rientro per controllare il flusso del programma è ciò che gli umani vogliono naturalmente fare, quindi ciò che vedi è ciò che esegue. Se è rientrato male, non funziona. Dover decodificare il significato di quelle parentesi graffe, indipendentemente dal fatto che riflettano effettivamente il rientro, è un lavoro aggiuntivo che va oltre la comprensione del programma. Il rientro è ridondante alle parentesi graffe, quindi perché i programmatori lo usano se le parentesi graffe sono utili? Il nesting profondo è incomprensibile in qualsiasi lingua. Stavo solo dicendo.
Neil_UK,

14

La convenzione che associ a Java è lo stile K&R, o "Uno stile di parentesi graffa reale", e originariamente proviene da C. Questa pagina in stile rientro dal venerabile Jargon File mostra quanti anni ha questa distinzione.

Ho sempre pensato che lo stile Allman e le sue varianti riflettano il modo in cui gli autori pensano al codice, elevando i delimitatori di blocco al livello di parole chiave simile a come alcune lingue usano "inizio" e "fine" attorno a blocchi di codice.


Ho l'impressione che oggigiorno OTBS (un vero stile di parentesi graffa) implichi di non tralasciare mai le parentesi graffe dopo le dichiarazioni di controllo, anche per le singole righe di codice. Vedi il bug di Apple goto fail.
Craig,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.