Domanda

A questa domanda ha già una risposta qui:

Allen Holub ha scritto il seguente,

Non è possibile avere un programma senza qualche accoppiamento.Tuttavia, è possibile ridurre al minimo accoppiamento notevolmente da pedissequamente seguenti OO (object-oriented), precetti (il più importante è che l'attuazione di un oggetto dovrebbe essere completamente nascosti da oggetti che lo uso).Per esempio, un oggetto che le variabili di istanza (membro campi che non sono costanti), dovrebbe essere sempre privato.Periodo.Senza eccezioni.Mai.Voglio dire che.(In alcuni casi è possibile utilizzare i metodi protetti in modo efficace, ma protetto le variabili di istanza sono un abominio.)

Che suona ragionevole, ma poi va a dire,

Si dovrebbe non utilizzare mai get/set di funzioni per la stessa ragione—sono solo troppo complicato modi per fare un campo pubblico (se l'accesso a funzioni che restituiscono completa di oggetti, piuttosto che una base di tipo valore sono ragionevoli in situazioni in cui l'oggetto restituito la classe è una chiave di astrazione nel design).

Il che, francamente, solo che suona folle per me.

Capisco il principio di information hiding, ma senza funzioni di accesso e mutator si poteva utilizzare Java beans a tutti.Non so come si dovrebbe seguire una MVC design senza funzioni di accesso nel modello, in quanto il modello non può essere responsabile per il rendering della vista.

Tuttavia, io sono un giovane programmatore e imparare di più su di Progettazione Orientata agli Oggetti di tutti i giorni.Forse qualcuno con più esperienza può pesare su questo problema.

Allen Holub articoli per riferimento


Le Domande Relative A:

È stato utile?

Soluzione

Non ho un problema con Holub che ti dice che si dovrebbe in genere non alterare il Stato di un oggetto, ma invece ricorrere a metodi integrati (esecuzione di comportamenti) per raggiungere questo fine. Come Corletk fa notare, non v'è saggezza nel pensare a lungo e duramente per il più alto livello di astrazione e non solo di programmazione sconsideratamente con getter / setter che solo consentono di fare un fine-correre incapsulamento.

Comunque, ho una grande quantità di problemi con chi ti dice che si dovrebbe "mai" usare setter o dovrebbe "mai" di accesso tipi primitivi. In effetti, lo sforzo richiesto per mantenere questo livello di purezza in tutti casi possono e finirà per causare una maggiore complessità nel codice che utilizzare le proprietà in modo appropriato implementate. È solo avere abbastanza buon senso da sapere quando si sta costeggiando le regole per guadagno a breve termine a scapito di dolore a lungo termine.

Holub non si fida di conoscere la differenza. Credo che conoscere la differenza è ciò che ti rende un professionista.

Altri suggerimenti

Leggere questo articolo con attenzione. Holub sta spingendo il punto che getter e setter sono un male "antipattern default", una cattiva abitudine che si scivola in fase di progettazione di un sistema; perché possiamo.

Il processo di pensiero dovrebbe essere lungo le linee; Che cosa significa questo oggetto do ? Quali sono le sue responsabilità? Quali sono i suoi comportamenti? Che cosa sa? Pensare a lungo e duramente su queste domande che conduce naturalmente verso la progettazione di classi che espongono l'interfaccia più alto livello possibile.

Una macchina è un buon esempio. Si espone una ben definito, un'interfaccia standard di alto livello. Io non mi occupo di setSpeed(60) ... è che MPH o km / h? Ho solo accelerare, da crociera, decelerare. Io non devo pensare ai dettagli in setSteeringWheelAngle(getSteeringWheelAngle()+Math.rad(-1.5)), ho appena turn(-1.5), ei dettagli sono curati sotto il cofano .

Si riduce a "Si può e si deve capire che cosa ogni classe sarà utilizzato per, quello che fa, ciò che rappresenta, ed esporre il più alto livello possibile di interfaccia che soddisfa questi requisiti. Getter e setter sono di solito un COP- fuori, quando il programmatore è solo quello pigro per fare le analisi necessarie per determinare esattamente ciò che ogni classe è ed è-no, e così andiamo giù per il sentiero di "si può fare qualsiasi cosa". getter e setter sono il male!

A volte le reali esigenze per una classe sono inconoscibile prima del tempo. Che figata, basta cop-out e utilizzare getter / setter antipattern per ora, ma quando si conosce, attraverso l'esperienza, ciò che la classe viene utilizzato per, probabilmente si vorrà di rimonta e la pulizia dell'interfaccia sporca di basso livello. Refactoring sulla base di "roba che si desidera si sapeva quando si scrive la ventosa in primo luogo" è par per il corso. Non è necessario sapere tutto, al fine di fare un nuovo inizio, è solo che più ti conosco, il meno rilavorazione è probabile che sia richiesto al momento la strada.

Questa è la mentalità che sta promuovendo. Getter e setter sono una trappola facile cadere.

Sì, i fagioli in pratica richiedono getter e setter, ma per me un fagiolo è un caso speciale. Fagioli rappresentano nomi, cose, materiali identificabili (se non fisici) oggetti. Non un sacco di oggetti in realtà hanno comportamenti automatici; la maggior parte delle volte le cose sono manipolati da forze esterne, compreso l'uomo, per rendere loro le cose produttive.

daisy.setColor(Color.PINK) ha perfettamente senso. Che altro si può fare? Forse un Vulcan fusione mentale, per fare il fiore volete per essere rosa? Hmmm?

getter e setter hanno la loro? Il male? posto. E 'solo, come tutte veramente buoni cose OO, si tende a farne un utilizzo eccessivo di loro, perché sono sicuro e familiare, per non parlare di semplice, e quindi potrebbe essere migliore se niubbi non hanno visto o sentito parlare di loro, almeno fino a quando' d padronanza della cosa fusione mentale.

Credo che ciò che Allen Holub cercato di dire, riformulato in questo articolo , è il seguente.

  

getter e setter può essere utile per le variabili che si specificamente bisogno di incapsulare, ma non c'è bisogno di usarli per tutte le variabili. In realtà, che li utilizzano per tutte le variabili è brutto odore di codice.

I programmatori hanno difficoltà, e Allen Holub era proprio di segnalarlo, è che a volte usano getter / setter per tutte le variabili. E lo scopo di incapsulamento è perduto.

(nota Vengo a questo da un angolo di .NET "proprietà")

Bene, semplicemente - non sono d'accordo con lui; egli fa una grande confusione sul tipo di ritorno di proprietà di essere una cosa negativa, perché può rompere il vostro codice chiamante - ma esattamente lo stesso ragionamento si applica a argomenti di metodo. E se non è possibile utilizzare i metodi sia?

OK, argomenti del metodo potrebbe essere cambiato come ampliamento conversioni, ma .... solo perché ... Si noti inoltre che in C # la parola var potrebbe attenuare un sacco di questo percepito dolore.

accessor sono non un dettaglio di implementazione; essi sono il pubblico API / contratto. Yup, se si interrompe il contracft hai problemi. Quando ha fatto che diventare una sorpresa? Allo stesso modo, non è raro per le funzioni di accesso di essere non banale - vale a dire che fanno più di solo campi avvolgere; effettuano calcoli, controlli logici, notifiche, ecc E permettono astrazioni basate interfaccia di stato. Oh, e il polimorfismo -. Etc

Re la natura verbose di funzioni di accesso - in C # (p3 4??):. public int Foo {get; private set;} - lavoro fatto

In definitiva, tutto il codice è un mezzo per esprimere la nostra intenzione al compilatore. Proprietà mi permetta di farlo in un type-safe, su base contrattuale, verificabile, estensibile, modo polimorfico - grazie. Perché ho bisogno di "fissare" questo?

getter e setter vengono utilizzati come poco più di una maschera per fare un pubblico privato variabile.

Non ha senso ripetere quello che ha detto già Holub, ma il punto cruciale è che le classi devono rappresentare un comportamento e non solo dello stato.

Ho fatto qualche ulteriore ricerca con Google su Allen Holub, sembra che egli ha la sua parte di avversari, c'comunità Java.

L'ultimo è particolarmente appuntito.Commentatore del testo è in corsivo.

Se getIdentity inizia con "get", non è una funzione perché non solo il ritorno di un campo.Restituisce un oggetto complesso che ha un comportamento ragionevole

Oh, ma aspetta...quindi è bene utilizzare le funzioni di accesso, come lungo come restituire gli oggetti, invece di tipi primitivi?Ora che è una storia diversa, ma è altrettanto stupido per me.A volte hai bisogno di un oggetto, a volte hai bisogno di un tipo primitivo.

Inoltre, ho notato che Allen ha radicalmente ammorbidito la sua posizione, poiché la sua colonna precedente sullo stesso argomento, dove il mantra "non utilizzare Mai accessori" non soffrire una sola eccezione.Forse si rese conto, dopo qualche anno che le funzioni di accesso non servono a uno scopo, dopo tutto...

Tenete a mente che io in realtà non ho messo alcun codice dell'interfaccia utente nella logica di business.Ho scritto il livello di interfaccia utente in termini di AWT (Abstract Window Toolkit) o Swing, che sono entrambi strato di astrazione.

Buona.Che cosa succede se si sta scrivendo un applicazione su SWT?Come "astratto" è davvero AWT in quel caso?Semplicemente faccia:questo consiglio semplicemente ti porta a scrivere codice dell'interfaccia utente in una logica di business.Che cosa un grande principio.Dopo tutto, è solo da almeno dieci anni, da quando abbiamo identificato questa pratica come una delle peggiori decisioni di progettazione si possono fare in un progetto.

Il mio problema è come un programmatore alle prime armi è a volte inciampo su articoli su internet e li danno più credito quindi dovrei.Forse questo è uno di quei casi.

Quando le idee come queste vengono presentate a me, mi piace dare un'occhiata a librerie e framework che uso e che ho come l'utilizzo.

Per esempio, anche se alcuni non saranno d'accordo, mi piace l'API Java Standard. Mi piace anche la Spring Framework. Guardando le classi in queste librerie, si noterà che molto raramente ci sono setter e getter che sono lì solo per esporre qualche variabile interna. Ci sono metodi nome GetX, ma questo non significa che si tratta di un getter nel senso convenzionale.

Quindi, penso che abbia un punto, ed è questo: ogni volta che si preme scegliere "Generare getter / setter" in Eclipse (o il vostro IDE di scelta), si dovrebbe fare un passo indietro e chiedersi cosa si sta facendo . E 'davvero opportuno esporre questa rappresentazione interna, o fatto io rovinare il mio progetto ad un certo punto?

Non credo che sta dicendo non usare mai get / set, ma piuttosto che utilizzando get / set per un campo non è migliore di appena rendendo il campo pubblico (ad esempio pubblica string Nome vs. Nome public string {get; set; }).

Se si utilizza get / set che limita le informazioni che nasconde delle OO che può potenzialmente bloccare in una brutta interfaccia.

Nel precedente esempio, il nome è una stringa; cosa succede se vogliamo cambiare il disegno seguito per aggiungere più nomi? L'interfaccia esposta una sola stringa in modo non possiamo aggiungere altro senza rompere implementazione esistente.

Tuttavia, se invece di usare get / set inizialmente aveva un metodo come Add (string name), internamente si potrebbe elaborare nome singolarmente o aggiungere a un elenco o cosa non e chiamare dall'esterno il metodo Add tutte le volte che si vogliono aggiungere altri nomi.

L'obiettivo è quello di progettare OO con un livello di astrazione; non esporre più in dettaglio di quanto è assolutamente necessario.

È probabile che se hai appena finito di girare un tipo primitivo con un get / set hai rotto questo principio.

Naturalmente, questo è se si crede negli obiettivi OO; Trovo che la maggior parte non, non proprio, semplicemente utilizzare gli oggetti come un modo comodo per gruppo di codice funzionale.

Le variabili pubbliche hanno senso quando la classe non è altro che un insieme di dati con alcuna reale coerenza, o quando è davvero, davvero elementare (ad esempio una classe punto). In generale, se c'è qualsiasi variabile in una classe che si pensa probabilmente non dovrebbe essere pubblico, il che significa che la classe ha una certa coerenza, e le variabili hanno un certo rapporto che deve essere mantenuta, in modo da tutte le variabili devono essere privati.

getter e setter hanno senso quando riflettono una sorta di idea coerente. In una classe poligonale, per esempio, le coordinate x ed y del dato vertici hanno un significato fuori del confine classe. Probabilmente senso avere getter, ed è probabile che senso avere setter. In una classe di conto bancario, il saldo è probabilmente memorizzato come una variabile privata, e quasi certamente dovrebbe avere un getter. Se ha un setter, ha bisogno di avere la registrazione costruito nel preservare verificabilità.

Ci sono alcuni vantaggi di getter e setter su variabili pubbliche. Essi forniscono una certa separazione di interfaccia e implementazione. Solo perché un punto ha una funzione .getX() non significa che ci deve essere un x, poiché .getX() e .setX() possono essere fatti funzionare bene con coordinate radiali. Un altro è che è possibile mantenere invarianti di classe, facendo tutto ciò che è necessario per mantenere la classe coerente all'interno del setter. Un altro è che è possibile avere funzionalità che si innesca su un set, come la registrazione per il saldo del conto bancario.

Tuttavia, per più classi astratte, le variabili membro perdono significato individuale, e hanno senso solo nel contesto. Non è necessario conoscere tutte le variabili interne di una classe C ++ flusso, per esempio. Hai bisogno di sapere come ottenere gli elementi dentro e fuori, e come eseguire varie altre azioni. Se avete contato sulla struttura interna esatto, devi essere impantanati in dettaglio che potrebbe arbitrariamente variare tra compilatori o versioni.

Quindi, direi di usare variabili private quasi esclusivamente, getter e setter dove hanno un significato reale nel comportamento oggetto, e non altrimenti.

Solo perché getter e setter sono spesso abusato non significa che siano inutili.

Il problema di getter / setter è che cercano di incapsulamento falso, ma in realtà si rompono esponendo i loro interni. In secondo luogo si sta cercando di fare due cose separate - che fornisce l'accesso e il controllo il loro stato -. E finiscono per fare né molto bene

Si rompe l'incapsulamento, perché quando si chiama un metodo get / set è necessario prima conoscere il nome (o avere una buona idea) del campo che si desidera modificare, e in secondo luogo si deve sapere che è di tipo ad es. Non si potrebbe chiamare

setPositionX("some string");

Se si conosce il nome e il tipo di campo, e il setter è pubblico, quindi chiunque può chiamare il metodo, come se si trattasse di un campo pubblico in ogni caso, è solo un modo più complicato di farlo, quindi perché non solo semplificare esso e ne fanno un campo pubblico, in primo luogo.

Per consentire l'accesso al suo stato, ma cercando di controllare allo stesso tempo, un metodo get / set solo confonde le cose e finisce per entrambi essere inutile caldaia-piastra, o fuorvianti, non effettivamente facendo quello che dice lo fa da avendo effetti collaterali l'utente potrebbe non aspettarsi. Se è necessario il controllo degli errori, potrebbe essere chiamato qualcosa come

public void tryPositionX(int x) throws InvalidParameterException{
    if (x >= 0)
        this.x = x;
    else
        throw new InvalidParameterException("Holy Negatives Batman!");
}

o sia necessario un codice aggiuntivo che potrebbe essere definito un nome più accurata in base a ciò l'intero metodo fa ad es.

tryPositionXAndLog(int x) throws InvalidParameterException{
    tryPositionX(x);
    numChanges++;
}

IMHO che necessitano di getter / setter per fare qualcosa di lavoro è spesso un sintomo di cattiva progettazione. Fare uso del principio di "dire, non chiedere", o ri-pensare il motivo per cui un oggetto deve inviare i dati è stato in primo luogo. Esporre metodi che modificano il comportamento di un oggetto anziché suo stato. I vantaggi di che includono una più facile manutenzione e una maggiore estensibilità.

Si parla di MVC troppo e dire un modello non può essere responsabile per la sua vista, per quel caso Allen Holub fornisce un esempio di fare un livello di astrazione da avere una "classe do-me-a-JComponent-che-rappresenta-il-tuo-identità" che dice avrebbe "isolare il modo in cui le identità sono rappresentate dal resto del sistema." Non ho abbastanza esperienza di commentare se che avrebbe funzionato o no, ma in superficie suona un'idea decente.

getter pubblici / setter sono male se prevedono l'accesso ai dettagli di implementazione. Eppure, è ragionevole fornire l'accesso alle proprietà di oggetto e utilizzare getter / setter per questo. Ad esempio, se auto ha la proprietà di colore, è accettabile lasciare che i clienti "osservare" usando un getter. Se qualche cliente ha bisogno della capacità di ricolorare una macchina, la classe in grado di fornire un setter ( 'recolor' è il nome più chiaro però). E 'importante non lasciare che i clienti sanno come proprietà vengono memorizzate in oggetti, come si sono mantenuti, e così via.

Ummmm ... è che non ha mai sentito parlare del concetto di incapsulamento. Metodi getter e setter sono messe in atto per controllare l'accesso ai membri di una classe. Facendo tutti i campi pubblicamente visibile ... chiunque poteva scrivere quello che volevano i valori a loro in tal modo completamente invalidare l'intero oggetto.

Nel caso in cui qualcuno è un po 'confusa sul concetto di incapsulamento, leggere su di esso qui:

Encapsulation (Computer Science)

... e se sono davvero il male, avrebbe NET costruire il concetto di proprietà nel linguaggio? (Metodi getter e setter che basta guardare un po 'più bella)

Modifica

L'articolo fa menzione Encapsulation:

" getter e setter può essere utile per le variabili che si specificamente bisogno di incapsulare, ma non c'è bisogno di usarli per tutte le variabili. In realtà, che li utilizzano per tutte le variabili è brutto odore di codice. "

Con questo metodo porterà a molto duramente per mantenere il codice nel lungo periodo. Se si scopre a metà strada attraverso un progetto che si estende anni che un campo ha bisogno di essere incapsulato, si sta andando ad avere per aggiornare tutti i riferimenti di quel campo in tutto il mondo nel software per ottenere il beneficio. Suona molto più intelligente per un uso corretto Encapsulation su fronte e il mal di testa in seguito al sicuro da soli.

Credo che getter e setter deve essere utilizzato solo per le variabili che si ha la necessità di accedere o modificare al di fuori di una classe. Detto questo, non credo che le variabili devono essere pubblici meno che non siano statici. Ciò è dovuto al fatto che fanno variabili pubbliche che non sono statici può portare a loro di essere cambiato indesiderato. Diciamo che si dispone di uno sviluppatore che sta noncuranza utilizza variabili pubbliche. Ha poi accede a una variabile da un'altra classe e senza volerlo, lo cambia. Ora ha un errore nel suo software a causa di questo incidente. Ecco perché io credo nel corretto utilizzo di getter e setter, ma non li hanno bisogno per ogni variabile privata o protetta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top