Un metodo "start", "run" o "execute" è una buona pratica?


30

Attualmente sto lavorando su una base di codice che ha molte classi che implementano un metodo Start. Mi sembra una costruzione a due fasi, che avevo sempre considerato una cattiva pratica. Non so distinguere tra questo e un costruttore.

Quando è appropriato utilizzare un metodo di avvio anziché la normale costruzione di oggetti?

Quando dovrei preferire usare il costruttore?

Modifica: non credo sia rilevante, ma il linguaggio di programmazione è C #, potrebbe valere anche per Java o C ++


3
Potresti aggiungere un po 'più di contesto? Linguaggio? Discussione vs thread singolo? differenza tra starte il costruttore? ecc ...

@MichaelT Posso capire perché me lo stai chiedendo, ma sono interessato al principio generale dietro quando è appropriato. Sono preoccupato che se fornissi esempi specifici dalla base di codice su cui sto lavorando, le risposte sarebbero troppo focalizzate sui dettagli e non sulle mie domande specifiche.
Dave Hillier,

2
@DaveHillier Ad esempio, in perl è pratica standard (e buona) avere un initmetodo di qualche tipo al di fuori della newfunzione - perldoc.perl.org/perlobj.html . I modi di dire di una lingua possono funzionare bene lì e non in altre lingue.

1
Esempi di classi con Startmetodi in API comuni includono thread e cronometri.
luiscubal,

1
Contami tra quelli che hanno bisogno di un esempio di codice per capire cosa stai effettivamente chiedendo.
user16764,

Risposte:


44

Un Start()metodo (come Run(), Execute()o qualcosa di simile) è appropriato quando il costo di costruzione dell'oggetto è bassa, ma il costo di utilizzo è alto. Ad esempio: una classe che incapsula un algoritmo di ottimizzazione del percorso ottimale. È banale impostarlo con un set di parametri ( Xquadrati per Yquadrati, con metodo di valutazione suchandsuch), ma potrebbe richiedere del tempo per essere eseguito. Se vuoi creare 20 di questi oggetti, potresti voler ritardare l'esecuzione fino a quando non sono stati creati tutti - questo ti consente di parallelizzarli più facilmente, ad esempio.

In alternativa, potrebbe essere utile quando non sai quando sarà necessario avviare l'oggetto, forse perché è basato sull'input dell'utente o sulla logica che seleziona da un elenco di possibilità.

Ciò presuppone, naturalmente, che Start()sia il metodo utile sull'oggetto e non equivalente a un Initialize()metodo. Se è solo un modo aggiuntivo per impostare più parametri, non dovrebbe esistere.


1
Un altro uso di un metodo di avvio è quando l'azione eseguita crea anche un nuovo thread di lavoro o un timer. Il costruttore non dovrebbe fare questo tipo di sollevamento pesante o generare effetti collaterali significativi (come la creazione di un nuovo thread).
Ziv,

50

Code Complete (e molte altre risorse di ingegneria del software) enfatizza l'adattamento delle classi agli oggetti del mondo reale. Credo che la ragione fondamentale di ciò sia che rende più probabile che tu abbia una vera comprensione di ciò che stai implementando, piuttosto che hackerare un'idea immateriale.

Se sei un abbonato a questa teoria, non vedo nulla di sbagliato nell'aggiungere un Start()metodo a qualsiasi classe che dovrebbe, se fosse un oggetto reale, anche avere uno stato di riposo. Se non ha alcun senso che il tuo oggetto esista mentre non è in esecuzione (o non ha alcun senso che il tuo oggetto sia in esecuzione), direi che è una cattiva pratica.


16
Una buona analogia. Vale la pena notare che Start()potrebbe corrispondere a un interruttore di accensione / spegnimento (come un interruttore della luce) che dovrebbe quindi avere un Stop(), o un pulsante (come il pulsante Stampa su una fotocopiatrice) dove inizia e poi funziona fino al termine.
Bobson,

3
+1 ben detto e benvenuto su P.SE, risposte come questa sono un ottimo inizio.
Jimmy Hoffa,

14

È possibile utilizzare l' inizializzazione lenta.

Nella programmazione per computer, l'inizializzazione lenta è la tattica di ritardare la creazione di un oggetto, il calcolo di un valore o qualche altro processo costoso fino alla prima volta che è necessario.

In questo modo eviti l'accoppiamento temporale, il che significa che il consumatore della tua classe deve chiamare determinati metodi in un certo ordine. Dover chiamare per start()primo è un modo per sapere come funziona la classe internamente, il che è male perché potresti cambiarlo in futuro.

Ritarda l'inizializzazione costosa fino a quando non è necessaria per la prima volta.

Esempio:

public class FooClass{

    private ExpensiveResource resource;
    private CheapResource cheap;

    public  FooClass(String someParameter){
        // constructor: initialize CheapResource cheap 
            // but NOT ExpensiveResource resource
    }

    public ExpensiveResource getExpensiveResource(){
        if (resource == null) {
            this.initializeExpensiveResource();     
        }
        return this.resource
    }

    public String getExpensiveResourceName(){
        if (resource == null) {
            this.initializeExpensiveResource();     
        }
        return this.resource.getName();
    }   

    public CheapResource getCheapResource(){
        return this.cheap;
    }

    private initializeExpensiveResource(){
        // do expensive initialization of field "resource"
    }

}

public class Test{
    public static void main (String args[]){

        FooClass foo = new FooClass("some string");
        CheapResource cr = foo.getCheapResource();
        String s = foo.getExpensiveResourceName(); 
          // just now is the expensive resource initialized

    }
}

5
Un altro vantaggio dell'inizializzazione lenta che vale la pena notare è che ci vuole pochissimo sforzo per trasformarlo in un proxy virtuale . A seconda della situazione, questo può essere molto utile per visualizzare qualcosa durante l'attesa per il caricamento di una risorsa (particolarmente utile per cose come immagini remote). Sulla base della domanda originale, non penso che questo sia in realtà ciò che l'OP stava cercando, ma ho pensato che valesse la pena menzionarlo.
Dan Albert,

@DanAlbert hai ragione non è quello che stavo chiedendo ma comunque interessante
Dave Hillier,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.