È meglio eseguire un calcolo nel setter del campo o avere un metodo diverso?

0

Sto implementando un semplice oggetto Quota che determina una percentuale di utilizzo basata su maximum e used .

private int maximum;
private int used;

public Quota(int used, int maximum) {
    this.maximum = maximum;
    this.used = used;
}

public double getUsagePercentage() {
    return ((double) used / (double) maximum) * 100.0;
}

public int getMaximum() {
    return maximum;
}

public void setMaximum(int maximum) {
    this.maximum = maximum;
}

public int getUsed() {
    return used;
}

public void setUsed(int used) {
    this.used = used;
}

Mi sono reso conto che avrei potuto farlo in un altro modo, però, e in realtà ho la logica del setter:

private int maximum;
private int used;
private double percentageUsed;

public Quota(int used, int maximum) {
    this.maximum = maximum;
    this.used = setUsed(used);
}

public int getMaximum() {
    return maximum;
}

public void setMaximum(int maximum) {
    this.maximum = maximum;
    percentageUsed = ((double) used / (double) maximum) * 100.0;
}

public int getUsed() {
    return used;
}

public void setUsed(int used) {
    this.used = used;
    percentageUsed = ((double) used / (double) maximum) * 100.0;
}

public double getUsagePercentage() {
    return percentageUsed;
}

Il secondo modo sembra molto, molto più brutto per me, ma forse sono solo indottrinato. Ovviamente mi rendo conto che la logica viene copiata tra i due setter, ma anche se l'hai estratta nel suo metodo di supporto private , ottieni il punto. Ho pensato che forse questo era l'approccio migliore in modo che il calcolo della percentuale non dovesse accadere ogni volta che viene chiamato il metodo getUsagePercentage() . Se non sono stati modificati né i valori maximumused , sembra inutile continuare a eseguire un'operazione a cui già conosciamo la risposta.

Esiste un precedente per cui scegliere l'altro? Mi piace il primo migliore solo perché ho fatto Java per sempre, ma non è un argomento valido per mantenerlo in quel modo. Quali sono i vantaggi e gli svantaggi di entrambi? O è veramente, oggettivamente migliore dell'altro?

    
posta asteri 23.01.2015 - 19:31
fonte

2 risposte

6

Se imposti il valore (massimo) e poi aggiorni il prossimo (usato) (e anche più spesso - pensa a una barra di avanzamento) stai facendo il calcolo due volte e, peggio ancora, nessuno ha chiesto i valori tra il setXY -alle azioni. Perché spendere tempo per cose che nessuno realmente richiede. Quindi è perfettamente bene usare il getter per calcolare il valore reale ogni volta che è necessario. Come hai scoperto, stai violando il DRY (non ripeterti) -Principle. Con setter più complessi e calcoli complessi, il tuo compromesso sarà ancora più peggio. Il tuo primo esempio va bene.

    
risposta data 23.01.2015 - 19:59
fonte
3

Una linea guida comune è che per ogni fatto noto dal tuo sistema, ci dovrebbe essere solo un posto dove è memorizzato. In un database, questo è noto come normalizzazione; nella progettazione di oggetti il principio viene a volte indicato come "Punto singolo della verità" o l'acronimo SPOT. Questo è strettamente correlato al principio "non ripeterti" (ASCIUTTO), e infatti in una formulazione di DRY è in realtà identico:

"Ogni pezzo di conoscenza deve avere una singola, non ambigua, autorevole rappresentazione all'interno di un sistema."

Nel tuo esempio, ci sono due punti di verità per la percentuale: la variabile che lo memorizza direttamente e le variabili che contengono i valori interi completi da cui è calcolato. Questo non è un problema particolarmente grave, perché i due si trovano all'interno di una singola classe e possono quindi essere gestiti, ma a meno che tu non abbia una buona ragione per farlo, lo eviterei.

    
risposta data 23.01.2015 - 20:08
fonte

Leggi altre domande sui tag