LoginSignup
15
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-24

Merry Christmas! 🎅🏼

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

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

アプリケーションの説明

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

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

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

改修の計画を立てよう

まず、今回の改修事項を書き出してみましょう。
改修前のスナップショット[^注釈]
[^注釈]:改修に際して開発環境を最新化しています。記事が長くなってしまうので今回は省略。
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 さんが挙げていた例を参考にしました
  • カスタム型を活用したかったけど、実装が大きくなりそうなので見送り(さよなら〜)
比較用の関数
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.hereCmd.batch に追加する 削除しました
  • Task.perform Tick Time.nowCmd.batch に追加して、subscriptions を廃止する

まとめ

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

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

2019年を振り返る

2020年に向けて

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
1