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.