Il nuovo operatore null-condizionale di C # 6.0 va contro la legge di Demeter?

29

La Legge di Demetra afferma quanto segue:

  • Ogni unità dovrebbe avere solo una conoscenza limitata delle altre unità: solo le unità "strettamente" correlate all'unità corrente.
  • Ogni unità dovrebbe parlare solo con i suoi amici; non parlare con estranei.
  • Parla solo con i tuoi amici più stretti.

C # 6.0 ha introdotto un nuovo operatore chiamato operatore condizionale nullo . IMHO, semplifica la codifica e migliora la leggibilità. Ma rende anche più facile scrivere più codice accoppiato, dato che è più facile navigare attraverso i campi delle classi, già verificando la nullità (qualcosa come var x = A?.B?.C?.D?.E?.F? ).

È corretto affermare che questo nuovo operatore va contro la legge di Demeter?

    
posta Arthur Rizzo 07.10.2015 - 19:34
fonte

4 risposte

44

Is it correct to state that this new operator goes against the Law of Demeter?

No *

* L'operatore condizionale nullo è uno strumento all'interno del linguaggio e del framework .NET. Qualsiasi strumento ha la capacità di essere abusato e utilizzato in modi che potrebbero danneggiare la manutenibilità di una determinata applicazione.

Ma il fatto che uno strumento possa essere abusato non significa necessariamente che ha da abusare, né che lo strumento violi alcuno particolare (i) che può essere trattenuto.

The Law of Demeter e altri sono linee guida su come dovresti scrivere il tuo codice. È mirato agli umani, non agli strumenti. Quindi il fatto che il linguaggio C # 6.0 abbia un nuovo strumento al suo interno non incide necessariamente su come dovresti scrivere e strutturare il tuo codice.

Con qualsiasi nuovo strumento, devi valutarlo come ... se il tizio che finisce per mantenere il tuo codice sarà un violento psicopatico ... . Nota di nuovo che questa è una guida per la persona che scrive il codice e non per gli strumenti usati.

    
risposta data 07.10.2015 - 19:46
fonte
10

Sort of.

Se stai facendo solo un accesso ( a?.Foo ), allora è equivalente a:

a == null ? null : a.Foo

che la maggior parte delle persone sarebbe d'accordo non è una violazione della legge di Demeter. A quel punto, è solo zucchero sintattico per migliorare la leggibilità.

Qualunque cosa in più, e probabilmente violerebbe la Legge di Demeter, e questa caratteristica tende a promuovere questo tipo di utilizzo. Direi anche che il suddetto utilizzo "buono" da solo non è sufficiente per giustificare questo tipo di modifica alla lingua, quindi mi aspetto che sia stato fatto per supportare l'utilizzo meno chiaro.

Detto questo, vale la pena ricordare che la Legge di Demetra non è una legge in sé, ma più di una linea guida. Un sacco di codice lo viola e funziona bene. A volte la semplicità del design o del codice vale più del rischio rappresentato dalla violazione della legge di Demeter.

    
risposta data 07.10.2015 - 19:58
fonte
9

No. Consideriamo sia l'operatore da solo che l'uso pesantemente incatenato che hai per questo.

Di per sé .?A dipende dalla stessa quantità di conoscenza della classe del valore di sinistra e del tipo restituito dal metodo come fa .A != null , vale a dire. È necessario sapere che la proprietà A esiste e restituisce un valore che può essere confrontato con null .

Possiamo solo obiettare che questo viola la legge di Demetra se le proprietà tipizzate lo fanno. Non siamo neppure forzati ad avere A come tipo concreto (il suo valore potrebbe essere di tipo derivato). L'accoppiamento qui è minimo.

Ora consideriamo var x = A?.B?.C?.D?.E?.F .

Ciò significa che A deve essere di un tipo che potrebbe essere nullo o che potrebbe avere una proprietà B , che deve essere di un tipo che potrebbe essere nullo o avere una proprietà C e così via fino a il tipo della proprietà E è qualcosa che potrebbe essere nullo o potrebbe avere una proprietà F .

In altre parole, dobbiamo farlo con un linguaggio tipizzato staticamente o applicare un vincolo sui tipi che possono essere restituiti se la digitazione è libera. Nella maggior parte dei casi, C # utilizza la digitazione statica, quindi non abbiamo modificato nulla.

Se avessimo allora il seguente codice violerebbe anche la legge:

ExplicitType x;
var b = A.B;
if (b == null)
  x = null;
else
{
  var c = b.C;
  if (c == null)
    x = null;
  else
  {
    var d = c.D;
    if (d == null)
      x = null;
    else
    {
      var e = d.E;
      if (e == null)
        x = null;
      else
        x = e.F;
    }
  }
}

Che è esattamente lo stesso . Questo codice che utilizza l'accoppiamento di elementi diversi deve "conoscere" l'intera catena di accoppiamento, ma sta usando un codice che non viola la Legge di Demetra per farlo, con ogni unità avere un accoppiamento ben definito con il prossimo.

    
risposta data 08.10.2015 - 13:06
fonte
5

L'oggetto può essere creato allo scopo di incapsulare comportamenti o contenere dati e gli oggetti possono essere creati allo scopo di essere condivisi con codice esterno o tenuti in privato dal loro creatore.

Gli oggetti che sono creati allo scopo di incapsulare il comportamento (sia condiviso che non), o per essere condivisi con codice esterno (se incapsulano comportamenti o dati) dovrebbero generalmente essere accessibili tramite la loro interfaccia di superficie. Quando gli oggetti di conservazione dei dati vengono creati per essere utilizzati esclusivamente dal loro creatore, tuttavia, non si applicano le normali ragioni di Law of Demeter per evitare l'accesso "profondo". Se parte di una classe che memorizza o manipola i dati nell'oggetto viene modificata in un modo che richiederebbe la modifica di altro codice, sarà possibile garantire che tutto questo codice venga aggiornato perché - come notato sopra - l'oggetto è stato creato per l'uso esclusivo di una classe.

Mentre penso che il?. l'operatore potrebbe forse essere stato progettato meglio, ci sono abbastanza situazioni in cui gli oggetti fanno uso di strutture dati annidate che l'operatore ha molti casi d'uso che non violerebbero i principi espressi dalla Legge di Demetra. Il fatto che possa essere usato per violare il LoD non dovrebbe essere considerato un argomento contro l'operatore, poiché non è peggio del "." operatore al riguardo.

    
risposta data 07.10.2015 - 22:53
fonte

Leggi altre domande sui tag