Elm を実戦投入した話 2018年冬

弊社製品の一機能を作るにあたり、設計と開発を自分一人でやる機会があったため、Elm を採用しました。その経験にまつわる、初心者に役立ちそうな話をします。

## Elm 採用動機

Elm を後述する手順で勉強し、本番で必要な要素を詰め込んだサンプルプロジェクトを作ってみて、これならいけると確信した上で採用を決めました。

1. 普段 Vue.js を使用しています。v0.x 系から触ってきましたが、v2 になって本当に使いやすくなりました。ただ Vuex がもうちょっと洗練されてくれればいいですね。
2. Haskell を触ってみた際に気づいたのですが、自分はイミュータブルな世界が好きだということです。変数が何の値を指しているのか一意であってほしい。
3. 型。

## Elm の学習方法について

ほぼこの通りでした。
[2019年 Elmをはじめる人が最初に読むページ](https://qiita.com/arowM/items/5ec5853298fc880353b7)

1. [Elm guide](https://guide.elm-lang.org/) を一通り読む
2. 各パッケージの使用方法はまず https://package.elm-lang.org で確認する
    * サンプルコードが結構載っている
    * あるいは GitHub でコード検索すると、どう書けるか分かる
3. v0.18 と v0.19 の変更点をざっくり把握しておくと、使える情報を見分けるのに役立つ
    * https://github.com/elm/compiler/blob/master/upgrade-docs/0.19.md
    * 便利そうな Elm パッケージが 0.19 で使用できるかどうか、elm.json が存在するか否かですぐ判断できる
    * [Elm Tutorial](https://www.elm-tutorial.org/) は（まだ）0.19 に未対応だということ
    * elm-lang/* に属するパッケージの情報は 0.18 以前のものだということ。ググるとすぐにひっかかってくるので惑わされないで！
        * <img width="936" alt="Screenshot 2018-12-03 07.52.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/15528/fc24e63b-4054-f195-c3fb-8d175181851f.png">
4. SPAを作るので、[elm-spa-example](https://github.com/rtfeldman/elm-spa-example) を頑張って読み解く
    * 解説 https://dev.to/rtfeldman/tour-of-an-open-source-elm-spa
    * どういう単位で Elm ファイルが別れているかを把握する
    * ページ切り替えをどう実現しているか理解する
    * ログインユーザ情報などの、全てのページで使用する情報をどう保持しているかを理解する
    * `type Username = Username String` の利点を理解する
    * 読み解き方を別記事にまとめます
5. わからないことを Elm-jp discord の beginners チャンネルで色々質問させてもらった
    * 皆さん親切丁寧で返信も早いので、一人で悩む時間がもったいない
    * 積極的にパブリックで質問したほうが、コミュニティを盛り上げるための貢献にもなる状況だと思う
    * [Ellie](https://ellie-app.com) が最小限のコードを示して質問するのに便利

## Elm で一定規模のアプリケーションを作り上げてみての感想

* 今後も Elm で書きたいです。今回アニメーションを使わなかったので、そこの書き味が問題なければいつでも採用していいかも。SSR は知らん
    * あくまで自分の製品では。
* 学習コストはあるが大きいとは思わない。Vue.js を採用できるなら代わりに Elm にしても必要なコストは同等。…言い過ぎたかな、英語のドキュメントがそんなに苦にならない前提。Haskell も Monad も知らなくて大丈夫。それを学ぶきっかけにはなる
* Elm で不具合が少なくメンテしやすい良い設計にするには、良いモデルを作れるかどうかが大きいと思った。良いモデルとは何か...それを学ぶには先人のコードを読み、自分でコードを書くしか無いのか
* 型とコンパイラメッセージのおかげでリファクタリングしやすく、大きなアプリケーションを構築しても安心感がある
* 0.19 以降でパフォーマンスが問題になることがあるのか、それはどんな時か知りたい
* CSS は CSS でいいんじゃないかな BEM とか使ってさ

## その他素晴らしい情報

* [[Elm] Decoder a からいろいろ理解ってしまおう](https://qiita.com/ymtszw/items/1cabbdbda4273b4c1978)
    * これ読んで `Json.Decode.Decoder` を使って自由自在に JSON をデコードできるようになりました
* ["Making Impossible States Impossible" by Richard Feldman](https://www.youtube.com/watch?v=IcgmSRJHu_8)
    * モデル設計の一つの指針
    * `type Username = Username String` の解説
* [Elm開発における思考フロー](https://qiita.com/ababup1192/items/629585f8b2ae953a9b47)
    * まずビジネスロジックをTDDで作ることで、ビジネスロジックをビュー等から分離する話
* [10000行超のElmを書いて見つけたベストプラクティス](http://jinjor-labo.hatenablog.com/entry/2016/12/04/002210)
    * 先輩の言う「ベストプラクティス」にはまず従っとくもんだ

## 作ったアプリケーションの elm.json を貼っておく

```json
{
    "type": "application",
    "source-directories": [
        "src"
    ],
    "elm-version": "0.19.0",
    "dependencies": {
        "direct": {
            "elm/browser": "1.0.0",
            "elm/core": "1.0.0",
            "elm/html": "1.0.0",
            "elm/http": "1.0.0",
            "elm/json": "1.0.0",
            "elm/random": "1.0.0",
            "elm/time": "1.0.0",
            "elm/url": "1.0.0",
            "elm-community/json-extra": "4.0.0",
            "elm-community/list-extra": "8.1.0",
            "myrho/elm-round": "1.0.4",
            "surprisetalk/elm-bulma": "6.1.2"
        },
        "indirect": {
            "elm/parser": "1.1.0",
            "elm/virtual-dom": "1.0.2",
            "rtfeldman/elm-iso8601-date-strings": "1.1.2"
        }
    },
    "test-dependencies": {
        "direct": {
            "elm-explorations/test": "1.1.0"
        },
        "indirect": {}
    }
}
```