初めて作ったアプリケーションをリファクタリングして、Elmに入門した1年を振り返る

#### Merry Christmas! 🎅🏼

この記事では、2019年2月に Elm を始めた私が1年間の経験をもとに、Elmで初めて作ったアプリケーションをリファクタリングしていきます。当時の自分ができなかったことが、今の自分ならできるはず！この記録がElm入門者の壁を乗り越える助けになれば嬉しいですね。

できるだけ簡潔に書けるように頑張ります。「もっと説明がほしい」「詳しく知りたい！」というリクエストがあれば追記します。私はたくさんの記事を書く性格ではないので、少ない記事を大切に育てたい。

#### アプリケーションの説明
私はモータースポーツが好きです。自動車のレースです。ここ数年、日本人選手や日本チーム活躍も目立つので皆さんもニュースで見かけたことがあるかもしれません。「自動車を走らせるだけじゃん」と思われるかもしれませんが、いくつかの種目が世界各地で行われていて、選手もファンも大忙し！

そこで、レースの日程がひと目でわかるカレンダーを作りました。

MotorSportsCalendar 2019
https://y047aka.github.io/MotorSportsCalendar-2019/


# 改修の計画を立てよう

まず、今回の改修事項を書き出してみましょう。
[改修前のスナップショット](https://github.com/y047aka/MotorSportsCalendar-2019/tree/21a82e902e7ee65e52579f4a4736cb03d8b1572c)\[^注釈]
\[^注釈]:改修に際して開発環境を最新化しています。記事が長くなってしまうので今回は省略。
https://github.com/y047aka/MotorSportsCalendar-2019/pull/1


- **コードの見通しを良くする**
→ view の整理など

- **データのロード速度を改善する**
→ 複数の JSON のロードを `Task.sequense` で直列に実行しているので、`Cmd.batch` に変更して改善する

- **現在日付の取得タイミングを早くする**
→ `subscription` ではなく、`init` の際に取得する

では改修スタートです。


# コードの見通しを良くする
以下の Pull Request にコミットをまとめました
https://github.com/y047aka/MotorSportsCalendar-2019/pull/2

#### モジュール分割に対する自分なりの基準ができた
- `The Elm Architecture` に影響しない箇所は、分割するほうが見やすいのであればモジュールに切り出していく

#### Elm の記法に目が慣れてきた
- 記法に慣れて一時変数が不要になったので `let ~ in` を削除する
- `List.map a b` の書き方に慣れて、`b |> List.map a` よりも明快だと思うようになった


# データのロード速度を改善する
管理の都合でカレンダーの情報を複数の JSON で構成しています。これを全てロードして使用していたのですが、当時はまだ `The Elm Architecture` を理解しないまま先に進んだため、`Task.sequense` での実装になっています。全ての JSON をロードして表示するまでに数秒かかることがあったので、改善することにしました。

以下の Pull Request にコミットをまとめました
https://github.com/y047aka/MotorSportsCalendar-2019/pull/3

#### Cmd.batch に変更する
- 複数の `Cmd msg` を束ねるために `Cmd.batch` を使用する
- ただ使うだけであれば `Task` よりも簡単
- それぞれのロードが非同期に行われるので、完了した順番に `Model` へ追加される（どうしよう？）

#### ロードした JSON を任意の順番にソートする
- `List.sortWith` を使うと、任意の順番で比較できるようになります
- 専用の `compare` 関数を作成しました
- Elm-jp の Discord で @arowM さんが挙げていた例を参考にしました
- カスタム型を活用したかったけど、実装が大きくなりそうなので見送り（さよなら〜）

```elm:比較用の関数
import List.Extra as List -- List.dropWhile を使うために List.extra をインポートする

compare : Season -> Season -> Order
compare a b =
    let
        -- 定義した順番にソートされる
        enumarate =
            [ "F1"
            , "Formula E"
            , "WEC"
            , "WEC"
            , "ELMS"
            , "IMSA WSCC"
            , "IndyCar"
            , "NASCAR"
            , "SUPER FORMULA"
            , "SUPER GT"
            , "DTM"
            , "Blancpain GT"
            , "IGTC"
            , "WTCR"
            , "Super Taikyu"
            , "WRC"
            , "MotoGP"
            , "Red Bull Air Race"
            ]
    in
    if a.seriesName == b.seriesName then
        EQ

    else
        case List.dropWhile (\x -> x /= a.seriesName && x /= b.seriesName) enumarate of
            x :: _ ->
                if x == a.seriesName then
                    LT

                else
                    GT

            _ ->
                LT
```

改善は成功しました！


# 現在日付の取得タイミングを早くする

以下の Pull Request にコミットをまとめました
https://github.com/y047aka/MotorSportsCalendar-2019/pull/4

アプリケーションの仕様上 `Time.here` を使ってもあまり意味がなかったので、`zone`は削除しました（バグっちゃったね）
https://github.com/y047aka/MotorSportsCalendar-2019/commit/e5e3278942448773c8c80909069fc850d8f7c927

- ~~`Task.perform AdjustTimeZone Time.here` を `Cmd.batch` に追加する~~ 削除しました
- `Task.perform Tick Time.now` を `Cmd.batch` に追加して、`subscriptions` を廃止する


# まとめ

最新のコードはこちらからご覧ください
https://github.com/y047aka/MotorSportsCalendar-2019

大晦日に厳かな気持ちで MotorSportsCalendar 2020 を作りたいと思います。

# 2019年を振り返る
- 8月25日のイベント『Elm Meetup in Summer』で登壇しました
    - 発表資料：[私たちは絶対に絶対に
Ports を頼ったりしない](https://slides.y047aka.me/2019-08-25_we-are-never-ever-getting-back-together/#2)
    - Elm のステッカーを作って配布した
- 12月7日 に Elm のイベント『[ELMP1](https://y047aka.github.io/ELMP1/)』を企画・実施しました


# 2020年に向けて
- 1月10日 に1966年のル・マン24時間レースを題材にした映画[『フォードVSフェラーリ』](http://www.foxmovies-jp.com/fordvsferrari/)が上映されます
    - マット・デイモン と クリスチャン・ベイル のダブル主演です（豪華！）
    - モータースポーツに詳しくなくても面白いので、ぜひ観てみてください（私は試写会で観た）
- デイトナ24時間レースまで、あと1ヶ月！
- 4月に Evan Czaplicki（Elm を作った人）が来日するイベント [Elm Japan 2020](https://elmjapan.org/) が計画されているので、一緒に盛り上げていきたい
- ELMP2 と ELMH（北海道 / 兵庫 / 広島）もやりたいね！
- モータースポーツのアプリケーションをいくつか作りたい
- 種子島でロケットの打ち上げを観たい