[翻訳]AKAノート-リミテッドステートメントマシン-1
5219 ワード
原文の住所:http://rerun.me/2016/05/21/akka-notes-finite-state-machines-1/
最近Akca FSIを仕事に使う機会がありました.とても面白い例です.API(実はDSL)は、使用体験がとても素晴らしいです.ここは私がAkca FSIの有限状態マシンで日記を書こうと試みました.例として、コーヒーマシンを構築する手順を例に挙げます.
なぜBECOMEとUNBECOMEは使わないですか?
私たちはplin vanilla Akca Actorがbecome/unbecomeで動作を切り替えることができることを知っています.なぜ私たちはAkca FSIが必要ですか?簡単にActorで状態を切り替えることはできませんか?もちろんいいです.しかし、Akcaのbecome and unbecomeが一山の状態にかき混ぜられて、絶えず状態を切り替える時、多くの状態がある状態機能を構築して、コードを迅速に異常に難しくします.
不思議なことではないですが、Actorで2つ以上の状態を使うとAkca FSIに切り替わるという提案がよくあります.
AKA FSIとは何ですか
Akca FSIはActorにおける異なる状態とスイッチング状態の管理を簡略化して有限状態マシンを構築する方法である.
最下階ではAkca FSIはActorのtritを継承しています.
言い換えれば、私達の従来のActorは一つのreceive方法しかなく、FSI tritはreceive方法の実現を包装し、特定の状態機に向けた処理コードブロックを呼び出す.
コードを書き終わってから気をつけたもう一つのことは、FSI Actorの完備されたものはまだきれいで分かりやすいです.
コードを見始めましょう.前に話しましたが、私たちはAkca FSIでコーヒーマシンを作りたいです.状態マシンはこうです.
ステータスとデータ
FSIには、常に存在している2つのものと、どの時点にも状態があり、状態で共有されているデータがある.Akca FSIでは、どれが自分のデータか、どれがステータスマシンのデータかをチェックしたいです.この声明を確認してください.
一つのスタイルとしては、一般のActorと同じように、companionの対象ですべてのメッセージを表明していますので、companionの対象で状態とデータを宣言しました.
状態とデータについてはこれだけです.
各状態機の実現とユーザーの利用可能な状態機との相互作用を見る前に、まず5万フィートでFSI Actorを見ます.
FSI ACTRの構造
FSI Actorの構造は私達の状態マシン図と似ているように見えます.
1)初期状態(Open)があります.Open状態の受信メッセージをwhen(open)コードブロックで処理します.ReadyToBuy状態はwhen(ReadyToBuy)コードブロックで処理します.私が話しているメッセージは通常私たちがActorに送ったメッセージと同じです.メッセージはデータと一緒に包装しました.包装したのはEvent(akka.actor.FSI.Event)といいます.見たところのサンプルはこのようなEvent(deposit:Deposit、MachineData)です.
Akcaの文書紹介:
4)最後に、状態が変化した時に反応したり、通知したりできるようなone Transitionの方法があります.
インタラクション/メッセージ
二種類の人がコーヒーマシンと対話してコーヒーを飲む人とコーヒーマシンが必要で、コーヒーマシンを維持して管理する人がいます.
管理を容易にするために、すべての機器との相互作用の中で2つのtritを使いました.
私達も供給商が機械との相互作用ができると声明しましょう.機械をオンまたはオフにする コーヒーの値段を設定します. セットしてマシンに持ってきたコーヒーの数です. ユーザーインタラクション貯金してコーヒーを一杯買います. コーヒーよりお金が高いとお釣りがもらえます. コーヒーの値段より高いお金を貯めたらコーヒーマシンを作ることができます. コーヒーを沸かす前に取引をキャンセルして、全部の払い戻しをもらいます. 機械でコーヒーの値段を調べます.
次のページでは、すべての状態を見て、彼らの相互作用を研究します.
コード
コードはgithubにあります
文章はWeChatプラットフォーム「麦芽パン」からのWeChat公式アカウント「darkjunneguthink」に転載しています.面白いと思ったら、WeChatスキャンして公衆番号を確認してください.
最近Akca FSIを仕事に使う機会がありました.とても面白い例です.API(実はDSL)は、使用体験がとても素晴らしいです.ここは私がAkca FSIの有限状態マシンで日記を書こうと試みました.例として、コーヒーマシンを構築する手順を例に挙げます.
なぜBECOMEとUNBECOMEは使わないですか?
私たちはplin vanilla Akca Actorがbecome/unbecomeで動作を切り替えることができることを知っています.なぜ私たちはAkca FSIが必要ですか?簡単にActorで状態を切り替えることはできませんか?もちろんいいです.しかし、Akcaのbecome and unbecomeが一山の状態にかき混ぜられて、絶えず状態を切り替える時、多くの状態がある状態機能を構築して、コードを迅速に異常に難しくします.
不思議なことではないですが、Actorで2つ以上の状態を使うとAkca FSIに切り替わるという提案がよくあります.
AKA FSIとは何ですか
Akca FSIはActorにおける異なる状態とスイッチング状態の管理を簡略化して有限状態マシンを構築する方法である.
最下階ではAkca FSIはActorのtritを継承しています.
trait FSM[S, D] extends Actor with Listeners with ActorLogging
FSI tritは純粋な魔法を提供しています.彼は通常のActorを包装したDSLを提供してくれます.より速く手持ちの状態マシンを構築することに集中できます.言い換えれば、私達の従来のActorは一つのreceive方法しかなく、FSI tritはreceive方法の実現を包装し、特定の状態機に向けた処理コードブロックを呼び出す.
コードを書き終わってから気をつけたもう一つのことは、FSI Actorの完備されたものはまだきれいで分かりやすいです.
コードを見始めましょう.前に話しましたが、私たちはAkca FSIでコーヒーマシンを作りたいです.状態マシンはこうです.
ステータスとデータ
FSIには、常に存在している2つのものと、どの時点にも状態があり、状態で共有されているデータがある.Akca FSIでは、どれが自分のデータか、どれがステータスマシンのデータかをチェックしたいです.この声明を確認してください.
class CoffeeMachine extends FSM[MachineState, MachineData]
これはすべてのfsmの状態を表しています.MachineStateから継承されていますが、状態間で共有されているデータはすべてMachineDataです.一つのスタイルとしては、一般のActorと同じように、companionの対象ですべてのメッセージを表明していますので、companionの対象で状態とデータを宣言しました.
object CoffeeMachine {
sealed trait MachineState
case object Open extends MachineState
case object ReadyToBuy extends MachineState
case object PoweredOff extends MachineState
case class MachineData(currentTxTotal: Int, costOfCoffee: Int, coffeesLeft: Int)
}
状態マシンの図では、私たちは三つの状態があります.私達のデータは、Machinedataは飛行機を運転する前のマシンのコーヒーの数量を保留しています.コーヒーの価格(coffees Left)、コーヒーマシンのお釣り(currentTxTotal)、小銭がコーヒーの価格より低いなら、マシンはコーヒーを販売しません.状態とデータについてはこれだけです.
各状態機の実現とユーザーの利用可能な状態機との相互作用を見る前に、まず5万フィートでFSI Actorを見ます.
FSI ACTRの構造
FSI Actorの構造は私達の状態マシン図と似ているように見えます.
class CoffeeMachine extends FSM[MachineState, MachineData] {
//What State and Data must this FSM start with (duh!)
startWith(Open, MachineData(..))
//Handlers of State
when(Open) {
...
...
when(ReadyToBuy) {
...
...
when(PoweredOff) {
...
...
//fallback handler when an Event is unhandled by none of the States.
whenUnhandled {
...
...
//Do we need to do something when there is a State change?
onTransition {
case Open -> ReadyToBuy => ...
...
...
}
構造から何が見えるか:1)初期状態(Open)があります.Open状態の受信メッセージをwhen(open)コードブロックで処理します.ReadyToBuy状態はwhen(ReadyToBuy)コードブロックで処理します.私が話しているメッセージは通常私たちがActorに送ったメッセージと同じです.メッセージはデータと一緒に包装しました.包装したのはEvent(akka.actor.FSI.Event)といいます.見たところのサンプルはこのようなEvent(deposit:Deposit、MachineData)です.
Akcaの文書紹介:
/**
* All messages sent to the [[akka.actor.FSM]] will be wrapped inside an
* `Event`, which allows pattern matching to extract both state and data.
*/
case class Event[D](event: Any, stateData: D) extends NoSerializationVerificationNeeded
2)2つのパラメータを受け入れるwhen方法-最初は状態の名前、例えばOpen、ReadyToBuy、もう一つのパラメータはPartalFunctionで、Actorのreceive方法と同じようにモードマッチングをする.一番重要なことは、各パターンがマッチするcaseブロックは一つの状態に戻らなければなりません.コードブロックはこのようになります.when(Open) {
case Event(deposit: Deposit, MachineData(currentTxTotal, costOfCoffee, coffeesLeft)) => {
...
...
3)基本的には、メッセージにwhenの2番目のパラメータにマッチしたモードが特定の状態で処理される.もし一致していないならば、FSI Actorは私達のメッセージをwhennUnhandedブロック中のモードと一致させることを試みます.理論的には、パターンにマッチしていないメッセージはすべてwhennnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnundedによって処理されます.(私はあまりコードスタイルを提案したくないですが、小さいサイズのPartalFunctionを宣言してandThe nを組み合わせて使うと、選択した状態でパターンマッチングを再利用できます.)4)最後に、状態が変化した時に反応したり、通知したりできるようなone Transitionの方法があります.
インタラクション/メッセージ
二種類の人がコーヒーマシンと対話してコーヒーを飲む人とコーヒーマシンが必要で、コーヒーマシンを維持して管理する人がいます.
管理を容易にするために、すべての機器との相互作用の中で2つのtritを使いました.
object CoffeeProtocol {
trait UserInteraction
trait VendorInteraction
...
...
サプライヤー相互作用私達も供給商が機械との相互作用ができると声明しましょう.
case object ShutDownMachine extends VendorInteraction
case object StartUpMachine extends VendorInteraction
case class SetCostOfCoffee(price: Int) extends VendorInteraction
//Sets Maximum number of coffees that the vending machine could dispense
case class SetNumberOfCoffee(quantity: Int) extends VendorInteraction
case object GetNumberOfCoffee extends VendorInteraction
だから、サプライヤーはいいです. case class Deposit(value: Int) extends UserInteraction
case class Balance(value: Int) extends UserInteraction
case object Cancel extends UserInteraction
case object BrewCoffee extends UserInteraction
case object GetCostOfCoffee extends UserInteraction
では、ユーザーがインタラクションするために、ユーザは可能である.次のページでは、すべての状態を見て、彼らの相互作用を研究します.
コード
コードはgithubにあります
文章はWeChatプラットフォーム「麦芽パン」からのWeChat公式アカウント「darkjunneguthink」に転載しています.面白いと思ったら、WeChatスキャンして公衆番号を確認してください.