TUTTE le tue variabili devono essere dichiarate private? [duplicare]

14

So che è meglio restare al sicuro e che dovremmo sempre impedire a altri di accedere direttamente alle proprietà di una classe. Lo sento sempre dai professori universitari, e lo vedo anche in un sacco di codice sorgente pubblicato su App Hub . In realtà, i professori dicono che in realtà prenderanno i voti per ogni variabile che viene dichiarata pubblica.

Ora, questo mi lascia sempre dichiarando variabili come private. Non importa cosa. Anche se ognuna di queste variabili avesse sia un getter che un setter.

Ma ecco il problema: è un lavoro tedioso. Tendo a perdere rapidamente interesse per un progetto ogni volta che ho bisogno di avere una variabile in una classe che potrebbe essere stata semplicemente dichiarata pubblica invece che privata con un getter e un setter.

Quindi la mia domanda è, devo davvero dichiarare tutte le mie variabili private? O potrei dichiarare pubbliche alcune variabili ogni volta che richiedono sia un getter che un setter?

    
posta skizeey 13.03.2011 - 09:24
fonte

10 risposte

19

I responsabili che dicono "SEMPRE fare questo o quello" in merito alla programmazione dovrebbero essere licenziati o tornare a scuola da soli. Nella programmazione non c'è mai un solo modo migliore per fare qualcosa, tutto dipende dalla particolare applicazione.

Esempio per il tuo caso: supponiamo di avere una classe che rappresenta una semplice struttura di configurazione con 10 campi, ma nessuna funzionalità effettiva, quindi nessun metodo tranne un costruttore potrebbe. Tutti i membri possono essere letti / scritti. Personalmente preferirei

class MyConfig
{
public:
  int a;
  int b;
  int c;
  int d;
  int e;
};

molto, molto più del prossimo, che non aggiunge ulteriori funzionalità rispetto all'originale ..

class MyConfig
{
public:
  int GetA() const{ return a; }
  void SetA( int i ){ a = i; }
  int GetB() const{ return b; }
  void SetB( int i ){ b = i; }
//you get the point.. 
private:
  int a;
  int b;
  int c;
  int d;
  int e;
};
    
risposta data 13.03.2011 - 09:54
fonte
27

In generale sì, io e molti altri facciamo eccezioni per i DTO vedere questo breve blogpost di zio Bob Martin.

Se tutto ciò che stai facendo è creare variabili private e usare getter e setter, potresti voler pensare al motivo per cui lo stai facendo? Ci sono un sacco di persone che dicono che getter e setter sono malvagi, vedi questo articolo o questo articolo di Alan Holub. Da quell'articolo:

Summing up

Let's pull everything together: You shouldn't use accessor methods (getters and setters) unless absolutely necessary because these methods expose information about how a class is implemented and as a consequence make your code harder to maintain. Sometimes get/set methods are unavoidable, but an experienced OO designer could probably eliminate 99 percent of the accessors currently in your code without much difficulty.

Getter/setter methods often make their way in code because the coder was thinking procedurally. The best way to break out of that procedural mindset is to think in terms of a conversation between objects that have well-defined responsibilities. Cunningham's CRC card approach is a great way to get started.

    
risposta data 13.03.2011 - 09:51
fonte
9

C'è una buona ragione per usare getter e setter in Java invece di avere campi pubblici.

Il motivo è perché devi sempre code alle interfacce e le interfacce non consentono di specificare campi ma solo metodi.

    
risposta data 13.03.2011 - 10:49
fonte
3

Java, a differenza di altre lingue come Ruby, distingue tra accesso diretto a una proprietà e accesso a una proprietà tramite accessor / mutator. Una buona pratica orientata agli oggetti dice che dovresti, quando possibile, nascondere lo stato interno di un oggetto dall'esterno. Significato, la rappresentazione interna dei dati non deve essere direttamente manipolata da oggetti esterni. Il motivo è che è possibile applicare una logica al valore prima che l'azione venga intrapresa (ad esempio: convalidarlo, pulire una stringa, formattare il reso, ...). Il problema è che la maggior parte delle persone pensa che i "POJO" dovrebbero essere "il più puliti possibile" e finire per implementare queste convalide / formattazioni / ripuliture altrove, lasciando i POJO muti e noiosi da scrivere.

Detto questo, di recente mi sono imbattuto in una libreria chiamata "lombok", che mi permette di scrivere solo le proprietà e genererà i getter / setter al volo. Se ho bisogno di fare qualche logica in più in ogni accessor / mutator, faccio solo l'effettiva implementazione per esso e lombok ignorerà quel metodo specifico.

    
risposta data 13.03.2011 - 11:20
fonte
3

Come dici tu stesso:

But here's the problem: it's tedious work.[emphasis mine] I tend to quickly loose interest in a project every time I need to have a variable in a class that could have simply been declared public instead of private with a getter and a setter.

Stai facendo il giro del noioso lavoro cercando di argomentare la sua necessità fuori dall'esistenza, piuttosto che renderla meno noiosa, che fondamentalmente significa aggirare il problema invece di risolverlo. Per risolverlo:

Utilizza gli strumenti giusti e usali a destra

Se la creazione di semplici accessor è troppo complessa, allora il set di strumenti attuale deve essere migliorato.
Infatti, ogni volta che c'è un lavoro noioso, il tuo set di strumenti ha bisogno di miglioramenti .

Per molte lingue, è disponibile una sorta di zucchero sintattico per creare accessor oppure è possibile utilizzare i preprocessori per questo e la maggior parte degli IDE fornisce snippet di codice / generatori di codice. In effetti, in qualsiasi IDE decente si tratta di una sequenza di tasti per convertire un campo pubblico in privato con accessor.

Potrei fornire una spiegazione piuttosto lunga sul motivo per cui l'utilizzo di campi pubblici viola completamente l'OOP. Allo stesso tempo, OOP non è la verità ultima e talvolta è meglio scegliere consapevolmente un'alternativa, se sai cosa stai facendo e le circostanze sono giuste. Quindi sì, ci sono casi in cui l'uso di semplici campi pubblici è ok.
Questo tuttavia non è il caso, perché non stai prendendo questa decisione in base a vincoli tecnici di alcun tipo, ma solo perché il tuo flusso di lavoro ha bisogno di ottimizzazione.

    
risposta data 08.02.2012 - 16:40
fonte
1

Esponendo i membri sia come campi pubblici che attraverso semplici getter e setter va contro idee originali di OO .

Se stai modellando valori e non oggetti ci potrebbe essere un motivo per modellarli come valori.

Gli oggetti puristicamente parlando riguardano il comportamento ogni variabile membro è un dettaglio dell'implementazione e nessun valore è parte del comportamento. Quindi, se vuoi fare OO puristico ogni volta che vuoi creare un setter o un getter, dovresti porre a te stesso delle domande sul tuo design, visto che la necessità di getter e setter (quando non si parla di valori come appannati agli oggetti) è un odore che non si sta modellando ciò che fa il sistema (comportamento) ma di cosa si tratta (dati). Un paradigma che si concentra sulla separazione di questi concetti è DCI

    
risposta data 08.02.2012 - 15:07
fonte
0

È sempre una parola molto strong, e vorrei evitarlo. Se si tratta solo di una questione di digitazione, è a cosa servono i tasti della tastiera. Scrivi un piccolo script che richiederà un riempimento di origine Java per trovare tutti i vars pubblici convertirli in privato e scrivere i getter e setter per te.

Trovo che sia sempre una buona idea automatizzare le parti di alesatura e piastra di riscaldamento del lavoro. Migliora la qualità del codice perché le cose noiose sono fatte dal computer.

Ricorda solo quanto segue:

  1. Il codice sorgente è solo dati

  2. I programmi manipolano i dati

  3. Scrivi un programma per manipolare i tuoi dati in modi utili!

Buona fortuna!

    
risposta data 13.03.2011 - 10:59
fonte
0

Il punto con i getter / setter rispetto alle variabili pubbliche è la separazione delle preoccupazioni. Le variabili interne sono un dettaglio di implementazione di una classe e quindi non dovrebbero essere viste dall'esterno.

Ciò che dovrebbe essere visibile dall'esterno sono le proprietà che sono gestite dalla classe, e queste proprietà potrebbero non avere una corrispondenza uno-a-uno con le variabili interne.

Ad esempio una classe può gestire una proprietà 'temperatura'. Una variabile interna può essere collegata a questa temperatura ma gli utenti non dovrebbero fare alcuna assunzione di ciò che rappresenta il valore memorizzato in quella variabile: ° C, ° F, ° K, o anche, a seconda del sensore, misura grezza espressa in: mm, V ...

I getter ei setter dovrebbero applicarsi alle proprietà, non alle variabili interne, consentendo così di includere funzioni di calibrazione o conversione.

In questo modo, gli interni di classe possono cambiare senza aggiornare la sua interfaccia e tutti gli altri componenti a seconda della classe.

    
risposta data 08.02.2012 - 15:05
fonte
0

Dopo aver letto alcune risposte il mio primo punto sarebbe che in questo contesto non credo che dovrebbe equivale a dire deve che non è lo stesso che dire devo , penso che tu stia forse sottolineando always .

  • dovrebbe implica che ci sia un consenso generalizzato sul fatto che questo è un approccio migliore o più appropriato
    • tu dovresti dichiarare sempre i tuoi membri privati
  • deve implica che questo è il modo in cui è fatto
    • tu devi dichiarare sempre i tuoi membri privati
  • devono non implica altre opzioni
    • tu devi dichiarare sempre i tuoi membri privati

Effettivamente in tutti e tre gli esempi (in particolare data la circostanza da cui deriva questa domanda) si dovrebbe e IMO dovrebbe (anche se non deve o deve) interrogare qualsiasi istruzione posta loro, questo è il modo in cui si programma il miglior computer di tutti. Ad esempio se qualcuno dicesse che dovresti sempre fare qualcosa nonostante tu sappia che questa volta sarebbe dannoso se lo facessi senza mettere in discussione il loro razionale?

Immagino che in questo caso il tuo tutor (molto probabilmente per facilità) ti abbia ipotizzato, una pratica migliore che in effetti io (e forse molti altri) sarei d'accordo. La domanda che ritengo non dovrebbe mai essere la ragione per cui rendere un membro privato, ma in realtà l'inverso sul perché renderlo pubblico, prendendo come esempio facebook, le persone amano chiaramente divulgare informazioni su se stessi ma, anche allora, forse solo i miei amici possono vederlo la mia famiglia può vederlo, e tu che non conosco non puoi vedere nulla.

Riportando questo a OOP e in particolare a Java, una delle ragioni principali per i getter e setter è IMO (e potrei sbagliarmi) un caso di buona pratica semantica, tu obj.getState() e obj.setState() in contrapposizione a obj.state e obj.state = 'foo' , in entrambi i casi direi che il processo per farlo è imperativo. Mi piacerebbe pensare che l'orientamento all'oggetto non sia solo l'allontanamento da questo paradigma, ma tra l'altro incapsulare dati e funzioni in una componente riutilizzabile. Se non abbiamo nascosto nulla, ci ritroviamo con uno spazio dei nomi per la memorizzazione di dati e metodi?

Un altro punto chiave, credo, si riduce a scavalcare, le classi che ereditano da una classe super contenente variabili pubbliche sono ora bloccate da una variabile pubblica che a mio parere sembra possa portare a una diminuzione della riutilizzabilità. Usando getter e setter hai fornito un modo per le sottoclassi di sovrascrivere l'accesso alle tue variabili, magari aggiungendo quel bit di convalida che non ti sei mai preso la briga.

Per quanto sia noioso per quanto riguarda la scrittura di getter e setter questo è veramente nullo, perché penso che la maggior parte degli IDE farà molto di questo per te (e come ho appena trovato lombok che sembra piuttosto interessante e mi ricorda @property ecc in obiettivo-c)

In breve sì dovresti usare sempre membri privati a meno che tu non abbia una buona ragione per non farlo (i DTO sarebbero, in una certa misura, un'eccezione ragionevole)

    
risposta data 08.02.2012 - 17:06
fonte
-2

Il motivo per cui devi sempre implementare getter e setter è perché tutti ti dicono di farlo (le persone sane lo chiamano Dogma). Nei 10 anni in cui programma Java, probabilmente il 99 percento delle proprietà che ho usato sono pubblicamente disponibili attraverso getter e setter, quindi in pratica sono PUBBLICI. Facilitiamo l'eccezione, invece della regola.

    
risposta data 08.02.2012 - 14:35
fonte

Leggi altre domande sui tag