Qual è il punto delle proprietà?

10

Ecco alcuni argomenti per le proprietà e i miei argomenti contrari:

Più facile da usare rispetto alla scrittura di metodi getter e setter

Le coppie metodo Getter e setter sono un odore di codice. Rendere più facile la scrittura di questi è come rendere più facile fallire un test di matematica usando un modulo di Scantron e compilando tutte le "C". Gli oggetti che contengono solo lo stato, per la persistenza, non dovrebbero utilizzare getter / setter e dovrebbero creare oggetti immutabili al momento della persistenza.

Ciò che è importante per un consumatore di un oggetto è ciò che fa, non come lo fa. Il suo comportamento è quello che fa; il suo stato è come lo fa. Se ti stai preoccupando dello stato di un oggetto (eccetto per la persistenza, anche se questo rompe anche OO), semplicemente non stai facendo OOP e perdi i suoi vantaggi.

Forniscono un'indicazione approssimativa delle prestazioni ai consumatori

Questo è qualcosa che potrebbe cambiare in futuro, per qualsiasi proprietà data. Supponiamo che nella versione 1.0, l'accesso a PropertyX restituisca semplicemente un campo. Nella versione 1.5, se il campo è nullo, PropertyX utilizza il modello Oggetto Nullo per creare un nuovo oggetto nullo. Nella versione 2.0, il campo viene ulteriormente convalidato dal metodo getter in PropertyX.

Poiché la proprietà diventa sempre più complessa, l'indicazione delle prestazioni dell'utilizzo di una proprietà sembra sempre meno veritiera.

Sono migliori dei campi pubblici

Questo è vero. Ma anche i metodi.

Rappresentano un aspetto fondamentalmente diverso di un oggetto rispetto a un metodo, e tutti i consumatori dell'oggetto dovrebbero occuparsi di questo

Sei sicuro che entrambe le affermazioni precedenti sono vere?

Sono più facili da digitare, man

Certo, digitare myObject.Length è più semplice che digitare myObject.Length() , ma non è possibile che sia corretto con un po 'di zucchero sintattico?

Perché utilizzare i metodi anziché le proprietà?

  • Nessuna garanzia di rendimento. L'API rimarrà veritiera anche se il metodo diventa più complesso. Il consumatore dovrà profilare il proprio codice se è in esecuzione per problemi di prestazioni e non fare affidamento su word-of-API.

  • Meno per il consumatore a cui pensare. Questa proprietà ha un setter? Un metodo sicuramente no.

  • Il consumatore sta pensando da una corretta mentalità OOP. Come consumatore di un'API, sono interessato a interagire con il comportamento di un oggetto. Quando vedo le proprietà nell'API, sembra molto simile allo stato. Infatti, se le proprietà fanno troppo, non dovrebbero nemmeno essere proprietà, quindi in realtà le proprietà in uno stato API sono come appaiono ai consumatori.

  • Il programmatore dell'API analizzerà in modo più approfondito i metodi con i valori restituiti ed eviterà di modificare lo stato dell'oggetto in tali metodi, se possibile. La separazione dei comandi dalle query dovrebbe essere applicata ovunque sia possibile.

Quindi ti chiedo, perché usare le proprietà invece dei metodi? La maggior parte dei punti su MSDN sono odori di codice in e di se stessi e non appartengono a nessuno dei due metodi o proprietà.

(Questi pensieri mi sono venuti dopo aver pensato a CQS.)

    
posta xofz 26.03.2011 - 22:47
fonte

10 risposte

44

Perché "metodi contro le proprietà"? Un metodo fa qualcosa. Una proprietà è, beh, un membro di un oggetto. Sono cose completamente diverse, anche se due tipi di metodi comunemente scritti - getter e setter - corrispondono alle proprietà. Dato che confrontare le proprietà con i metodi in generale non è significativo, presumo che intendiate parlare di getter / setter.

Getter and setter method pairs are a code smell.

Non necessariamente, direi, ma in ogni caso non si tratta di getter / setter rispetto alle proprietà, ma della necessità di utilizzare entrambi. Si noti inoltre che è possibile ad es. lascia la parte setX proprio come puoi creare proprietà di sola lettura.

What is important to a consumer of an object is what it does, not how it does it. Its behavior is what it does; its state is how it does it. If you find yourself caring about an object's state (except for persistence, though this also breaks OO), you're simply not doing OOP and losing out on its advantages.

Un'attitudine altamente discutibile. Se la GUI vuole esportare i dati detenuti da un DataStuffManagerImpl , deve in qualche modo ottenere quel numero (e no, inserire metà dell'applicazione nella classe widget non è un'opzione).

As the property gets more and more complex, the performance indication of using a property seems less and less truthful.

[Methods have] No performance guarantees. The API will remain truthful even if the method gets more complex. The consumer will need to profile their code if they are running in to performance issues, and not rely on word-of-API.

In quasi tutti i casi, tutta la logica di convalida, ecc., è ancora efficacemente O (1), o altrimenti in termini di costi. Altrimenti, forse sei andato troppo lontano ed è ora di cambiare. E un metodo getX() di solito viene trattato anche come economico!

Sure, typing myObject.Length is easier than typing myObject.Length(), but couldn't that be fixed with a little syntactic sugar?

Proprietà sono quello zucchero sintattico.

Less for the consumer to think about. Does this property have a setter? A method sure doesn't.

"C'è un setter per questo getter?" Stessa differenza.

The programmer of the API will think more deeply about methods with return values, and avoid modifying the object's state in such methods, if possible. Separation of commands from queries should be enforced wherever possible.

Non sono sicuro di cosa stai cercando di dirci qui. Per le proprietà, c'è una legge non scritta ancora più strong che non causa effetti collaterali.

    
risposta data 26.03.2011 - 23:13
fonte
19

Getter and setter method pairs are a code smell.

Questa è un'ipotesi errata e completamente errata. I metodi Get / Set sono un modo per incapsulare un membro dati e non sono in alcun modo un "odore di codice". Odio davvero il modo in cui alcune persone gettano il termine "odore di codice", ma comunque ...

This is something that could change in the future, for any given property. Suppose in release 1.0, accessing PropertyX simply returns a field. In release 1.5, if the field is null, PropertyX uses the Null Object pattern to create a new null object. In release 2.0, the field is getting further validated by the getter method in PropertyX.

As the property gets more and more complex, the performance indication of using a property seems less and less truthful.

Sembra un'API mal progettata, non vedo come sia colpa della sintassi delle proprietà.

Le proprietà in C # erano semplicemente zucchero sintattico per un modello molto comune che rendeva le nostre vite di programmatori un po 'più semplici. Tuttavia, al giorno d'oggi, se si desidera utilizzare l'associazione dei dati, è necessario "utilizzare" le proprietà, quindi ora sono un po 'più dello zucchero sintattico. Immagino di non essere affatto d'accordo con nessuno dei tuoi punti e non capisco perché non ti piaccia una caratteristica linguistica che supporta direttamente un modello comune.

    
risposta data 26.03.2011 - 23:11
fonte
9

La tua premessa è sbagliata.

Le proprietà non sono in alcun modo un contratto per le prestazioni o l'implementazione interna o qualsiasi altra cosa.
Le proprietà sono coppie di metodi speciali, che rappresentano semanticamente un attributo, se vuoi. E quindi il contratto solo è, che una proprietà si comporta come ci si aspetterebbe da un attributo.
Se chiedo il colore di un oggetto, non presumo se è ottenuto da un semplice accesso al campo o se è calcolato appena in tempo.
L'obiettivo è di avere la capacità di esporre il comportamento di un attributo utilizzando i metodi, mentre è trasparente per il consumatore dell'interfaccia, indipendentemente dal fatto che tu stia utilizzando un campo o accessorie.

Avere attributi (e in realtà nascondere la loro implementazione, poiché le proprietà si oppongono ai campi) è una potente funzione dichiarativa , che è la base per avere gli ispettori degli oggetti visivi e altre generazioni di visualizzazioni automatiche, per l'associazione dei dati e molte altre cose utili. E, soprattutto, trasporta chiaramente queste informazioni anche per i tuoi colleghi programmatori.

    
risposta data 27.03.2011 - 14:12
fonte
6

The consumer is thinking from a proper OOP mindset. As a consumer of an API, I am interested in interacting with an object's behavior. When I see properties in the API, it looks a lot like state. In fact, if the properties do too much, they shouldn't even be properties, so really, properties in an API ARE state as they appear to consumers.

Una proprietà è supposta come uno stato. Se il setter o il codice getter sottostante cambia per aggiungere significativamente all'elaborazione richiesta per impostare o ottenere lo stato, in realtà non è più una proprietà e dovrebbe sostituirlo con i metodi. Questo dipende da te come sviluppatore del codice.

Mettere troppo (quanto è troppo dipende) il codice in un setter o getter è sbagliato, ma solo perché è possibile non è un motivo per gettare il modello in tutti i casi.

    
risposta data 27.03.2011 - 14:28
fonte
6

Una cosa che ti manca e non so se questo è dovuto all'ignoranza o se stai intenzionalmente trascurando questo dettaglio, è che i metodi ARE sono metodi.

Quando usi la sintassi della proprietà di C #, il compilatore crea tranquillamente i metodi getter e setter con i metadati che indicano alle lingue che comprendono le proprietà come una funzione sintattica di prima classe per trattarle come tali. Questo è, in effetti, lo zucchero sintattico che stai chiedendo. Alcune lingue che possono essere eseguite sul CLR non nascondono completamente questo dettaglio da te (Boo, se la memoria serve me e alcune implementazioni Lisp), e puoi chiamare i getter e setter in modo esplicito.

Le proprietà occasionalmente hanno effetti collaterali, come l'attivazione degli eventi di notifica delle modifiche (ad esempio, INotifyPropertyChanged) o il contrassegno di un'istanza di una classe come sporca. È qui che hanno il loro valore reale, anche se la loro creazione è un po 'più di lavoro (eccetto in Boo, che ha macro di sintassi).

Ora, la domanda più ampia è se i metodi getter e setter siano, in realtà, una buona cosa. Ci sono chiaramente dei compromessi; se hai metodi mutator, il tuo codice è intrinsecamente meno parallelizzabile, perché ora devi affrontare i problemi di sincronizzazione dei thread. Ed è del tutto possibile che rischierai di violare la Legge di Demetra usando metodi di mutatore (sia chiamati proprietà o metodi getter / setter, che sono equivalenti), perché è davvero conveniente farlo.

Ma a volte è la cosa giusta da fare. A volte il tuo problema è quello di prendere i dati da qualche fonte, cambiarli un po ', presentare i dati aggiornati all'utente e salvare le modifiche. Questo idioma è ben servito dalle proprietà. Come dice l'articolo di Allen Holub , solo perché getter e setter hanno problemi Significa che non dovresti mai usarli. (Pappagallo astratto Guruspeak considerato dannoso). Anche quando segui l'approccio Classe / Responsabilità / Collaboratori, finisci comunque per divulgare informazioni o presentazioni di informazioni a qualcuno; il punto è minimizzare l'area di superficie dell'entanglement.

Il vantaggio delle proprietà è che è molto facile avere un altro oggetto traendone vantaggio. Il rovescio della medaglia è che è molto facile avere un altro oggetto traendone vantaggio e non è facile prevenirlo.

La mutazione degli oggetti ha senso a livello di controller, ad esempio in un'architettura MVC. Questo è il tuo collaboratore. Il tuo punto di vista è anche un collaboratore, ma non dovrebbe mutare direttamente i tuoi oggetti, perché ha responsabilità diverse. Il rollare il codice di presentazione nei tuoi oggetti di business non è necessariamente il modo giusto per evitare getter / setter.

L'equazione cambia un po 'se si usano astrazioni funzionali, piuttosto che OO, astratte, che in genere rendono piuttosto banale la realizzazione di copie di un oggetto "record" con un paio di modifiche, sebbene non siano gratuite. E hey, se stai cercando di ottenere garanzie sulle prestazioni, le proprietà sono generalmente più prevedibili rispetto alla ricostruzione lenta di una collezione immutabile.

    
risposta data 27.03.2011 - 19:54
fonte
5

Un altro motivo importante nel mio libro per l'utilizzo delle proprietà è che possono aumentare notevolmente la leggibilità.

account.setBalance(Account.getBalance()+deposit);

è chiaramente molto meno leggibile di

account.Balance += deposit;
    
risposta data 27.03.2011 - 07:46
fonte
4

Hai quasi il punto di vista religioso opposto a me:)

Quando mi sono trasferito da Delphi a Java, la mancanza di proprietà è stata un enorme affronto per me. Ero abituato a dichiarare una proprietà ea puntarla direttamente su una variabile privata o scrivere un getter & protetto setter poi "plumbing" loro alla proprietà. Questo incapsulò la proprietà e controllò come dovrebbe essere accessibile in un modo chiaro e non ambiguo. Si può avere una proprietà di sola lettura che calcola il totale quando vi si accede e chiamarla "Total" non "_getTotal ()" o simili ballochs. Significava anche che si poteva limitare l'accesso alle proprietà rendendole protette nella classe base astratta, quindi spostandole in pubblico o pubblicate in sottoclassi.

Per me, le proprietà sono più naturali e amp; modo espressivo di impostare & ottenere lo stato dell'oggetto. Affidarsi a convenzioni di codifica non forzate è più un "odore di codice" di qualsiasi cosa si stia criticando per le proprietà. Inoltre, come altri hanno detto, inventando un uso mal progettato delle proprietà e usando i suoi difetti per provare & respingere il concetto di proprietà in generale è una forma estremamente cattiva. È possibile che tu abbia visto solo un cattivo uso di proprietà e amp; Supponiamo che sia così, suppongo, ma dovresti fare più ricerche prima di diventare troppo dogmatico.

    
risposta data 30.09.2011 - 03:02
fonte
1

Una delle ragioni per cui le proprietà sono state introdotte in Java Beans Framework era quella di consentire l'integrazione con un IDE - è possibile trascinare tali componenti sull'IDE e modificare le proprietà utilizzando gli editor di proprietà.

(a quei tempi erano solo getter e setter regolari - ed erano definiti solo dalla convenzione di denominazione - e questo effettivamente annusava)

Oggi ci sono ancora più casi in cui le proprietà sono accessibili e modificate non tramite codice normale, ad esempio durante il debug.

    
risposta data 27.03.2011 - 08:22
fonte
1

Un altro angolo: provenivano davvero da VB. Ricorda, nei giorni bui del XX secolo, quando .NET era stato concepito, l'enfasi principale era che fosse un rimpiazzo facile e immediato per VB in modo che i tuoi programmatori VB potessero semplicemente trascinare le cose su webform. VB aveva proprietà quindi era necessario mantenere quella caratteristica affinché le cose venissero tradotte correttamente.

    
risposta data 27.03.2011 - 16:54
fonte
1

Ci sono almeno due scopi per le proprietà:

  • Sono concettualmente identici ai campi anche se sono implementati in modo diverso. Un getter non dovrebbe cambiare lo stato dell'oggetto e non dovrebbe avere effetti collaterali. Un setter dovrebbe cambiare lo stato solo in modo concettualmente simile a modificare un campo e non avere altri effetti collaterali.

  • Sono sintatticamente identici ai campi pubblici (possibilmente di sola lettura). Ciò significa che un campo pubblico può essere modificato in una proprietà senza rompere i chiamanti al livello di origine.

risposta data 27.03.2011 - 17:06
fonte

Leggi altre domande sui tag