Posizionamento dei metodi di supporto [duplicato]

2

Ecco una domanda che mi ha sempre infastidito. Userò java come esempio perché non ho quasi mai incontrato un problema in java in cui non avevo bisogno di usare metodi helper nella sua struttura di classe.

Diciamo che ho un metodo che fa una cosa o due e poi chiama un metodo di supporto:

public void doStuff() {
    int x = 4;
    int y = 5;
    doStuffHelper(x, y);
}

Ora ho bisogno di creare un metodo privato, doStuffHelper , che doStuff chiama con x e y. Per la leggibilità, metto sempre l'helper direttamente sopra o sotto la funzione, ma non riesco mai a decidere quale sia il migliore. Quali sono i tuoi pensieri / esperienze con esso?

So che la domanda sembra banale, ma dal momento che non ho alcun principio guida su questo, trovo che uccida sempre il tempo di codifica per decidere cosa fare e riorganizzare il mio codice se non funziona. Se non c'è consenso, penso che sia il momento di impegnarsi finalmente l'uno sull'altro per me.

    
posta user1427661 04.05.2013 - 06:37
fonte

2 risposte

4

Ho sempre messo la funzione doStuffHelper in seguito. Questo lo rende più facile da leggere, poiché quando inizi a leggere il codice dall'alto, non devi prima ricordare cosa fa doStuffHelper (senza comprenderne il contesto) e poi mentre lo ricordi, leggi la funzione fare cose(). Invece leggi la funzione doStuff () che dovrebbe essere la funzione "principale" della classe, capisci cosa sta cercando di fare, quindi leggi la funzione doStuffHelper ().

Un po 'come la differenza tra una frase passiva e una frase attiva in inglese.

    
risposta data 04.05.2013 - 13:11
fonte
3

Le funzioni di ordinazione sono una preoccupazione valida e importante e alcuni schemi funzionano meglio di altri. Come i commenti e @Lachlan suggeriti, mettere gli aspetti fondamentali della classe in precedenza spesso ha più senso.

Spesso preferisco vedere le cose statiche precedere le cose dell'istanza e pubblico prima del privato. Preferisco vedere i dati e le cose creazionali prima di vedere le cose da fare. Nello specifico, preferisco vedere costruttori, inizializzazioni, getter e setter e quindi metodi di attività. Cerco spesso di mettere le funzioni di aiuto immediatamente dopo la prima funzione che lo usa, invece di lasciarle cadere in fondo. Perché questo ordine di base?

  • Costruttori: prima che tutto possa essere fatto con un oggetto, deve essere creato. Come con getter e setter, voglio sapere subito se c'è qualcosa di diverso su come l'oggetto gestisce la sua costruzione, e cosa succederebbe se altri effetti collaterali potessero verificarsi dai vari metodi di costruzione (tutti inizializzano esplicitamente, o solo in alcuni casi?).

  • Inizializzazione: quale impostazione viene eseguita per me e cosa devo probabilmente fornire per fare effettivamente qualcosa di utile con questo oggetto

  • Getter e setter: voglio sapere in anticipo se c'è qualcosa di strano su come i valori vengono letti o scritti. Stanno usando qualsiasi tipo di blocco multi-threading per limitare l'accesso che potrebbe distorcere il modo in cui normalmente anticiperei il funzionamento del getter o setter? Accedono al backing store in modo non standard, come l'utilizzo di una matrice indicizzata o una raccolta di valori anziché una variabile discreta? O stanno scrivendo le modifiche ad un database mentre la proprietà è cambiata [ all'interno della proprietà]? E quali altri effetti collaterali potrebbero verificarsi cambiando o accedendo allo stato sottostante?

  • Funzioni attività: queste sono le funzioni che definiscono la responsabilità primaria della classe o del modulo. Come ho detto, mi piace mettere i metodi helper che sono esplicitamente parte della classe, più vicini al punto in cui sono per primi, o che probabilmente saranno usati per primi.

Man mano che organizzi quelle funzioni "extra" con le funzioni del compito principale, dovresti sempre tenere a mente la seguente domanda: in che modo questa funzione di aiuto si riferisce all'unica responsabilità e una ragione per cambiare per questa classe?

Le funzioni extra [private] sono inevitabili nel corso delle funzioni di refactoring fino al loro scopo principale, ma attenzione che alcune di queste funzioni extra potrebbero violare Principio di responsabilità singola (SRP) e" un motivo per cambiare "per la classe.

Il caso potrebbe essere che le funzioni di aiuto meritano una classe a parte, forse diverse. Un modo per valutare se una funzione rimane o passa a casa sua è guardando coesione . I parametri che la funzione accetta e i valori interni che manipola sono variabili fondamentali per la classe? Sono variabili che sono comunemente usate nel resto della classe, o sono per lo più utilizzate solo da un numero molto piccolo di funzioni secondarie? Se la funzione non usa, o usa solo alcune di quelle variabili di classe o stato interno, potrebbe indicare una bassa coesione e una strong candidatura per la promozione in una classe separata, e un metodo leggermente diverso di invocare quel metodo di supporto.

Un esempio abbastanza comune di dove ciò si verifica è con oggetti che hanno aiutanti di formattazione o helper di input e output. Gli helper che eseguono una conversione della rappresentazione degli oggetti nella o dalla rappresentazione gestita dal modello sono in genere buoni candidati per la propria classe di formattazione. Normalmente, un oggetto non dovrebbe avere la responsabilità di caricare o salvare il proprio stato, dato che sanguina i dettagli di implementazione nel modello. Tale attività è spesso indicata da parole o abbinamenti come:

  • da o a
  • converti o configura o trasforma
  • leggi o scrivi
  • carica o salva
  • riproduci o registra
  • avvia o sospende (e probabilmente resetta a seconda della classe / contesto)

Molte lingue e framework hanno spesso alcuni metodi incorporati per convertire la rappresentazione interna dello stato di un oggetto in un altro modulo di base. Spesso prende la forma di 'stringare' o qualche leggera variazione di questo. Di solito questo viene fornito per due motivi: per semplificare determinati aspetti e aspettative della piattaforma e per comodità. È una licenza per moderare eccessivamente e estendere il metodo in modo che una rappresentazione di base di un oggetto complesso possa essere comunicata al resto del framework, ma non dovrebbe essere considerata una licenza per dare a una classe più responsabilità di quella ha bisogno.

    
risposta data 15.06.2013 - 01:04
fonte

Leggi altre domande sui tag