È una buona pratica di programmazione non usare getter e setter in parti banali del codice?
Non secondo me. (Perché penseresti diversamente?)
Per lo meno, la coerenza dovrebbe essere un fattore importante in una base di codice , quindi avrei pensato che se si utilizzano getter / setters dovrebbero essere utilizzati globalmente.
Inoltre, ciò che è banale ora potrebbe finire per essere una grande distanza da banale in sei mesi, quindi sarebbe ingenuo presumere il contrario e trattare tali segmenti di codice in modo diverso.
È buona prassi di programmazione non utilizzare getter e setter in classi che sono intese per essere più di un fascio di dati (come un C struct
). Espongono la struttura interna della classe, violando l'incapsulamento e aumentando notevolmente l'accoppiamento. I metodi pubblici dovrebbero essere usati per esprimere operazioni significative a seconda di ciò che rappresenta la classe, non secondo l'implementazione.
Per le classi che sono fondamentalmente pacchetti di dati, sono più complicate del semplice rendere pubblici i dati di classe, ma offrono un controllo leggermente maggiore. A volte preferisco le variabili pubbliche perché sono più pulite, ma i setter consentono di inserire i ganci nelle modifiche, il che mi ha permesso di risparmiare un sacco di lavoro una volta.
Una classe con ampie coppie getter / setter potrebbe essere mal progettate (in quanto potrebbe essere scarsamente incapsulata nei dettagli dell'implementazione). Ma i getter / setter stessi di solito non sono il problema in uno scenario del genere, il semplice fatto che i dati siano pubblici spesso lo è, quindi in un tale scenario un grande elenco di variabili pubbliche potrebbe essere altrettanto negativo.
È davvero difficile dire senza vedere esempi concreti; Personalmente vorrei evitare di fare generalizzazioni come quella nella tua domanda (preferendo invece affermazioni più deboli che coinvolgono "potrebbe", "potrebbe essere", "possibilmente", eccetera). Se una classe è pensata per essere un'astrazione di livello molto elevato, dovrebbe probabilmente avere un minor numero di coppie get / set banali rispetto a qualcosa che modella un concetto di livello inferiore.
Se, in particolare, intendi codice "banale" per essere un codice one-off specifico per testare un'idea o programmi molto piccoli, probabilmente non c'è bisogno di sovradimensionare o sovrastimolare la soluzione.
Direi che tu vuoi TDD (e con questo intendo Test driven Design ) i tuoi oggetti. Ti renderai presto conto se hai davvero bisogno di quegli setter e getter. Personalmente, scrivo solo il codice che devo.
Oh, e se il tuo progetto in seguito dice che ho bisogno di tutti quei getter e setter, allora questo è ciò che gli IDE moderni sono per:)
Nessun codice è banale
Se, in fase di esecuzione, la CPU lo esegue, non è banale perché sta avendo un effetto.
Tutto incapsula
Se vuoi violare praticamente ogni consiglio sull'incapsulazione dei dati nel libro OOP, esponi semplicemente lo stato interno del tuo oggetto a tutti. Basta rendere pubblico il campo e partire. In breve tempo tutti i riferimenti che stai distribuendo verranno modificati da una chiamata remota di una chiamata di una chiamata e il tuo oggetto non sarà più saggia - fino a quando non verrà eseguita un'operazione che genera un errore epico.
Fallimento epico? Non voglio che ...
Se vuoi assicurarti che solo il tuo oggetto stia cambiando il suo stato interno allora i getter / setter sono la strada da percorrere. Il getter / setter sorveglia lo stato interno assicurandosi che le classi esterne non abbiano altro modo di arrivarci. (OK, sento la sottoclasse, la riflessione yada yada ...)
Hai un esempio per comprovarlo?
Considera di esporre gli array. Se lo fai direttamente attraverso un getter, come questo (in Java)
public byte[] getRedBackgroundPDF() {
return this.redPDF;
}
si ottiene un errore epico perché il byte[]
viene passato per riferimento e quindi le classi esterne possono modificare gli interni della classe, ignorando lo scopo del getter. Il PDF può essere modificato in qualche modo (diciamo per farlo avere uno sfondo blu) e la tua classe non ne ha idea.
Per superare questo problema, devi clonare in modo che le classi esterne ottengano effettivamente una versione di sola lettura di byte[]
.
public byte[] getRedBackgroundPDF() {
return Arrays.copyOf(this.redPDF,this.redPDF.length) ;
}
Il codice esterno potrebbe cambiare in blu, ma ogni volta che qualcun altro visita il metodo getRedBackgroundPDF()
inizieranno sempre con uno sfondo rosso.
Sembra inutile e brutto, ma protegge il tuo stato interno.
Secondo Jon Skeet (di StackOverflow fame) -
What is a trivial property ? It's one that’s read/write and that stores its value in a straightforward private variable without any validation or other custom code. Trivial properties only take a few lines of code, but it’s still a lot when you consider that you’re only expressing a very simple concept.
Where previously you might have been tempted to use a public variable for the sake of simplicity, there’s now even less excuse for not using a property instead. This is particularly true for throwaway code—which we all know tends to live far longer than anticipated.
MODIFICA - Suggerirei di utilizzare per utilizzare le proprietà automatiche ove possibile. Per me mi fa capire a un solo sguardo che questa proprietà non sta facendo niente di speciale. Inoltre rende il codice più leggibile.
L'idea di getter e setter è un estremismo assolutamente stupido, quindi non dovresti usarli. Ecco perché:
Se hai un tipo di prodotto come una struct in C, allora ti vengono fornite le proiezioni categoriali (getter) come parte della lingua e dovresti usarle. In C sono anche utili per impostare un valore e anche operazioni di lettura / modifica / scrittura. I prodotti sono tipi di dati concreti, non c'è nulla di astratto su di loro e i loro dati dovrebbero essere pubblici. Alcune lingue idiote nascondono i dati per impostazione predefinita o consentono di leggere ma non di scrivere.
Le astrazioni dovrebbero essere evitate a tutti i costi. L'astrazione è dispendiosa dal punto di vista computazionale, e non intendo per il computer (anche se di solito è così): intendo per il cervello umano. Basta guardare tutta la ridicola immondizia nei linguaggi OO rispetto alla semplice codifica in un linguaggio funzionale: anche i linguaggi poveri come C possono essere molto espressivi.
L'astrazione è utile quando hai invarianti e ne sei sicuro e vorrai farle rispettare. In questo caso, in genere i costruttori stabiliscono l'invariante, i dati sono nascosti per impedire l'uso delle proiezioni per rompere l'invariante e quindi è necessario che gli accessori ottengano informazioni sul valore dell'oggetto.
Se l'oggetto è mutevole, chiaramente hai bisogno di un modo per modificarlo.
Tuttavia, questi non sono "getter e setter" nel senso di impostare i componenti di un tipo di prodotto, perché è ciò che si sta tentando di impedire, poiché alcuni valori della struttura dati privata non rappresentano valori del tipo astratto.
Sì. Non uso get / set per gli attributi privati se non vengono utilizzati al di fuori della classe e la classe non può essere ereditata.
Se è necessario accedere all'attributo al di fuori della classe, un get / set è in ordine. Un get senza set per una classe immutabile, un get / set per mutable.
Quando ho bisogno di avere un sacco di questi, prendo il mio IDE e glielo faccio generare per me.
Leggi altre domande sui tag programming-languages