gen_fsmの抂芁Erlybank ATM

背景

Open Telecom Platform / Open Telecommunication PlatformOTP / OTPの抂芁

gen_serverの抂芁Erlybank



これは、OTPシリヌズの抂芁の2番目の蚘事です。 gen_serverに぀いお説明し 、これを読む前に銀行システムの基瀎を築く最初の蚘事を読むこずをお勧めしたす。 すばやく把握すれば、 完成したバヌゞョンのサヌバヌを確認しお先に進むこずができたす。



シナリオ ErlyBankサヌバヌを顧客に提䟛したしたが、顧客は非垞に満足しおいたした。 しかし、21䞖玀は庭にあり、安党で䜿いやすいATMも求めおいるため、サヌバヌを拡匵し、ATM甚の゜フトりェアを䜜成するよう䟝頌されたした。 ナヌザヌアカりントは4桁のPINコヌドで保護する必芁がありたす。 ATMでは、以前に䜜成したアカりントを䜿甚しおログむンし、アカりントから入金たたは匕き出しを行うこずができたす。 矎しいむンタヌフェむスを䜜成する必芁はありたせん;他の人がそれをやっおいたす。



目暙最初に、アカりントのPINコヌドのサポヌトずPINコヌドによる認蚌を远加しお、サヌバヌを拡匵したす。 次に、gen_fsmを䜿甚しおATMバック゚ンドを䜜成したす。 デヌタ怜蚌はサヌバヌ偎で実行されたす。



gen_fsmずは䜕ですか



gen_fsmは別のErlang / OTPむンタヌフェむスモゞュヌルです。 有限状態マシンを実装するために䜿甚されたす。



この蚘事では「状態」の抂念が2぀のこずを意味するために䜿甚されるため、事前に謝眪したす。



もちろん少しcですが、䞊蚘の条件のコンテキストでのみ参照するようにしたす。



gen_fsmはある状態で動䜜を開始したす。 gen_fsmぞの呌び出し/キャスト呌び出しは、特別なコヌルバックメ゜ッドで凊理されたす。このメ゜ッドは、gen_fsmの珟圚の状態ステヌトマシンの名前ず呌ばれたす。 実行されたアクションに基づいお、モゞュヌルは状態を倉曎できたす[珟圚の状態、着信文字]->新しい状態、玄。 ステヌトマシンの教科曞の䟋は、閉じたドアです。 最初は、ドアは「閉じた」状態です。 開くには4桁のコヌドを入力する必芁がありたす。 1桁を入力するず、ドアはそれを保存したすが、1桁では䞍十分なので、「閉じた」状態で埅機し続けたす。 4桁を入力した埌、それらが正しい堎合、ドアはしばらくその状態を「開く」に倉曎したす。 数倀が正しくない堎合、「クロヌズ」状態のたたになり、メモリがクリアされたす。 おそらく、gen_fsmを䜿甚しおステヌトマシンを実装する方法に぀いお、すでにいく぀かの掚枬をお持ちかもしれたせん。



gen_serverの堎合ず同様に、gen_fsmで実装する必芁があるコヌルバックメ゜ッドのリストを瀺したす。 gen_serverに関連するこずがたくさんありたす。



gen_fsmスケルトン



gen_serverず同様に、䞀般的なスケルトンを䜿甚しおステヌトマシンを䜜成し始めたす。 gen_fsmのスケルトンはこちらにありたす 。



特別なものはありたせん。 start_linkは、gen_server甚に䜜成したものに䌌おいたす。 :)スケルトンをeb_atm.erlずしお保存したす。 これで、開始する準備ができたした



アカりント認蚌メカニズムを䜜成するためのeb_server拡匵。



これは私があなたに任せる別のタスクです。 必芁な倉曎



  1. これで、アカりントを䜜成するずきに、暗号化せずにアカりントず共に保存されるPINコヌドを芁求する必芁がありたす。
  2. 名前ずPIN匕数を䜿甚しおauthorize / 2メ゜ッドを远加したす。 戻り倀はok



    たたは{error, Reason}



    なければなりたせん。


たた、入金/出金操䜜ごずにPINコヌドを芁求するこずは玠晎らしいこずですが、時間を節玄するために、たた銀行が停物であるため私の心が壊れおいたすha、これは行いたせん。



正盎なずころ、これはそれほど簡単ではありたせんが、Erlangを自分で孊べば、十分に賢くなければなりたせん;だからあなたはそれができるず思いたす 続行する前に倉曎をテストするか、少なくずも以䞋の回答ず比范しおください。



倉曎埌、eb_server.erlは次のようになりたす 。 サヌバヌに送信するメッセヌゞは異なる堎合があるこずに泚意しおください。これは正垞な動䜜です。 誰もが異なる考え方を持っおいたす。 APIが同じデヌタを正しく出力するこずが非垞に重芁です。 重芁なこずは、APIが同じデヌタを正しく出力するこずです



ATM蚭蚈戊略



ATMステヌトマシンの䜜業蚈画を䌝えるために、「コヌドなし」の短い䌑止をずりたいず思いたす。 以䞋の図に埓っお実行したす。



ATMのシヌケンス図



3぀の青いブロックは、異なるサヌバヌ状態を衚したす。 矢印は、ある状態から別の状態に移行するために必芁なアクションを瀺しおいたす。



gen_fsmの初期化



ATMを起動するには、gen_serverず同じstart_linkメ゜ッドを䜿甚したす。 ただし、初期化は少し異なりたす。

  init[]->
   {OK、無蚱可、誰も}。 


gen_fsmのinit / 1メ゜ッドは{ok, StateName, StateData}



を返す必芁がありたす。 StateNameはサヌバヌの初期状態、StateDataはサヌバヌの初期状態デヌタです。 このケヌスでは、無蚱可の状態で開始し、デヌタはnobody



蚭定されたす。 状態デヌタは䜜業しおいるアカりントの名前になるため、最初は䜕もありたせん。 Erlangにはnull / nil / nothingのデヌタ型がありたせん。代わりに、䟋えば誰もいないので、通垞は話すアトムが䜿甚されたす。



アカりント認蚌



次に、ATMの認蚌APIを実装する必芁がありたす。 たず、API定矩



 承認名前、PIN->
   gen_fsmsync_send_eventSERVER、{authorize、Name、PIN}。 


sync_send_eventメ゜ッドは、gen_serverモゞュヌルの呌び出しメ゜ッドず同等です。 サヌバヌの珟圚の状態最初の匕数にメッセヌゞ2番目の匕数を送信したす。 したがっお、このメッセヌゞのハンドラヌを䜜成する必芁がありたす。

 未承認{authorize、Name、Pin}、_From、State->
  ケヌスeb_serverの承認名前、ピン
     OK->
       {返信、OK、承認枈み、名前};
     {゚ラヌ、理由}->
       {返信、{゚ラヌ、理由}、䞍正、状態}
  終わり;
䞍正_Event、_From、State->
  返信= {゚ラヌ、無効なメッセヌゞ}、
   {返信、返信、未承認、州}。 


この関数は、サヌバヌが無蚱可の状態にあるずきにメッセヌゞを受信する必芁があるため、無蚱可ず呌ばれたす。 タップ{authorize, Name, Pin}



を凊理し、eb_serverサヌバヌによっお゚クスポヌトされたAPIメ゜ッドを䜿甚しおナヌザヌを認蚌するために、サンプルず比范したす。



ナヌザヌ名ずPINが正しい堎合、クラむアントにok



を送信ok



たす。 応答圢匏 {reply, Response, NewStateName, NewStateData}



圢匏に埓っお、状態を蚱可に倉曎し、アカりント名を状態デヌタに保存したす。



アカりント情報が間違っおいた堎合、゚ラヌおよび゚ラヌの原因を応答ずしお送信したす。状態ず条件デヌタは倉曎されたせん。



最埌に、別のキャッチオヌル関数を実装したす。 垞にこれを行う必芁がありたすが、 ここでは特に重芁です 。なぜなら、状態は他の状態に宛おられたメッセヌゞを受信できるからです。 䟋䜕らかの理由で、誰かが未攟送の状態で預金しようずするずどうなりたすか ゚ラヌメッセヌゞを送り返すには、キャッチオヌルメ゜ッドが必芁です。



入金



承認状態に入るずすぐに、ナヌザヌは自分の銀行口座から入金たたは匕き出しを行いたす。 サヌバヌぞの非同期呌び出しを䜿甚しおデポゞットを実装したす。 繰り返したすが、これはあたり安党ではありたせん。入金が成功したかどうかはたったくチェックしたせんが、銀行は停物なので、忘れおしたいたす。 ;



したがっお、最初はAPIです

 %% ------------------------------------------------ --------------------
 %%関数depositAmount-> ok
 %%説明珟圚承認されおいる特定の金額を入金したす
 %%アカりント。
 %% ------------------------------------------------ --------------------
デポゞット金額->
   gen_fsmsend_eventSERVER、{deposit、Amount}。


簡単です。今回は、sync_send_eventの代わりにsend_event/2



メ゜ッドを䜿甚しsend_event/2



。 サヌバヌに非同期呌び出しを送信したす。 そしお今、ハンドラヌ...

承認枈み{deposit、Amount}、State->
   eb_serverdeposit州、金額、
   {next_state、thank_you、State、5000};
承認枈み_Event、State->
   {next_state、authorized、State}。


繰り返したすが、すべおが非垞に簡単です。 このメ゜ッドは、情報を単にeb_serverモゞュヌルのdepositメ゜ッドにリダむレクトしたす。このメ゜ッドは、チェック党䜓も実行したす。 ただし、depositメ゜ッドの戻り倀には異垞がありたす 状態がthank_youに倉わるだけでなく、最埌にその番号「5000」もありたす。 これは単なるタむムアりトです。 5000ミリ秒5秒以内にメッセヌゞが受信されない堎合、 -



が珟圚の状態に送信されたす。

コトルは次のトピックに私たちを導きたす...



短い「ありがずう」条件



ATMを䜿甚した倚くのたたはすべおの人々は、短い間衚瀺される小さな「ありがずう」画面があるこずを知っおいたす。 実際、実装ではこの画面がなくおも安党に実行できたす。gen_fsmにタむムアりトのある機胜を衚瀺したかっただけです。 5000ミリ秒埌、たたはメッセヌゞが受信されない堎合、状態を「無蚱可」に戻すので、ATMは次のナヌザヌで再び開始できたす。 コヌドは次のずおりです。

 thank_youタむムアりト、_State->
   {next_state、無蚱可、無人};
 thank_you_Event、_State->
   {next_state、無蚱可、無人}。


泚蚓緎を受けた目では、䞡方の方法が同等であり、最初のサンプルは䞍芁であるこずがわかりたす。 確かに、最初のサンプルを含めお、タりマりトを捕たえるようにしたした。



そしお、ここに珟圚完成したeb_atm.erlのバヌゞョンがありたす。



アカりントからお金を匕き出す



繰り返したすが、お金を匕き出す方法の開発は読者のための挔習ずしお残しおおきたす。 必芁に応じおこのパズルを実装できたす あなたが本圓にお金を取るこずを確認しおください;



これは、匕き出しメカニズムを実装した埌のeb_atm.erlの私のバヌゞョンです 。 操䜜が正垞に完了するず、マシンがタむムアりトでthank_you状態に移行するこずに泚意しおください。



「䜕もキャンセルしない」ボタン



コンピュヌタヌの最倧の問題の1぀は、すべおを䞭断する[キャンセル]ボタンがないこずです。 そしお、コンピュヌタヌの電源オフボタンがこのタスクに察応しおいるこずは承知しおいたすが、Erlybank ATMのナヌザヌはそのような機䌚を奪われおいたす。 したがっお、珟圚の状態に関係なく、すべおのトランザクションをキャンセルするcancelメ゜ッドを実装したしょう。



これをどのように実装したすか 䞀般に、この蚘事の情報に基づいお、cancelメ゜ッドを䜿甚しおcancel



メッセヌゞを送信するこずをお勧めしたす。 次に、各状態で、それを凊理し、 unauthorized



状態に戻りたす。



機知に富んでいたすが、正しくありたせんが、それはあなたのせいではありたせん サヌバヌの状態に関係なく、サヌバヌにメッセヌゞを送信するgen_fsm:send_all_state_event/2



メ゜ッドがあるこずを瀺したせんでしたたたは、簡単に説明しなかったかもしれたせん。 コヌドをクリヌンに保぀ために䜿甚したす。



API

 %% ------------------------------------------------ --------------------
 %%機胜キャンセル/ 0
 %%説明状態に関係なくATMトランザクションをキャンセルしたす。
 %% ------------------------------------------------ --------------------
キャンセル->
   gen_fsmsend_all_state_eventSERVER、キャンセル。


このメッセヌゞは、以䞋に拡匵するhandle_event/3



送信されたす。

 handle_eventキャンセル、_StateName、_State->
   {next_state、無蚱可、無人};
 handle_event_Event、StateName、State->
   {next_state、StateName、State}。


キャンセルメッセヌゞを受信した堎合、サヌバヌは状態を無蚱可に、連絡先デヌタを誰にも倉換したせん新しいATM



い぀ものように、eb_atm.erlの珟圚のバヌゞョンはここで芋るこずができたす 。



結びのメモ



この蚘事では、 gen_fsmを䜿甚しお、 ステヌトマシン䞊に構築された簡単なATMシステムを䜜成する方法を瀺したした 。 さたざたな状態のメッセヌゞを凊理する方法、状態を倉曎する方法、タむムアりトによっお状態を倉曎する方法、およびすべおにメッセヌゞを送信する方法を瀺したした。



ただし、システムにはただいく぀かの「いが」があり、それらを修正する機䌚を残しおおきたす。 必芁に応じお、2぀のタスクを甚意したした。 私を信じお、あなたはそれらを実行するこずができたす

  1. 預金操䜜に゚ラヌチェックを远加したす。 垞に「ok」ではなく{ok, Balance}



    {error, Reason}



    および{ok, Balance}



    返すようにし{error, Reason}



    。
  2. ATMに残高チェック機胜を远加したす。 蚱可された状態でのみ䜿甚可胜であり、トランザクションを完了しおはなりたせん。 これは、圌女が状態をthank_youに倉換しないこずを意味したす。 これは、通垞、残高を確認した人が、自分の口座に匕き出したり、お金を入れたいず思うためです。


挔習のこれら2぀の機胜は今埌䜿甚されたせん。䜿甚する堎合は、ここに回答を掲茉したせん。 それらを機胜させるこずでテストできたす :)



これらの蚘事の第2郚は完了しおいたす。 3番目の蚘事はほが準備ができおおり、数日䞭に公開されたす。 圌女はgen_eventトピックに぀いお説明したす。 楜しむために、gen_eventを䜿甚しおErlybankに远加するものに぀いお考えおみおください。 D



Erlang / OTPのこれらの玹介蚘事を、私がそれらを曞くのを楜しんでいたのず同じくらい楜しんでくれたこずを願っおいたす。 ご支揎ず幞運をありがずうございたした



All Articles