Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Ruby でステート マシンをマスターする:実践ガイド

ステートマシンは何かのすべての可能な状態を保持できます。 たとえば、ドアのステート マシンには 2 つの状態 (open) のみが含まれます。 および closed )、トランジションは 2 つだけ (opening) と closing ).

一方、複雑なステート マシンには、それらの間で何百もの遷移があるいくつかの異なる状態を持つことができます。実際、周りを見渡すと、ウェブサイトから買い物をするとき、自動販売機でポテトチップスのパックを買うとき、または単に ATM からお金を引き出すときでも、有限のステート マシンが周囲にあることに気づくでしょう。

この投稿では、Ruby でステート マシンをセットアップし、ステート マシン gem を使用する方法を見ていきます。

開発中のステート マシン

開発においてステート マシンが必要になるのはどのような場合ですか?簡単な答えは、状態遷移の複数のルールをモデル化したいとき、または一部の遷移で副作用を実行したいときです。ここで重要なのは、ステート マシンから恩恵を受けるアプリケーションの部分を特定することです。私にとって常に機能する良い例は、Order です。 e コマース アプリケーションのコンテキストで。

オンラインで製品を販売する単純なアプリケーションの場合、Order いくつかの状態のいずれかになります。

  • created
  • processing
  • ready
  • shipped
  • delivered
  • void

次の図で、許可される遷移を確認できます。

Ruby でステート マシンをマスターする:実践ガイド

注文をステート マシンの形式で視覚化すると、製品の注文から配送に至るまでの完全なフローを即座に明確に理解できるようになります。また、開発者にとって、フローの特定のポイントで何ができるか、何ができないかを明確に設定した手順が可能になります。

そうは言っても、これを非常に広範な問題として取り上げると、ウサギの穴に飛び降りるのは簡単で、最終的には、推論して実行するのが難しい何百もの状態が存在することになります。そのため、提案するステート マシンを実装する前に、常にそのトップレベルのアイデアと状態図を用意してください。

Ruby での最初のステート マシン

OrderStateMachine を実装してみましょう。 ルビーを使って。

 

これは非常に単純な実装です。ステート マシンで考えられる遷移ごとに、健全性チェックを行って遷移を実行する新しいメソッドを定義します。

上記の実装の優れた点は、すべてが明示的であることです。新しい開発者は、ステート マシンの全範囲をすぐに理解できます。

トランジションに副作用を追加する方法を見てみましょう。梱包され配達可能な注文は自動的に発送されます。

 

素朴な実装はうまく機能しますが、特に多くの遷移や条件がある場合、過度に冗長になります。

Ruby Toolbox を簡単にチェックすると、ステート マシン用の gem がいくつか表示されます。state_machinesaasm は最も人気のあるもので、Rails で使用する場合はどちらも ActiveRecord アダプターが付属しています。どちらも徹底的にテストされており、運用準備が整っているため、ステート マシンを実装する必要がある場合はチェックしてください。

Ruby での State Machines Gem の使用

この投稿では、Order のステート マシンをモデル化する方法について説明します。 state_machines を使用する 宝石。

 

上記のクラスは、単純なステート マシンとその可能なすべての遷移を定義します。これに加えて、オーダーに関する多くのユーティリティ メソッドも自動的に公開されます。

 

Ruby のステート マシン Gem を使用して副作用を実行する

現実世界のシステムでは通常のことですが、ステート マシンの多くの遷移には副作用が伴います。state_machines gem を使用すると、それらの定義と実行が簡単になります。2 つの副作用を追加しましょう:

<オル>
  • ready へのすべての遷移時 、注文が deliverable の場合、配送委託品を作成します。 .
  • すべての fail_delivery で イベントを通知する電子メールをユーザーに送信します。
  •  

    通常どおり、次の順序でトランジションを実行できます。

     

    state_machines の Github ページをチェックすることをお勧めします。 gem を参照して、gem が提供するすべての可能なオプションについて学習してください。

    Ruby on Rails の ActiveRecord でステート マシン Gem を使用する

    前に説明したように、両方の state_machinesaasm ActiveRecord をサポートします。state_machines を使用する場合 gem と ActiveRecord を組み合わせたものですが、実装によって多くのことが変わるわけではありません。この投稿の前のセクションですでに説明した内容のほとんどは、引き続き使用できます。

    以下に追加機能をいくつか示します。

    <オル>
  • 副作用はトランザクション内で発生します。これは、遷移フック内でデータベース操作を実行し、トランザクションが失敗した場合、状態の変更はコミットされないことを意味します。use_transactions を参照してください。 この動作を無効にしたい場合。
  • 他のすべての ActiveRecord コールバックと同様、トランジションから現在のモデルの属性を更新する場合は、before_transition 内でこれを行う必要があります。 callback.after_transition 内の属性を更新するには 、モデルを再度保存する必要があります。次の例を確認してください。
  •  <オル> 
  • Gem は、状態によってモデルをフィルタリングするためのスコープを自動的に提供します。たとえば、Order.with_state(:processing) を実行できます。 すべての処理オーダーを検索するか、Order.without_state(:processing) 処理されていない注文をすべて検索します。
  • 一致する遷移なしで状態変更が試行された場合 (たとえば、processing から) deliveredへ )、レコードの保存に失敗し、検証エラーにエラーが追加されます。生成されたエラー メッセージを国際化するには、構成ファイル内の状態とイベントの翻訳を提供するいくつかのキーを追加するだけです(たとえば、en.yml)。 ):
  •  

    補足 :ActiveRecord のパフォーマンスの問題をトラブルシューティングするには、この投稿を確認してください。

    まとめ:Ruby でステート マシンを構築する

    この投稿では、単純なステート マシンを構築する前に、開発でステート マシンを使用する理由を検討しました。最後に、Ruby および Ruby on Rails でのステート マシン gem の使用について検討しました。

    ステート マシンの基本を理解したところで、すでにステート マシンを使用している、またはステート マシンから大きな恩恵を受ける、身の回りのいくつかのシナリオに気づくでしょう。

    次回まで、ステート マシンの構築が成功することを祈っています!

    追記Ruby Magic の投稿を報道後すぐに読みたい場合は、Ruby Magic ニュースレターを購読して、投稿を 1 つも見逃さないようにしてください。

    Ruby でステート マシンをマスターする:実践ガイド

    プルキット ゴヤル

    ゲスト著者の Pulkit は、シニア フルスタック エンジニア兼コンサルタントです。自由時間には、自分の体験をブログに書いています。

    Pukit Goyal によるすべての記事


    1. 科学者による重要な Ruby on Rails コードのリファクタリング:実証済みのアプローチ

      ソフトウェア エンジニアに本番コードの重要な部分をレビューするよう依頼すると、必ずリファクタリングが必要な 3 つの点を指摘するでしょう。では、なぜこれほど多くの悪いコード、脆弱なコード、または誤解されたコードが実稼働環境で実行され続けるのでしょうか? 答えは簡単です。エンジニアはそれに触れるのを恐れているからです。リファクタリング タスクは特定されてバックログに追加されますが、現在のスプリントに反映されることはほとんどありません。 これには多くの理由があります。コードは何年も前にチームを離れたエンジニアによって書かれたものである可能性があり、それを完全に理解している人は誰もいません。また

    2. Rubyオブジェクトモデルを詳細に理解する

      ウィキペディアによると、オブジェクト指向プログラミング(OOP)は、「オブジェクト」の概念に基づくプログラミングパラダイムであり、データとコードを含めることができます。フィールド形式のデータ(多くの場合、属性またはプロパティと呼ばれます)と形式のコードです。手順の(多くの場合、メソッドとして知られています)。 Rubyは純粋なオブジェクト指向言語です。つまり、Ruby言語では、すべてがオブジェクトです。これらのオブジェクトは、文字列、数値、クラス、モジュールなどであるかどうかに関係なく、オブジェクトモデルと呼ばれるシステムで動作します。 。 Rubyはobject_idと呼ばれるメソッドを