C # sta diventando più difficile da leggere?

15

Mentre C # è progredito, sono state aggiunte molte funzionalità linguistiche. È arrivato al punto in cui sta diventando illeggibile per me.

Ad esempio, prendi in considerazione il seguente codice snip dal codice Caliburn.Micro qui :

            container = CompositionHost.Initialize(
                   new AggregateCatalog(
                      AssemblySource.Instance.
                             Select(x => new AssemblyCatalog(x))
                               .OfType<ComposablePartCatalog>()
                )
            );

Questo è solo un piccolo esempio.

Ho una serie di domande:

  • Si tratta di un problema comune o noto?
  • La comunità C # è identica?
  • Si tratta di un problema con la lingua o è lo stile utilizzato dallo sviluppatore?

Esistono soluzioni semplici per comprendere meglio il codice degli altri ed evitare di scrivere codice in questo modo?

    
posta Steven Evers 04.06.2012 - 14:49
fonte

6 risposte

12

Una nota rapida su dove dovrebbe essere la lingua dovrebbe essere chiarita: C # è un linguaggio di programmazione per scopi generici ; a differenza di C (come C ++) si sforza di ottenere un'alta astrazione; a differenza dei dialetti Lisp, mira all'espressività pratica e, a differenza di Java, è più aggressivo - Microsoft è pronto a rispondere alla domanda.

Questo è il motivo per cui si sta trasformando in un mix di LINQ, lambda e nuove strane parole chiave: si adatta rapidamente ai nuovi domini problematici, e questo è in effetti una pendenza scivolosa verso una lingua così complessa che pochissimi può usarlo correttamente (come C ++). Non è un problema con C # stesso, è un problema con qualsiasi linguaggio con questi obiettivi ambiziosi.

La community è consapevole di questo e, cosa più importante, i ragazzi dietro C # ne sono profondamente consapevoli (i pochi blog e podcast su ciò che era dietro le nuove aggiunte in C # 5.0 mostrano quanto male questi ragazzi vogliano mantenere le cose semplici ). Microsoft sta cercando di togliere parte del carico del loro fiore all'occhiello in modo che non diventi un tarpit: l'introduzione del DLR, un riflettore luminoso sulle nuove lingue (F #).

Inoltre, il materiale didattico sul C # (incluse le certificazioni MS) consiglia diversi stili (ma coerenti) di utilizzo per C # a seconda del problema: scegli la tua arma e atteniti ad essa: LINQ fluente su alcuni problemi, lambda con TPL su altri, semplicemente vecchi per la maggior parte.

    
risposta data 05.06.2012 - 08:49
fonte
27

No. C # ci sta offrendo più opzioni per scrivere codice in modo più sintetico. Questo può essere usato o abusato. Se usato correttamente, rende il codice più facile da leggere. Se usato in modo improprio, può rendere il codice più difficile da leggere. Ma i cattivi programmatori hanno sempre avuto la capacità di scrivere codice difficile da leggere.

Diamo due esempi, entrambi basati su esempi trovati su StackOverflow riguardanti lo stesso problema, trovando i tipi con un attributo specifico:

C # 2.0:

static IEnumerable<Type> GetTypesWithAttribute<TAttribute>(bool inherit) 
                              where TAttribute: System.Attribute
{
    foreach(Assembly assembly in AppDomain.Current.GetAssemblies())
    {
        foreach(Type type in assembly.GetTypes()) 
        {
            if (type.IsDefined(typeof(TAttribute),inherit))
                yield return type;
        }
    }
}

C # 4.0:

IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit) 
                              where TAttribute: System.Attribute
{ 
    return from assembly in AppDomain.CurrentDomain.GetAssemblies()
           from type in assembly.GetTypes()
           where type.IsDefined(typeof(TAttribute),inherit)
           select type;
}

IMHO, la nuova sintassi lo rende molto più facile da leggere.

    
risposta data 05.06.2012 - 08:45
fonte
8

Quando LINQ è stato aggiunto, ha reso popolare uno stile di codifica che coinvolge molti metodi di concatenamento in stile Fluent e il passaggio di lambda come parametri.

Questo stile è molto potente quando ti senti a tuo agio. Tuttavia può essere abusato per creare codice abbastanza illeggibile. Non penso che il tuo esempio sia troppo brutto, sebbene il rientro sia un po 'casuale (e questa è una caratteristica comune di questo stile di codice, Visual Studio non lo indentifica in modo molto coerente).

Sul mio posto di lavoro, abbiamo discusso di questo stile di codifica quando abbiamo rivisto i nostri standard di codifica all'inizio di quest'anno e abbiamo deciso di incoraggiare gli sviluppatori a suddividere il codice in questo modo: in particolare, non creare e inizializzare oggetti anonimi all'interno di una chiamata di funzione. Quindi il tuo codice diventerebbe:

var assemblyCatalog = AssemblySource.Instance
    .Select(x => new AssemblyCatalog(x))
    .OfType<ComposablePartCatalog>();
var aggregateCatalog = new AggregateCatalog(assemblyCatalog);
container = CompositionHost.Initialize(aggregateCatalog);
    
risposta data 05.06.2012 - 07:56
fonte
4

Il codice nel tuo esempio non è facilmente leggibile perché

  • Mescola molte nozioni (Composizione, Cataloghi, Aggregati, Assiemi, ComposableParts ...) con diversi livelli di nidificazione, mentre il codice chiamante dovrebbe normalmente avere a che fare con un solo livello. Sembra un po 'come una violazione della legge di Demeter solo con chiamate di metodo nidificate anziché una catena di proprietà secondarie secondarie. Questo confonde in qualche modo l'intenzione dietro la linea di codice.

  • C'è un uso singleton strano - AssemblySource.Instance.Select() implica che Instance è un oggetto IEnumerable, che è un po 'scomodo.

  • La variabile x nell'espressione lambda è brutta. Generalmente provi a dare alle tue variabili lambda i nomi che rivelano l'intenzione - aiuta il lettore a identificare di che tipo di dati si tratta, anche se non ha familiarità con lambdas.

  • Non è chiaro il motivo per cui devi filtrare con OfType<T>() una raccolta di oggetti appena aggiunti ...

Tuttavia, tutti questi difetti riguardano il modo in cui lo sviluppatore originale ha scritto il codice e quanto espressivo lo ha progettato. Questo non è qualcosa di specifico per le ultime versioni di C # e l'aspetto delle espressioni lambda.

Più in generale, aiuta se il lettore del tuo codice sa come funzionano i lambda, ma con un nome abbastanza chiaro puoi quasi sempre rendere il tuo codice leggibile anche a qualcuno con uno sfondo in premessa .NET 3.5.

    
risposta data 05.06.2012 - 16:50
fonte
2

Ogni volta che una nuova versione del linguaggio popolare acquisisce nuovi costrutti, sorgono dibattiti simili.

Ho avuto anche questi dubbi anni fa (http://gsscoder.blogspot.it/2009/08/use-csharps-features-wisely.html).

Secondo me C # si sta evolvendo in modo elegante e coerente.

Il codice nel tuo campione non è complesso, forse non sei usato con le espressioni lamda.

Il problema è che C # non è solo un linguaggio orientato agli oggetti, ma supporta anche costrutti funzionali (http://archive.msdn.microsoft.com/FunctionalCSharp/).

    
risposta data 05.06.2012 - 17:09
fonte
1

Mi ci è voluto un po 'di tempo per capire la sintassi di Lambda e sono di origine matematica e fisica. È un po 'simile alle espressioni matematiche, anche se usano - > invece di = >:

Esempio di matematica f (x): = x- > x + 2 questo dice che "la funzione f di x è definita come x map su x + 2

c # esempio del mioDelegate = x = > x +2; questo dice che "myDelegate è una funzione tale che myDelegate (x) mappa x on a x + 2

L'incoerenza tra matematica e programmazione non aiuta molto, anche se suppongo che - > era già stato ripreso in C ++ come "proprietà di" (urrgghh!)

link

    
risposta data 20.06.2013 - 18:18
fonte

Leggi altre domande sui tag