Kodorebusまたは.Net 4.0のパターン「戦略」

最近、あるプロジェクトに取り組んでいると、興味深いコードが生まれました。 私たちはすぐに、同僚が何であるか、それがどのように機能し、何をするのかを説明するよう求めて、すぐに心をテストし始めました。 経験豊富な開発者でさえ、このコードは(数分間のヒステリックな笑い声の後に)混乱に陥ります。 だから、私たちは会います:



Action<Action> action = (Action action) => { action(); };
      
      





habrakatの下を見る前に、いくつかの質問に答えてみてください(投稿タイトルが表示されなかったふりをしましょう)。



答えましたか? 次に、背景と説明のために、キャットの下に飛び込みます。





これは、.Net Framework 4.0でC#で記述された完全に機能するコードであることをすぐに言わなければなりません。 もちろん、意図的に面白いrebusに変更しました。製品コードでは次のようになります。



  private Action<Action> doWork = work => { work(); };
      
      





ロシア語で言えば、別のデリゲートをパラメーターとして受け入れるデリゲートを作成します。 次に、理解しやすいように、既存のコードを可能な限り単純化して、彼がどのように生まれたかを説明します。 このようなコードがありました(すべての名前は架空のものであり、偶然の一致はランダムです)。



  public class MyWorker { private void DoWorkInternal() { Thread.Sleep(1000);//simulate work IsWorkDone = true; } public void DoWork() { DoWorkInternal(); } public bool IsWorkDone { get; private set; } }
      
      





そして、作業の結果をチェックするテスト:



  [TestMethod] public void TestDoWork() { MyWorker worker = new MyWorker(); Assert.IsFalse(worker.IsWorkDone); worker.DoWork(); Assert.IsTrue(worker.IsWorkDone); }
      
      





時間の経過とともに、戦闘状態では、 DoWorkInternal



メソッドが長時間実行され、その実行の結果がアプリケーションのさらなる動作に影響を与えないことが判明しました(ここで、何ができるかを推測できます)。 当然、実行を非同期にしたかったのです。



  public void DoWork() { Task.Factory.StartNew(DoWorkInternal); }
      
      





そして、おそらくご想像のとおり、数十のテストを実施しましたが、テストは同期して行われると信じ続けていました。 テストを変更することは不適切であると考えました。 彼らは仕事を正しくやり遂げました(仕事の事実と結果を確認しました)。 さらに、1か月でこの作業が同期を必要とせず、すべてを元の形式に戻す必要があるという保証はまったくありませんでした。 状況を少し分析した後、ここでは作業を実行するための2つの戦略-同期実行と非同期を扱っていることを理解できます。 1つのメソッドを持つ戦略は、デリゲートに縮退します。



  public class MyWorker { private Action<Action> doWork = work => { work(); }; private void DoWorkInternal() { Thread.Sleep(1000);//simulate work IsWorkDone = true; } public void DoWork() { doWork(DoWorkInternal); } public bool IsWorkDone { get; private set; } }
      
      





つまり 同期操作の戦略は次のとおりです。



  (Action work) => { work(); }
      
      





非同期実行の戦略:



  (Action work) => { Task.Factory.StartNew(work); }
      
      





クラスに、デフォルト(同期)戦略を別の戦略に変更できるメソッドを追加します。



  public void SetDoWorkStrategy(Action<Action> doWork) { this.doWork = doWork; }
      
      





できた 証拠としてテストする:



  [TestMethod] public void TestDoWork() { MyWorker worker = new MyWorker(); Assert.IsFalse(worker.IsWorkDone); worker.DoWork(); Assert.IsTrue(worker.IsWorkDone); MyWorker worker2 = new MyWorker(); Action<Action> asyncWorkStrategy = (Action work) => { Task.Factory.StartNew(work); }; worker2.SetDoWorkStrategy(asyncWorkStrategy); Assert.IsFalse(worker2.IsWorkDone); worker2.DoWork(); Assert.IsFalse(worker2.IsWorkDone);//work is in progress }
      
      





非同期戦略を使用する場合、コントロールへのアクセス、例外処理など、スレッド間の相互作用の機能を十分に理解する必要があります。 そうでなければ、副作用は避けられません。 これを終了します。誰かがこの記事をお役に立てば幸いです。



PS与えられたコードボアの議論は、.Net開発者の地位の候補者との会話に適したトピックです。



All Articles