2012-08-04 14 views
10

Ho notato che anche quando si paga rispetto al singolo principio di responsabilità dell'OOD, a volte le classi diventano ancora grandi. A volte l'accesso alle variabili membro direttamente nei metodi sembra avere uno stato globale e molte cose esistono nell'attuale ambito. Solo osservando il metodo attualmente in uso, non è più possibile determinare da dove provengono le variabili inviduali accessibili nell'ambito corrente.Accedere direttamente alle variabili membro o passare come parametro?

Quando collaboravo con un amico ultimamente, mi sono reso conto di scrivere molto più codice verboso di lui, perché ho passato le variabili membro ancora come parametri in ogni singolo metodo.

Questa cattiva pratica?

edit: Esempio:

class AddNumbers { 
public: 
    int a, b; 
    // ... 
    int addNumbers { 
     // I could have called this without arguments like this: 
     // return internalAlgorithmAddNumbers(); 
     // because the data needed to compute the result is in members. 
     return internalAlgorithmAddNumbers(a,b); 
    } 

private: 
    int internalAlgorithmAddNumbers(int sum1, int sum2) { return sum1+sum2; } 
}; 
+1

Se le tue lezioni sono troppo grandi dividerle. Se hai una variabile membro usalo. Se non stai usando le variabili membro in un metodo dovrebbe probabilmente essere 'statico', ma farlo sembra strano. – Flexo

+1

Scusami, mi sembra di avere un piccolo problema con il tuo inglese. Passi le variabili membro come parametri? Variabili membro pubblico? O nuovi valori per queste variabili membro? Sono un po 'confuso. – ATaylor

+0

Mi dispiace di non averlo capito. Quando si implementa un algoritmo, di solito reiterro i parametri necessari nella firma del metodo, sebbene i dati richiesti dall'algoritmo possano essere effettivamente estratti direttamente dalle variabili membro. Supponiamo che tu abbia una classe, che aggiunge due numeri e ha i 2 numeri aeb come variabili membro. Quindi, invece di avere un metodo di aggiunta privato con parametri zero, definirei comunque una funzione prendendo 2 argomenti int. In questo modo potrei in seguito riutilizzare l'algoritmo anche al di fuori di una classe. – Tom

risposta

5

Se una classe ha variabili membro, usarli. Se si desidera passare esplicitamente i parametri, renderlo una funzione libera. Passare le variabili membro in giro non solo rende il codice più prolisso, ma viola anche le aspettative delle persone e rende il codice difficile da capire.

L'intero scopo di una classe è creare un insieme di funzioni con uno stato condiviso passato implicitamente. Se questo non è ciò che vuoi fare, non usare una classe.

2

Sì, sicuramente una cattiva pratica. Il passaggio di una variabile membro a una funzione membro non ha assolutamente senso, dal mio punto di vista. Essa ha diversi svantaggi:

  1. codice Diminuzione leggibilità
  2. costo in termini di prestazioni per copiare il parametro sullo stack

Alla fine la conversione del metodo per una semplice funzione, può avere senso. In effetti, dal punto di vista delle prestazioni, le chiamate a funzioni non membri sono in realtà più veloci (non è necessario dereferenziare questo puntatore).

MODIFICA:

Risposta al tuo commento. Se la funzione può eseguire il proprio lavoro utilizzando solo alcuni parametri passati in modo esplicito e non ha bisogno di alcun stato interno, probabilmente non c'è motivo di dichiarare che abbia una funzione membro. Usa una semplice chiamata di funzione in stile C e passa i parametri ad essa.

+0

Questo è esattamente il mio punto nella domanda. Perché ritengo che in realtà _ aumenti la leggibilità del codice, che nessun nome magico esterno compaia nel tuo ambito locale. Molto tempo fa mi è stato insegnato che le variabili globali hanno uno stile molto negativo e l'accesso a una variabile membro a volte sembra utilizzare variabili globali. Stai accedendo a qualcosa che non è né nel tuo ambito locale, né passato dall'esterno come parametro. – Tom

+1

@Tom: i memebers di classe non sono globali: sono deliberatamente esplicitamente locali rispetto all'istanza della classe con cui si sta lavorando. La tua classe è un incapsulamento di qualche piccolo stato correlato. Se non lo sono, hai problemi di progettazione più grandi che non possono essere rattoppati in questo modo. Nell'esempio che hai dato sarei tentato di rendere le tue istanze immutabili anche. – Flexo

1

Ho capito il problema, avendo dovuto mantenere grandi classi nel codice che non ero originariamente autore. In C++ abbiamo la parola chiave const per aiutare a identificare i metodi che non cambiano lo stato:

void methodA() const; 

L'utilizzo di questo aiuta manutenibilità perché possiamo vedere se un metodo può modificare lo stato di un oggetto.

In altre lingue che non dispongono di questo concetto preferisco essere chiaro sul fatto che sto cambiando lo stato della variabile di istanza da un'averlo passato per riferimento o di ritorno il cambiamento

this->mMemberVariable = this->someMethod(); 

Piuttosto che

void someMethod() 
{ 
    this->mMemberVariable = 1; // change object state but do so in non transparent way 
} 

Ho trovato nel corso degli anni che questo rende più facile da mantenere il codice.