Argomenti del metodo: più specifici o più generali?

0

Saluta il metodo:

public void hello(Data data);

Questo metodo utilizza alcuni dati ed esegue ... qualunque cosa. Ora, scritto in questo modo, il metodo è molto specifico - cioè l'argomento è molto specifico. Ma ora, nella vita reale, questo Data (ad esempio) può provenire da es. classe chiamata DataProvider :

public class DataProvider() {
    public Data getMeData(int from, int to);
}

Ora, la maggior parte delle volte in cui chiamiamo hello dobbiamo chiamare dataProvider.getMeData() . Poiché questo è ripetitivo, puoi fare:

public void hello(int from, int to);

Che è essenzialmente:

public void hello(DataProvider dp);

Questo sembra conveniente poichè, forse, in futuro, avrò bisogno di dati diversi oltre alla classe Data , e nessuna firma verrà modificata. In altre parole, il metodo stesso sapere quali dati prendere.

Questo secondo caso è un esempio di un metodo con argomenti più generali.

Quale avrebbe più senso:

  • Il primo, più rigoroso, più mirato.
  • Il secondo, generico, ma meno mirato.

Non si tratta di passare oggetti personalizzati. In entrambi i casi, vengono passati oggetti personalizzati. La differenza è che l'ambito di passaggio dell'oggetto è diverso. Il primo contiene solo dati grezzi. Il secondo è più generale, contiene più ciò di cui ha bisogno quel metodo.

    
posta igor 29.07.2016 - 11:08
fonte

5 risposte

4

Penso che la linea guida più pertinente sia il Principio di responsabilità singola . Un metodo che è responsabile dell'elaborazione di un oggetto Data non dovrebbe avere alcun business nella creazione o nel recupero di esso. Invece, dovrebbe essere passato come dipendenza; proprio quello che fa la tua prima versione.

Non sono d'accordo che la seconda versione sia, in generale, più generica. Funziona solo per Data oggetti recuperati da DataProvider specificando una coppia di int s. La prima versione funzionerà con qualsiasi Data , indipendentemente da dove provenga.

Se ti trovi a digitare

hello(this.dataProvider.getMeData(14, 92));

molto, non c'è niente di sbagliato nell'aggiungere un metodo di convenienza private

private void helloData(final int from, final int to) {
    hello(this.dataProvider.getMeData(from, to));
}

a quel class e usalo internamente come this.helloData(14, 92) . Il contrario: rendere la funzione che prevede un DataProvider e una coppia di int s per accettare un oggetto Data proveniente da altrove, tuttavia, non è altrettanto facilmente possibile.

    
risposta data 29.07.2016 - 18:48
fonte
1

Quindi stai chiedendo quando introdurre un ulteriore livello di astrazione per disaccoppiare parti di codice. È impossibile dare una risposta generale. La maggior parte degli sviluppatori segue la propria esperienza e il principio aperto / chiuso .

… maybe, in future, I will need different data …

La migliore risposta che posso dare in base alle informazioni fornite: Non ne hai bisogno!

    
risposta data 29.07.2016 - 13:21
fonte
1

Il metodo hello dovrebbe richiedere esattamente i parametri di cui ha bisogno per fare qualsiasi cosa. Se l'elenco dei parametri è lungo, il metodo potrebbe violare il Principio di responsabilità singola.

Uno dei motivi principali di ciò è la testabilità. Se il metodo richiede un DataProvider , è necessario creare una serie di oggetti nidificati per testare il metodo. Se il metodo accetta int s, devi solo aggiungere un paio di% di% di sconto e ... il gioco è fatto.

Una volta testato il metodo, non si desidera cambiarlo. Se i requisiti cambiano, lasciare il metodo originale da solo e sovraccaricarlo o sovrascriverlo. Questo è il principio Open-Closed.

    
risposta data 29.07.2016 - 19:39
fonte
0

Come già sottolineato dall'altra risposta, puoi prendere una decisione caso per caso basata su principi standard come OCP o YAGNI .

Successivamente, ha generalmente senso distinguere due diversi livelli di astrazione:

  1. Al livello inferiore, il metodo hello fa parte di un componente più piccolo e piuttosto lontano dalle interfacce di servizio.

In tal caso, in genere si desidera che l'argomento sia il più generico possibile per il riutilizzo. Anche se "generico" qui si riferisce ai dati, non alla creazione o al recupero dei dati.

Ad esempio, non vuoi che la hello signature richieda un ArrayList quando sarebbe sufficiente una più generica List o Collection di interfaccia.

  1. A livello superiore, il metodo hello può essere considerato una sorta di facciata per molte funzionalità più profonde, realizzate da più classi o quant'altro.

In tal caso, le modifiche apportate alla funzionalità possono richiedere rapidamente una modifica della firma dei dati. Quindi, per non dover cambiare sempre quella firma vitale, ha più senso in uno scenario del genere ottenere più dati di quelli di cui potresti aver bisogno al momento.

In breve, la divertente conclusione è che l'ambito del metodo determina l'ambito dei dati che richiede. Duh, lo so.

    
risposta data 29.07.2016 - 14:59
fonte
0

Domanda: quale è, se possibile, la relazione tra from e to ?

Se possono essere "più nulla", quindi aggiungere un argomento in più per qualcosa di più generale e più facile da testare è una vittoria.

Ma se ci sono relazioni e restrizioni complesse, ad es. le variabili sono in realtà la pagina di un libro e la parola su quella pagina, o l'indice di un tag XML e l'indice di uno dei suoi figli, quindi può essere indicato un oggetto più specifico (che tu sai essere valido).

    
risposta data 30.07.2016 - 06:15
fonte

Leggi altre domande sui tag