Ist eine Methode zum Starten, Ausführen oder Ausführen eine gute Praxis?

30

Ich arbeite derzeit an einer Codebasis mit vielen Klassen, die eine Start-Methode implementieren. Dies scheint mir eine zweiphasige Konstruktion zu sein, die ich immer für eine schlechte Praxis gehalten hatte. Ich kann den Unterschied zwischen diesem und einem Konstruktor nicht erkennen.

Wann ist es angebracht, eine Startmethode anstelle der normalen Objektkonstruktion zu verwenden?

Wann sollte ich lieber den Konstruktor verwenden?

Bearbeiten: Ich denke nicht, dass es so relevant ist, aber die Programmiersprache ist C #, es könnte gleichermaßen für Java oder C ++ gelten

Dave Hillier
quelle
3
Könnten Sie etwas mehr Kontext hinzufügen? Sprache? Threaded vs Einzelthread? Unterschied zwischen startund dem Konstruktor? etc ...
@MichaelT Ich kann sehen, warum Sie fragen, aber ich interessiere mich für das allgemeine Prinzip dahinter, wenn es angebracht ist. Ich mache mir Sorgen, wenn ich bestimmte Beispiele aus der Codebasis gebe, an der ich arbeite, würden sich die Antworten zu sehr auf die Details und nicht auf meine spezifischen Fragen konzentrieren.
Dave Hillier
2
@ DaveHillier Zum Beispiel ist es in Perl üblich (und gut), eine initMethode außerhalb der newFunktion zu haben - perldoc.perl.org/perlobj.html . Die Redewendungen einer Sprache mögen dort gut funktionieren und nicht in anderen Sprachen.
1
Beispiele für Klassen mit StartMethoden in allgemeinen APIs sind Threads und Stoppuhren.
Luiscubal
1
Zählen Sie mich zu denen, die ein Codebeispiel benötigen, um zu verstehen, was Sie tatsächlich fragen.
user16764

Antworten:

44

Ein Start()Verfahren (wie Run(), Execute()oder etwas Ähnliches) ist geeignet , wenn die Kosten für die Aufgabe des Konstruierens niedrig ist, aber die Kosten der Verwendung ist es hoch. Zum Beispiel: Eine Klasse, die einen Best-Path-Optimization-Algorithmus kapselt. Es ist trivial, ihn mit einer Reihe von Parametern einzurichten ( XQuadrate für YQuadrate, mit einer solchen Bewertungsmethode), aber es kann eine Weile dauern, bis er ausgeführt wird. Wenn Sie 20 dieser Objekte erstellen möchten, möchten Sie möglicherweise die Ausführung verzögern, bis alle Objekte erstellt wurden. Auf diese Weise können Sie sie beispielsweise einfacher parallelisieren.

Alternativ kann es nützlich sein, wenn Sie nicht wissen, wann das Objekt gestartet werden muss - möglicherweise, weil es auf Benutzereingaben oder einer Logik basiert, die aus einer Liste von Möglichkeiten auswählt.

Dies setzt natürlich voraus, dass dies Start()die nützliche Methode für das Objekt ist und nicht eine Entsprechung zu einer Initialize()Methode. Wenn es nur eine zusätzliche Möglichkeit ist, weitere Parameter festzulegen, sollte es nicht existieren.

Bobson
quelle
1
Eine andere Verwendung für eine Startmethode besteht darin, dass durch die ausgeführte Aktion auch ein neuer Arbeitsthread oder ein Zeitgeber erstellt wird. Der Konstrukteur sollte diese Art von schwerem Heben nicht ausführen oder erhebliche Nebenwirkungen verursachen (wie das Erstellen eines neuen Threads).
Ziv
50

Code Complete (und viele andere Softwareentwicklungsressourcen) heben hervor, dass Ihre Klassen mit Objekten der realen Welt verglichen werden. Ich glaube, der Hauptgrund dafür ist, dass Sie dadurch wahrscheinlicher verstehen, was Sie implementieren, als sich von einer immateriellen Idee abzukoppeln.

Wenn Sie sich für diese Theorie entscheiden, sehe ich nichts Falsches daran Start(), einer Klasse eine Methode hinzuzufügen , die, wenn es sich um ein reales Objekt handelt, auch einen Ruhezustand haben sollte. Wenn es keinen Sinn macht, dass Ihr Objekt existiert, während es nicht ausgeführt wird (oder wenn Ihr Objekt überhaupt ausgeführt wird), dann würde ich sagen, dass es eine schlechte Praxis ist.

Dan Albert
quelle
16
Eine gute Analogie. Es ist erwähnenswert, dass Start()dies entweder einem Ein / Aus-Schalter (wie einem Lichtschalter) entsprechen könnte, der dann einen haben sollte Stop(), oder einem Druckknopf (wie dem Druckknopf eines Kopiergeräts), bei dem er startet und dann ausgeführt wird, bis er fertig ist.
Bobson
3
+1 Gut gesagt und willkommen bei P.SE, Antworten wie diese sind ein guter Anfang.
Jimmy Hoffa
14

Sie können Lazy Initialization verwenden.

In der Computerprogrammierung ist die verzögerte Initialisierung die Taktik, die Erstellung eines Objekts, die Berechnung eines Werts oder einen anderen teuren Prozess bis zum ersten Mal zu verzögern, bis er benötigt wird.

Auf diese Weise vermeiden Sie eine zeitliche Kopplung, dh der Consumer Ihrer Klasse muss bestimmte Methoden in einer bestimmten Reihenfolge aufrufen. Wenn Sie start()zuerst anrufen müssen, müssen Sie wissen, wie die Klasse intern funktioniert. Dies ist schlecht, da Sie dies möglicherweise in Zukunft ändern werden.

Verzögern Sie die teure Initialisierung, bis sie zum ersten Mal benötigt wird.

Beispiel:

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

    }
}
Tulains Córdova
quelle
5
Ein weiterer bemerkenswerter Vorteil der verzögerten Initialisierung besteht darin, dass nur ein geringer Aufwand erforderlich ist, um einen virtuellen Proxy zu erstellen . Abhängig von der Situation kann dies sehr nützlich sein, um etwas anzuzeigen , während auf das Laden einer Ressource gewartet wird (besonders nützlich für Dinge wie Remotebilder). Ausgehend von der ursprünglichen Frage glaube ich nicht, dass dies tatsächlich das Ziel des OP ist, aber ich dachte, es wäre erwähnenswert.
Dan Albert
@DanAlbert du hast recht, es ist nicht das, wonach ich gefragt habe, aber immer noch interessant
Dave Hillier