Wodipadを作った話

TL;DR

Wodipadを作ったよ

最近、Wodipadなるものを作った。
以下で公開中。
http://ninecubix.net/wodipad

Wodipadは、WOLF RPGエディターのコマンド文を色分けが施された状態で簡単に共有するためのWebサービスで、こんな感じで共有できる
コマンド文が表示される部分はののの茶屋のカル太さんが作成した「コモンイベントリプレイサー」をElmに移植したものを使用。
Elm移植版のコモンイベントリプレイサーとそのサンプルは以下にある。左上のCOMPILEを押せば右側に表示される。
https://ellie-app.com/47c7psNn8Ksa1/0


Twitterなどで「この処理はこう書けばいいよ」というのを見せたい時や「なんでこういう処理だと動かないの?」といった質問をしたい時などが主な活用方法になりそう。

Wodipadの宣伝はここまで。

開発~完成まで

2017年2月頃、カル太さんTwitterでコモンイベントリプレイサーを作っているのを見かけて「codepadとかのソースコード共有サイトみたいにWeb上で共有できればかなり便利なのでは?」と思い開発開始。

当時は第七回うでぃおふが近かったので、そのくらいには完成させたいなーと思いつつ作っていると2日くらいで共有するところまでは作れた。
しかし、ここで公開しておけばよかったのに無駄にタグ機能やユーザー登録機能を付けようとしていたら当然の如く間に合わず。
その後、ダラダラと開発を続けてはいたけど思うように進まず。いつしかソースコードに触ることすらなくなってた。

そして時が経ち、5月。

Elmというプログラミング言語を知った。
その時は、過去にCoffeeScriptで書いていたコードを書き直したり、コモンイベントリプレイサーをElmに移植したりして遊んでた。

ある時ふと「これでWodipadを作ったらいいのでは」と思い、実際に作り始めてみたけど、Navigationを使ってみてもよくわからず、elm-spa-exampleで使っているところを見ても冗長に感じてしまい、ElmでのWodipad開発は一度諦めた。

また時が経ち、8月。

Electron+Elmでツールの作成をしているうちに、段々とElmに慣れてきたので、改めてWodipadを作り直そうと思った。
最初はまたNavigationを使って書いてたんだけど、やはり何か合わず。
他の書き方のサンプルはないかと調べてみたら、office-makerを発見。
PageごとにMainを作る分け方がすごく肌に合ったのでこの分け方を参考にしてWodipad開発再開。

そして、8月21日に完成したWodipadを公開。
今回はとにかく早く公開しようと思ってたので、共有機能ができた時点で公開した。

開発環境とか

バックエンドはRuby+Padrinoで書いてpumaで動かしてる。
PadrinoはRailsよりも手軽で扱いやすいと思う。

フロントエンドはElm+Sass。
最初はCoffeeScript+Haml+Sassだったけど、フロントエンドを静的型付き言語で書きたい欲が強かった。
でもTypeScriptやHaxeで書くのは面倒くささが強かった。
何かもっとシンプルで書きやすい(あとHaskellっぽい)言語はないかなーと思って探している時に、Elmを発見。
そして先述の流れから、今の構成になった。

開発環境はWindowsだが、本番環境はCentOS7なのでうまく動かないのではないか、と思っていたら、予想通り問題が起きた。
が、一番大きい問題の原因が本番環境のRubyのバージョンが低かったということだけだったので、rbenvを導入して開発環境のRubyのバージョンと一致させるだけで解決。
こまごまとした問題もあるにはあったが、特に苦労することなく解決し、無事に公開できた。

困ったこととか

Elmはコンパイルさえ通れば実行時エラーはほぼ発生しないので、特に困ることがなかった。
実際、過去にElmに移植したコモンイベントリプレイサーをコンポーネントに分割して書き直したりしたが、特に問題なかった。

当然ながら論理エラーは流石に防げないので、その辺を修正した程度。

例えば、行頭にスペースがあったらシンタックスハイライトが効かなくなるのを修正したり、

parseCommand : String -> Command
parseCommand input =
-   case runParser ruleCommand None input of
-     Ok (state, stream, command) ->
-       command
-     Err (state, stream, errors) ->
-       None
+   let
+     newInput =
+       input
+         |> Regex.replace Regex.All (Regex.regex "^\\s*|\\s+$") (\_ -> "")
+   in
+     case runParser ruleCommand None newInput of
+       Ok (state, stream, command) ->
+         command
+       Err (state, stream, errors) ->
+         None

"|■条件分岐(変数)"みたいなやつのシンタックスハイライトが効いていなかったのを修正したり。

ruleCommand : Parser Command Command
ruleCommand =
-   regex "^( \\|)*" *> ruleCmd
+   regex "^(\\ ?\\|)*" *> ruleCmd

(はてな記法がElmのシンタックスハイライトに対応していなかったのでHaskellシンタックスハイライトを使用)

あとは、Ruby側で起きているエラーの原因特定が面倒だったくらい。

所感

メインの機能ができたらさっさと公開しよう、と思った。
でないと開発当初のように無駄に機能を付け足そうとして放置することになる。

あと、フロントエンドをElmで開発するのはすごく良いなと思った。

まず、言語仕様がかなり小さく覚えやすい。
Core Languageの説明が1ページしかない程度には小さい。

次に、制限が多い。

  • 変数の書き換えができない(常にconstがついているようなもの)
  • 関数はその外部の状態などに干渉できない(引数として受け取った情報(入力)に依存した結果を返すことしかない)

などの制限がある。
こういった制限は、テストのしやすさや、コードの保守性の向上に繋がるし、グローバル変数の状態をプログラマが気にする必要がなくなって負担が減る。

次に、通常は言語仕様が大きめのJavaScript(というかECMAScript)の知識が特に必要ない。
Elm自体の仕様が小さいことも相まって、プログラミング初心者にも向いているのではないだろうか。ちょっと特殊な文法に感じるかもしれないけど。
ライブラリだけでは機能が足りないと思った時のみNativeやport等でJavaScriptに触れる必要があるが、そう思った時は既にJavaScriptに触れているか、基礎文法くらいならすぐに分かるくらいにはなっていると思う。

他にもコンパイルが通れば実行時エラーがほぼ起きないところとか、MVCフレームワークの選択に悩まされる必要がないとか色々利点があってすごく良い。
Electronと組み合わせればデスクトップアプリケーションも作れるし、今後はElmで開発をしていくことが増えそう。

欠点は、まだ日本語の情報がかなり少ないことや、言語のバージョンがまだ0.18だということだろう。

日本語情報に関しては、2017年9月27日にElmの本が出るようだし

基礎からわかる Elm

基礎からわかる Elm

Amazon

そこからさらに日本語情報とElmユーザーが増えていけば嬉しい。

バージョンに関しては、将来破壊的変更が起こりうる可能性があるのがつらい。しっかりと追いかけて最新版に追従していけるなら大丈夫そう。

今後の予定

  • タグ機能追加
  • 最近共有されたコード(直近5個くらい)一覧を追加
  • ユーザー登録機能追加
    • ふぁぼ機能追加
    • プライベート共有

さいごに

どんどんWodipad使ってね!
あとElmたのしいよ!!!!!