プロダクト開発における、Elmを選ぶポイント・

選ばないポイント

誰?

お名前

ABAB↑↓BA @ababupdownba

 

お仕事で、SaaSのWebサービス作ってます

Scala・TypeScript(B)・Elm(C)

 

24時間 Elm bot

前提

Elm は、

JavaScriptにコンパイルできる関数型言語

WEBサイトやWEBアプリケーションを作るためのツール

前提

Elm は、

JavaScriptにコンパイルできる関数型言語

WEBサイトやWEBアプリケーションを作るためのツール

比較対象は、

JavaScript(TypeScript)

または、Angular, React, Vue

前提

Elm は、

JavaScriptにコンパイルできる関数型言語

WEBサイトやWEBアプリケーションを作るためのツール

比較対象は、

JavaScript(TypeScript)

または、Angular, React, Vue

普段お仕事で使っている

ElmとTypeScriptのイメージ比較

Elm は飛行機の乗客

  • 乗客はパイロットに指示は、ほぼ出せない、乗っているだけで良い(安全・学習コスト低い)
  • 融通は効かないが、目的地へはほぼ一直線(速い)

 

  • 空港にのみ着陸する(細かいことをしようとしたら、そこから自力で移動・筋力が必要)

ElmとTypeScriptのイメージ比較

JavaScript(TypeScript)は車の乗客

  • 細かい指示をすることができる(自由度は高い)
  • いろんなところに寄り道できて楽しい(モダン技術の享受がしやすい)

 

  • 覚えるべきことが多い(出せる指示が多いため)
  • 危険な旅になりやすい(自由度の代償)
  • 選択肢の多さが速度に影響を及ぼす(ライブラリ選定・テクニック選定)

それではポイント比較

これから3つのポイントについて、Elmを選択する・しない理由について話していきます。

ポイント1

高い品質を保ち続ける必要があり、人の変動が多い(特に新人)プロダクトではElmを選ぶ

品質よりもスピードと自由度を求め、人の変動が少ないのであれば、Elmを選ばない

foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

  • 型をキチンとつけてください

  • 副作用を含めないでください
  • 必要のない変数を削除してください
  • 三項(条件)演算子を用いてください
  • テストコードを書いてください
foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

  • 型をキチンとつけてください

  • 副作用を含めないでください
  • 必要のない変数を削除してください
  • 三項(条件)演算子を用いてください
  • テストコードを書いてください
foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

  • 型をキチンとつけてください

  • 副作用を含めないでください
  • 必要のない変数を削除してください
  • 三項(条件)演算子を用いてください
  • テストコードを書いてください
foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

  • 型をキチンとつけてください

  • 副作用を含めないでください
  • テストコードを書いてください
  • 必要のない変数を削除してください
  • 三項(条件)演算子を用いてください

前提条件付き

foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

  • 型をキチンとつけてください

  • 副作用を含めないでください
  • テストコードを書いてください
  • 必要のない変数を削除してください
  • 三項(条件)演算子を用いてください
foo(x: any): void {
  let random = Math.random()
  let result = 1;
  
  if(random % 2 == 0) {
  	result = result * x * random + 2;
  } else {
  	result = result * x - 2;
  }
  
  this.result = result;
}

学習・レビューコスト

あなたがレビューすべきコードです

可能な限りツッコミを入れてください

  • 型をキチンとつけてください

  • 副作用を含めないでください
  • テストコードを書いてください
  • 必要のない変数を削除してください
  • 三項(条件)演算子を用いてください

学習・レビューコスト

僕が考えるレビューの優先順位

 

 

  1. テスト可能な状態へ持っていかせたい
  2. テストを書かせたい(仕様を明らかにし、要求を担保しておきたい)
  3. リファクタリングをさせたい

学習・レビューコスト

僕が考えるレビューの優先順位

 

 

  1. テスト可能な状態へ持っていかせたい
  2. テストを書かせたい(仕様を明らかにし、要求を担保しておきたい)
  3. リファクタリングをさせたい

製品品質の担保

学習・レビューコスト

僕が考えるレビューの優先順位

 

 

  1. テスト可能な状態へ持っていかせたい
  2. テストを書かせたい(仕様を明らかにし、要求を担保しておきたい)
  3. リファクタリングをさせたい

可読性・拡張性の担保

foo : Int -> Int -> Int
foo x randomValue =
    if modBy 2 randomValue == 0 then
        x * randomValue + 2

    else
        x - 2

学習・レビューコスト

Elmでは、十中八九誰が書いても以下のようなコードになります

  • any, voidが存在しない

  • 副作用は型が違うので起こせない

  • 一時変数はlet-in構文をわざわざ使わなければならない

  • if-else等の分岐が全て式(条件演算子は存在しない)

  • どう足掻いてもテストは書ける

foo : Int -> Int -> Int
foo x randomValue =
    if modBy 2 randomValue == 0 then
        x * randomValue + 2

    else
        x - 2

学習・レビューコスト

Elmでは、十中八九誰が書いても以下のようなコードになります

  • any, voidが存在しない

  • 副作用は型が違うので起こせない

  • 一時変数はlet-in構文をわざわざ使わなければならない

  • if-else等の分岐が全て式(条件演算子は存在しない)

  • どう足掻いてもテストは書ける

foo : Int -> Int -> Int
foo x randomValue =
    if modBy 2 randomValue == 0 then
        x * randomValue + 2

    else
        x - 2

学習・レビューコスト

Elmでは、十中八九誰が書いても以下のようなコードになります

  • any, voidが存在しない

  • 副作用は型が違うので起こせない

  • 一時変数はlet-in構文をわざわざ使わなければならない

  • if-else等の分岐が全て式(条件演算子は存在しない)

  • どう足掻いてもテストは書ける

foo : Int -> Int -> Int
foo x randomValue =
    if modBy 2 randomValue == 0 then
        x * randomValue + 2

    else
        x - 2

学習・レビューコスト

Elmでは、十中八九誰が書いても以下のようなコードになります

  • any, voidが存在しない

  • 副作用は型が違うので起こせない

  • 一時変数はlet-in構文をわざわざ使わなければならない

  • if-else等の分岐が全て式(条件演算子は存在しない)

  • どう足掻いてもテストは書ける

foo : Int -> Int -> Int
foo x randomValue =
    if modBy 2 randomValue == 0 then
        x * randomValue + 2

    else
        x - 2

学習・レビューコスト

Elmでは、十中八九誰が書いても以下のようなコードになります

  • any, voidが存在しない

  • 副作用は型が違うので起こせない

  • 一時変数はlet-in構文をわざわざ使わなければならない

  • if-else等の分岐が全て式(条件演算子は存在しない)

  • どう足掻いてもテストは書ける

foo : Int -> Int -> Int
foo x randomValue =
    if modBy 2 randomValue == 0 then
        x * randomValue + 2

    else
        x - 2

学習・レビューコスト

Elmでは、十中八九誰が書いても以下のようなコードになります

  • any, voidが存在しない

  • 副作用は型が違うので起こせない

  • 一時変数はlet-in構文をわざわざ使わなければならない

  • if-else等の分岐が全て式(条件演算子は存在しない)

  • どう足掻いてもテストは書ける

学習・レビューコスト

僕が考えるレビューの優先順位

 

 

  1. テスト可能な状態へ持っていかせたい
  2. テストを書かせたい(仕様を明らかにし、要求を担保しておきたい)
  3. リファクタリングをさせたい

学習・レビューコスト

僕が考えるレビューの優先順位

 

 

  1. テストを書かせたい(仕様を明らかにし、要求を担保しておきたい)
  2. リファクタリングをさせたい

製品品質の担保

学習・レビューコスト

僕が考えるレビューの優先順位

 

 

  1. テストを書かせたい(仕様を明らかにし、要求を担保しておきたい)
  2. リファクタリングをさせたい

可読性・拡張性の担保 -> 多くの場合、ほとんど満たしている

学習・レビューコスト

レビュイー(学習者)視点

  • 書き方が決まっているため学習に掛けるコストが少ない
  • 多くのアンチパターンはコンパイラが通さないため、設計レベルであったり仕様に対するレビューが受けやすい
  • レビューの応酬が少ない

学習・レビューコスト

レビュワー視点

  • テストがどう足掻いても書けるため、テストが書ける形に持っていく必要がない、テストを書かせることを促しやすい

  • レビューの応酬が少ない

ポイント2

プロダクトの細かな要求を筋力で乗り越え続ける覚悟があるなら、Elmを選ぶ

出来合いの仕組みを組み合わせて簡易に出来上がるのであれば、Elmを選ばない

GoogleやTwitterの例

Google検索やTwitterのツイートや投票の体験はシンプルながら素晴らしい体験を提供してくれる

がしかし、これらをコンポーネント提供されても他サービスでは使い物にならない -> ドメインに対して体験が一意に存在する

GoogleやTwitterの例

Google検索やTwitterのツイートや投票の体験はシンプルながら素晴らしい体験を提供してくれる

がしかし、これらをコンポーネント提供されても他サービスでは使い物にならない -> ドメインに対して体験が一意に存在する

Elmでも支障は無い

Angular Material UIの例

プロダクト独自の体験を直接表現するものでは無いが、クオリティの高さやカスタマイズ性は高い(強いものは強い)

ElmではUIライブラリは無いのか?

存在はする(例えば、elm-mdlなど)が、Elmがコンポーネント指向をしていない(TEAは疎結合でCSSやロジックを内包するには向いていない)

ポイント1での品質やコードの統一性を重視しているためトレードオフとなる

ロジックをゴリゴリ書いたり、CSSをゴリゴリ書く覚悟と筋力が求められる

ポイント3

意思決定のスピードや依存の少なさを重視するのであれば、Elmを選ぶ

技術自体を学び遊びたいのであれば、Elmを選ばない

技術選定の議論・維持コスト

どのフレームワークを使っていますか?

  • Angular

  • React

  • Vue

  • (jQuery)

どの通信ライブラリを使っていますか?

  • Angular Http Client & RxJS

  • Axios

  • Superagent

  • Fetch

  • Request

技術選定の議論・維持コスト

どの状態ライブラリを使っていますか?

  • RxJS

  • Akita

  • Akita + RxJS

  • React Hooks

  • Redux

  • Redux + redux-saga

  • Redux + redux-thunk

  • Redux + Hooks

  • Vuex

技術選定の議論・維持コスト

どのコレクションライブラリを使っていますか?

ちょっともうやめておきましょう・・・

技術選定の議論・維持コスト

(プロダクションやネット上で)今までのような議論をしたこと・見かけたことがありますか?

 

技術選定の議論・維持コスト

ある・ない

たのしんでる・うんざりしている

多すぎるサポートされなくなった技術の保守や依存に苦しんでますか?(見聞きしたことはありますか?)

技術選定の議論・維持コスト

苦しんだことがある・苦しくない

よく見聞きする・聞いたことがない

掛けたコストに見合っていますか?

技術選定の議論・維持コスト

  • 変動しやすい時代とは言え、粒度の細かすぎる技術に対してのコストとしては高すぎる

  • 初学者に対して優しい環境とは言えない

    • キャッチアップが難しい

    • 環境構築が難しい

どの通信ライブラリを使っていますか?

The Elm Architecture!

技術選定の議論・維持コスト

どの状態ライブラリを使っていますか?

技術選定の議論・維持コスト

The Elm Architecture!

どのコレクションライブラリを使っていますか?

技術選定の議論・維持コスト

9割

Elmをやる上で技術選定の議論は、ほぼ発生しません(発生したとしても、Elmの外の技術の話がほとんど)

議論の多くはデータ構造やモジュールの設計の議論で、アプリケーションの本質的な会話に時間を費やすことができます

技術選定の議論・維持コスト

これどうやって解決するの?の答えのほとんどが筋力です

Elmで維持するものはElmそのものです。

Elmが倒れること自体は大きなリスクですが、jQueryの例を見ているとどれも同じです。細かい何かに振り回されることはありません

技術選定の議論・維持コスト

まとめ

当日の僕が上手くまとめてくれる

Elm for Production

By ababup1192

Elm for Production

プロダクト開発でElmを選ぶかどうかを書いた資料

  • 1,154