È meglio generare una lista grande durante il costruttore o quando vi si accede?

4

Ho una funzione membro della classe che genera un elenco di grandi dimensioni e la inserisce in una variabile membro privata, in modo che sia accessibile tramite un getter. La generazione di questa lista è un processo piuttosto intenso (nei miei test è solo un secondo, ma con dataset più grandi mi aspetto che ci vorrà molto più tempo), che comporta un sacco di ricorsione e andare avanti e indietro su sottoliste. Questa funzione è pubblica in modo che l'elenco possa essere rigenerato in qualsiasi momento, indipendentemente dal fatto che l'inizializzazione "naturale" si sia verificata o meno.

Dato tutto questo, è meglio impostare le cose in modo che la lista sia generata quando l'oggetto è costruito, o per far sì che generi la lista quando viene chiamata la funzione getter se la lista non è ancora stata generata?

Inoltre, dovrei aggiungere che assumiamo che l'elenco sia aggiornato e non debba essere modificato finché l'utente non ci dice specificatamente di aggiornarlo.

    
posta SenorMeltyface 09.11.2017 - 20:58
fonte

4 risposte

7

Dipende.

Se la lista deve essere costruita prima, durante o dopo la costruzione delle altre parti dell'oggetto dipende dal contesto, come questo influenza la testabilità e cosa si aspetterebbe da un utente di quella classe sul comportamento della classe.

Generare la lista quando viene chiamata la funzione getter (se non è stata generata allora) ha più senso se si hanno situazioni in cui oggetti di quella classe potrebbero essere usati senza mai chiamare quella funzione getter. Anche un caso di test unitario può giustificare l'implementazione di questo tipo di caricamento lento, se la generazione dell'elenco rallenta troppo il test. Viene fornito al prezzo di rendere le cose più complesse e rendere meno prevedibile il comportamento temporale del getter (e forse il suo comportamento di lancio delle eccezioni).

Generare la lista in anticipo (e iniettarla nel costruttore) potrebbe essere la migliore se si può vedere questa come una responsabilità da sola, che potrebbe essere testata o riutilizzata separatamente, e che non richiede l'accesso ai campi privati del classe in gioco. Tuttavia, probabilmente non è una buona idea se l'elenco debba essere aggiornato automaticamente dall'oggetto in un secondo momento.

Per i casi rimanenti, la generazione dell'elenco nel costruttore (o al momento della costruzione, ma utilizzando una fabbrica o un oggetto del costruttore iniettati) è probabilmente la strada da percorrere. Se il contenuto dell'elenco deve essere aggiornato in un secondo momento, la logica per questo o parti di esso può essere facilmente riutilizzata dal costruttore e dalla funzione che aggiorna il contenuto.

    
risposta data 09.11.2017 - 22:36
fonte
3

Nessuno dei due!

In entrambi i casi violerei due principi importanti.

Come ci riesci? Facendo generare la lista grande qualcos'altro lavoro. Una volta generato si passa un riferimento alla lista nel costruttore dell'oggetto che lo userebbe. Ora non esiste nulla che non possa essere usato e la costruzione di un oggetto costa tanto quanto l'aggiunta del puntatore.

La parola di fantasia per questo è un'iniezione di dipendenza, ma noi vecchi scolari ricordiamo con il nome di riferimento che passa.

    
risposta data 09.11.2017 - 21:32
fonte
0

Se si utilizza .net, generalmente si considera una cattiva pratica creare un metodo di acquisizione delle proprietà long run (o indeterminatamente long running):

  • gli utenti API si aspettano che i metodi get vengano restituiti in un breve lasso di tempo costante e possono essere tranquillamente utilizzati nei loop.
  • Problemi del debugger: quando si esamina un'istanza in una gente del posto, in un orologio o in una finestra di controllo rapido, verrà eseguito il codice a esecuzione lunga.

Per gli stessi motivi, i metodi get di proprietà generalmente non dovrebbero generare eccezioni. Vedi anche . Linee guida per la progettazione di framework net .

    
risposta data 10.11.2017 - 17:34
fonte
0

Non si specifica la lingua, ma ecco una risposta (leggermente complessa), orientata a Java. E sono leggermente stantio sul mio Java, quindi potrebbe essere leggermente sbagliato.

  1. Il costruttore non crea l'elenco. Ma costruisce qualcosa come un FutureTask che può calcolare la lista.

  2. Qualcuno TBD, probabilmente il costruttore è il più semplice, inizia a eseguire quell'attività su un thread separato. Questa è la parte leggermente complessa. Se l'elenco deve essere ricalcolato, utilizzare un approccio simile.

  3. Il metodo getList() restituisce theFuture.get()

risposta data 10.11.2017 - 07:41
fonte