2020年11月10日に、『Elixir Digitalization Implementors #2:通信テスト込の愛でる会』(略称はEDI会)に参加しました。
イベントの詳細はこちらを参照。
fukuokaex.connpass.com
このイベントの中で、タイトルにもあるように「GenServerの"状態"」の話題も挙がりました。
なお、今回ブログを書こうと思ったきっかけがコレ。
ここから発展していった話題も面白かったので、あわせてご紹介します。
Elixir Digitalization Implementorsについて
fukuoka.exの主催の一人である、piacere氏が発足されたイベントです。
イベントの趣旨は以下の通り。
「Elixir Digitalization Implementors」、略称「EDI」は、「Elixir実装の芽」をみんなで愛でるコミュニティです
そうした芽から、「身近な仕事や生活をElixirでデジタル化して、良くしていこう」というのが、この会の狙いです
参加した印象としては『個々人のElixirの熟練度云々は置いといて、Elixirが好きな人たち集まって話そうよ』な雰囲気が感じられ、気楽に参加できるイベントだと思っています。
LTをする側にとっても、「I-IZM」「M-IZM」「S-IZM」と発表形式を選べるので、色んな楽しみ方もできるのではないでしょうか。
なお、ハッシュタグは「 #ElixirDI 」です。
これをみて雰囲気を掴むのもありですね。
余談ですが、第一回目の参加では自分もLTをしてきました。
LT会について
イベントでは、以下に関する発表が行われました。
今回の特徴としては、「I-IZM」形式(登壇者の発表を参加者もワイワイしながら進める形式)の発表が多かったです。
- Phoenix LiveView + WebViewでのスマホアプリ実装
- LiveViewだけだと審査が落とされるので、スマホ用オブジェクトを配置することで回避されたとか。なるほどと思いつつ、それだけでいいんだ感も(笑)
- Nerves GenServer Lチカ
- Nerves内でGenServerを使ってLチカする場合の実装説明。GenServerについての解説も。
- LiveUploadsプルリクレビューに参加して取り込んでもらえた話
- タイトルの件以外に複数の話題でお話されていました。Phoenixを使った"湯婆婆"にはクスリw
- AtCoder用nimixタスクを提供するライブラリの話
- mixタスクについてのお話。"mixタスクには2種類ある"には、思わず反応してしまいました(後述)
- リベンジ:Phoenix WebSocketで「VRの世界」を現実にAR投影
- 前回のリベンジ。今回はうまくいきました(笑)。NeosVR の世界を見せてもらっただけでもお腹いっぱいなのに、Elixirとも組み合わせられたということで、ニヤニヤしながら見ていました。VR空間内で、ネットの画面を切り貼り出来たのは驚きました。(後述)
いやー、どれも楽しかったです。
"mixタスクには2種類ある"、についてはこんな反応をしました。
#ElixirDI
— みずりゅ(「Elixirへのいざない」技術の泉シリーズで出版:しがないラジオsp65出演) (@MzRyuKa) 2020年11月10日
mix タスクには2種類ある。
なるほど。 pic.twitter.com/XEcp0pUZKt
なるほど、「単体で実行可能なmixタスク」と「mixプロジェクト配下で実行可能なmixタスク」があるのか。
話を聴いてて、"今度、mixタスクを自作してみよう"と思った次第。古賀さんのツイートも参考になる。
ファイル生成系のmixタスクを書くときはよくMix.Generator使う。phoenixのmixタスクがコードの参考になりますねhttps://t.co/i9wS7SGnIP
— 古賀 祥造 (@koga1020_) 2020年11月10日
#ElixirDI
また、"VRの世界"については画像がある方がわかりやすいので、こちらのツイートをご紹介。
今日の #NeosVR
— フリック@第2期公式VIVEアンバサダー/仮想世界創造機構-VCM (@TewiEwi_no96) 2020年11月10日
①piacereさんと #ElixirDI のリハーサルして~
②れにうむさんのワールドに行って~
③NeosVRで湯婆婆を実装してみて~
④遊んだ~ pic.twitter.com/b2QLIAkqoL
GenServerは状態を持っているからオブジェクト?
最初にも触れたましたが、これが本記事を書くことにしたきっかけ。
GenServerのわかりやすい&詳しい説明はこちらを参照。
端的に言えば、「状態を持っており」「メッセージの送受信で処理を行う」動きをするGenServerは、(オブジェクト指向における)"オブジェクト"とも言えるのでは?という提議がLT会中に出てきました。
LT会中では、「状態持ち+メッセージパッシングを"アクター"と呼ぶか"オブジェクト"と呼ぶかの違いでは?」の結論となりました。
備忘メモ。
— みずりゅ(「Elixirへのいざない」技術の泉シリーズで出版:しがないラジオsp65出演) (@MzRyuKa) 2020年11月10日
昨日の #ElixirDI 会で出た話題の一つ。
Q: "状態"をもち"メッセージ"でやりとりする『GenServer』はオブジェクトみたいだね
A: 状態持ち+メッセージバッシングを"アクター"と呼ぶか"オブジェクト"と呼ぶかの違いでは?
EDI会終了後のお茶会ではもっと詳しく解説されてました。
自分も、同じようなことを考えたことがありました。
しかし、アクターモデルの概念を知り、関数型言語とオブジェクト指向言語の差異から、「オブジェクトとは異なるよなぁ」と考えるようにはなっていました。
関数型言語の特徴は、同じ引数を渡した場合は必ず同じ結果が返ってくる、です。
これに対して、"状態"を保持しているとその"状態"によって返ってくる値が異なる可能性がある、のでオブジェクトのようにも見えてしまいます。
しかし、これはDBやファイルの中身のような"副作用"に関係する部分です。
この副作用の部分だけをみて、"オブジェクト"と呼ぶのには違和感が出てきました。
お茶会で出ていた話
EDI会のお茶会(≒懇親会)では、上述の「GenServerは状態を〜」に関連した話も出ていました。
いくつかを簡単にご紹介します。
※それぞれの詳しい話については、piacereさんが、elxiir jp Slackのelixirdiチャンネルに記載してくださっています。多謝。
EDIお茶会で出た、そのあたりのネタを、elxiir jp Slackのelixirdiチャンネルにメモしておきました😌https://t.co/jf4x4aOqDU
— piacere@DigiDock (love Elixir&Gravity+仮想世界創造機構) (@piacere_ex) 2020年11月11日
副作用と状態について
関数型の利点は、「同じ入力に対して、同じ出力を返す」=「テストが容易でバグりにくい」があります。
一方で、"状態"があると「同じ入力に対して、出力が異なる」が発生します。つまりは副作用です。
しかし、人間の使うシステムでは、副作用とは無関係ではいられません。それは、DB/ファイル/画面やUI、などに当たります。
本質的な課題は、「状態/副作用をいかに状態/副作用が無い領域と切り分けるか」である、と。
副作用のある箇所と密結合な作りになれば、バグの要因にもなります。
そうならないよう、モジュール分離/ライブラリ化、TDDを行って、安全設計していくのが良いとのこと。
型安全について
Elixirは型については割と制限が緩い言語です。
しかし、近年では型定義のしっかりした言語(もしくは、型定義をしっかりする仕組み)が人気です。JavaScriptにおけるTypeScriptが顕著ですかね。
Elixirと同じ関数型言語だと、Haskelも型安全な言語です。
型定義により型安全となることで、コンパイルでコーディングレベルのミスがはじけたり、エディタ補完もできるようになるため非常に利点が大きいです。
しかし、そこを踏まえた上でも、副作用によって問題が発生してしまいます。
Elixirは"エラーは必ず発生する前提"の思想が背景にあるため、型には緩い部分があるようです。
上記URLのスライドから抜粋した思想は以下です。
- プログラムは人が書くものだからバグは避けられない
- システムは、支配下以外にも存在する
- よって、すべてのエラーを把握してコードを書くことは不可能である
- なので、「エラーは必ず発生する」を前提とする
なお、スライドで述べているElixir/Erlangの哲学は、「すごいErlangゆかいに学ぼう!」に書かれているそうです。
これ以外にも
Slack上で、pojiroさんから次のようなコメントをいただけました。
- 関数を状態と分離してテスタブルにすることが大事
- GenServerモジュールがファットにならないように、必要に応じて別モジュールに分離
テスタブルについては、こちらの本が参考資料になるとのこと。
また、OTPのデザインパターンが載っている書籍についても教えていただきました。