「開始」、「実行」、「実行」の方法は良い習慣ですか?


30

現在、Startメソッドを実装する多くのクラスを持つコードベースで作業しています。これは私にとって二段階の構成のように思えますが、私は常に悪い習慣だと考えていました。これとコンストラクターの違いはわかりません。

通常のオブジェクト構築の代わりに開始メソッドを使用するのが適切なのはいつですか?

コンストラクターを使用するのはいつですか?

編集:私はそれが関連しているとは思わないが、プログラミング言語はC#であり、JavaまたはC ++に等しく適用できる


3
もう少しコンテキストを追加できますか?言語?スレッド対シングルスレッド?とstartコンストラクタの違いは?など

@MichaelTなぜあなたが尋ねているのかはわかりますが、適切な場合の背後にある一般原則に興味があります。私が取り組んでいるコードベースから特定の例を挙げた場合、答えは私の特定の質問ではなく詳細に集中しすぎるのではないかと心配です。
デイブヒリアー

2
例えば@DaveHillierは、perlで有するように、標準的なプラクティス(と良いもの)であるinitのある種の外の方法new-機能perldoc.perl.org/perlobj.htmlを。1つの言語のイディオムは、他の言語ではなく、そこで機能する場合があります。

1
Start一般的なAPIのメソッドを持つクラスの例には、スレッドとストップウォッチが含まれます。
ルイスキューバル

1
あなたが実際に何を求めているのかを理解するためにコードサンプルが必要な人の中で私を数えてください。
user16764

回答:


44

Start()方法(のようなRun()Execute()オブジェクトを構築するコストが低い場合、または同様のもの)が適切であるが、コストの使用は高いです。例:ベストパス最適化アルゴリズムをカプセル化するクラス。これは、パラメータ(のセットでそれを設定するには些細だXことにより、正方形Ysuchandsuch評価方法と四角)が、それは実行に時間がかかる場合があります。これらのオブジェクトを20個作成する場合は、すべてのオブジェクトが作成されるまで実行を遅らせることができます。これにより、たとえば、オブジェクトをより簡単に並列化できます。

あるいは、オブジェクトの開始がいつ必要になるかわからない場合に便利かもしれません-おそらくユーザー入力、または可能性のリストから選択するロジックに基づいているためです。

もちろん、これはStart()オブジェクトの便利なメソッドであり、Initialize()メソッドと同等ではないことを前提としています。さらに多くのパラメータを設定するための特別な方法である場合は、存在しないはずです。


1
startメソッドのもう1つの用途は、実行されたアクションによって新しいワーカースレッドまたはタイマーも作成される場合です。コンストラクタは、この種の重い処理を行ったり、重大な副作用(新しいスレッドの作成など)を発生させたりしないでください。
ジブ

50

Code Complete(および他の多くのソフトウェアエンジニアリングリソース)は、クラスを実際のオブジェクトに一致させることを強調しています。これの根本的な理由は、無形のアイデアをハックするのではなく、実装していることを真に把握する可能性が高くなるからだと思います。

あなたがこの理論の購読者なら、Start()メソッドをクラスに追加することに何の問題もないと思います。それが実際のオブジェクトである場合、静止状態にもなります。実行していない間にオブジェクトが存在することが意味をなさない場合(またはオブジェクトが実行されていることをまったく意味がない場合)、それは悪い習慣であると言えます。


16
良いアナロジー。Start()オン/オフスイッチ(ライトスイッチなど)に対応しStop()、プッシュボタン(コピー機の[印刷]ボタンなど)に対応し、キックオフされて完了するまで実行されることに注意してください。
ボブソン

3
+1はよく言ってP.SEへようこそ、このような答えは素晴らしい出発点です。
ジミー・ホッファ

14

遅延初期化を使用できます。

コンピュータープログラミングでは、遅延初期化は、オブジェクトの作成、値の計算、または他の高価なプロセスを最初に必要になるまで遅らせる戦術です。

これにより、一時的なカップリングを回避できます。つまり、クラスのコンシューマーは特定のメソッドを特定の順序で呼び出す必要があります。start()最初に呼び出さなければならないのは、クラスが内部でどのように機能するかを知る必要がある方法です。

最初に必要になるまで、高価な初期化を遅らせます。

例:

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
注目に値する遅延初期化のもう1つの利点は、仮想プロキシを形成するのにほとんど労力がかからないことです。状況によっては、これはリソースの読み込みを待っている間に何かを表示するのに非常に役立ちます(特にリモートイメージのようなものに役立ちます)。元の質問に基づいて、これは実際にはOPが求めていたものではないと思いますが、言及する価値があると思いました。
ダンアルバート

@DanAlbertあなたは正しいです、それは私が求めていたものではなく、まだ面白いです
デイブヒリアー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.