2009-09-11 13 views
9

È stato fornito da Microsoft come linea guida per la progettazione di framework che properties deve essere indipendente l'uno dall'altro e non fare affidamento sull'essere impostato in un ordine specifico.Nozioni di base di C# Creazione di proprietà atomiche

Si supponga di avere una classe triangolo che deve supportare dimmensions e un calcolo di area. Come modellerai questo?

Questo è naturalmente il design che è considerato gauche zona, perché dipende dalla base e altezza stato impostato prima:

class Triangle{ 
    public double Base {get;set;} 
    public double Height {get;set;} 
    public double Area { 
     get{ 
      return (Base * Height)/2; 
     } 
    } 
} 

Supponendo di utilizzare un costruttore, è possibile garantire i valori predefiniti per questo caso, ma è questo il approccio corretto?

class Triangle{ 
    public Triangle(double b, double h){ 
     Base = b; 
     Height = h; 
    } 

    public double Base {get;set;} 
    public double Height {get;set;} 
    public double Area { 
     get{ 
      return (Base * Height)/2; 
     } 
    } 
} 

Hai ancora una proprietà che ha una dipendenza da altre proprietà. Al fine di essere un purista che posso vedere solo alcuni approcci (immagino che potrebbero essere combinati):

  1. fare la base/altezza avere membri di sola lettura che può essere impostato solo nel costruttore

  2. Marchio il calcolo dell'area in un metodo.

  3. Utilizzare un tipo di schema factory + readonly membri per garantire che sebbene la dipendenza possa esistere, i valori possono essere impostati solo dal metodo che crea un'istanza della classe Triangle.

Domande:

  1. è la linea guida pratica (dovete modellare un sacco di complessità nelle vostre classi al fine di sostenerlo)? [ad esempio, una classe SqlConnection consente di inizializzare la proprietà della stringa di connessione ma consente di modificare singole parti come timeout del comando]

  2. Come si gestiscono le proprietà indipendentemente l'una dall'altra?

  3. Extra per le persone che utilizzano l'architettura di tipo Silverlight/MVVM, si accettano le dipendenze nelle proprietà a causa del modo in cui il database si collega a un oggetto? Ad esempio, vincola un'istanza triangolare che mostra altezza, base e area sullo schermo.

risposta

15

Microsoft sta veramente cercando di dire "Non progettare la classe in modo tale che chiamare immobili a un ordine arbitrario causerà un comportamento imprevisto." Gli utenti della tua classe non si aspettano di richiedere un valore (usando una proprietà) per avere effetti collaterali scomodi.

Questo rientra nel principio della sorpresa minima.

Penso che questa sia una linea guida completamente pratica da seguire. Le proprietà non dovrebbero avere effetti collaterali imprevisti.

Si pone una domanda eccellente: "Come gestisci il mantenimento delle proprietà indipendenti l'una dall'altra?". Molto attentamente! Elimina lo stato (e riduco il numero di proprietà di conseguenza) il più possibile. Inoltre, lo stato di partizione suddividendo le classi è un'altra tattica. Questo sarebbe un'ottima domanda da solo ...

In termini di classe del triangolo, penso che entrambe le soluzioni presentate in codice siano valide. Se dipendesse da me, disegnerei il triangolo in modo che sia immutabile e prenda la larghezza e l'altezza nel costruttore.

+0

Bello e conciso. –

3

Il modo più semplice sarebbe quella di accettare i valori di base e l'altezza solo sul costruttore e poi esporre tutti loro come proprietà di sola lettura:

class Triangle 
{ 
    private double base; 
    private double height; 

    private Triangle() { } 

    public Triangle(double base, double height) 
    { 
     this.base = base; 
     this.height = height; 
    } 

    public double Base 
    { 
     get 
     { 
     return this.base; 
     } 
    } 

    public double Height 
    { 
     get 
     { 
     return this.height; 
     } 
    } 

    public double Area 
    { 
     get 
     { 
     return (this.base * this.height)/2; 
     } 
    } 
} 
+1

Perché dovresti esporli come readonly? Quindi, non puoi cambiare il triangolo ... Naturalmente, se vedi il triangolo come un tipo di valore (e quindi immutabile), allora hai un punto, ma è necessario in questo esempio per fare un triangolo a tipo di valore? ... Penso che l'argomento abbia semplicemente interpretato male le linee guida. :) –

+1

Rendi gli oggetti sempre immutabili, a meno che tu non abbia un valido motivo per non farlo. Il triangolo è un buon esempio: perché mai vorresti cambiarlo invece di crearne uno nuovo? Non è che gli oggetti Mutabili siano inizialmente orribili, ma ne inseriamo uno in uno scenario multi-thread e all'improvviso hai bisogno di sincronizzazione senza una buona ragione se non che il programmatore dell'oggetto "Triangolo" ha deciso di programmare con i setter. –

+0

Non è possibile utilizzare base come nome di variabile, è una parola chiave. Inoltre, non può essere un nome parametro e un nome di variabile di classe –

2

penso che vorrei andare per una classe triangolo che ha un costruttore che prende la Base & Altezza come parametri, poiché un Triangolo non può esistere (imho) senza una base o un'altezza.

Offcourse, la proprietà Area ha una dipendenza su Base & Altezza, ma non vedo alcun problema in questo? Credo che la linea guida MS dovrebbe essere interpretato come segue:

proprietà devono essere indipendenti l'uno dall'altro e non invocare essere insieme in qualsiasi ordine specifico.

Significato: significa che non si deve avere un vincolo per il quale è necessario impostare la proprietà Base e solo quando è stata impostata la proprietà Base, è possibile impostare la proprietà Height.
Penso che questo sia ciò che si intende per la suddetta linea guida.

Accanto a questo, la proprietà Area non è impostabile, quindi non ci sono problemi con esso. :)

0

Alcune proprietà saranno intrinsecamente correlate e codipendenti. Il punto è che prima si imposta la base, quindi l'altezza dovrebbe avere lo stesso effetto dell'altezza di impostazione, quindi base. Non impostare uno di questi, quindi controllare l'area non avrebbe senso.

0

Scegliere l'opzione 2. Crea un metodo e chiamalo CalculateArea. Le proprietà dovrebbero essere utilizzate per incapsulare lo stato e non il comportamento. Quella Area può essere calcolata da Base e Altezza non significa che dovrebbe essere essa stessa stato; al contrario, questo è un argomento forte secondo il quale Area dovrebbe non essere stato.

class Triangle 
{ 
    public Triangle(double b, double h) 
    { 
     Base = b; 
     Height = h; 
    } 

    public double Base { get; set; } 
    public double Height { get; set; } 

    public double CalculateArea() 
    { 
     return (Base * Height)/2; 
    } 
} 

In questo modo i consumatori sanno che ottenere l'area del triangolo richiede un lavoro vero e proprio, piuttosto che semplicemente accedendo Stato.

Problemi correlati