Runner in the High

技術のことをかくこころみ

Elm Europe 2019 にスピーカーとして参加した

2019/6/27-28にかけて開催されていた Elm Europe 2019 というカンファレンスにスピーカーとして参加した

f:id:IzumiSy:20190630225553p:plain

このような海外カンファレンスへの参加は、だいぶ昔にサンフランシスコへ行ったとき以来だし、とくにスピーカーとして登壇するというのは人生初だった。英語でトークをやるというのは非常に緊張する体験だったけれど、率直に言ってめちゃくちゃ楽しかった。

詳しいカンファレンスの内容などはおそらく所属している会社のブログの方で書くはずなので、こっちではもう少しパーソナルなことを書こうと思う。

CFPの応募

Elm Europe は日本のちょっと大きめのカンファレンスと同じで、スピーカーを CFP で募集している。3月ごろに、会社の同僚から募集しているということを知らされ、雑な CFP をサブミットした。このとき、たしかインターンのイベントかなにかがあり、社内で酒を飲んでいたのでかなり適当な英文を書いた。

後日、朝起きて携帯でメールチェックをすると Elm Europe から以下の内容でメールが届いており、腰を抜かした。

f:id:IzumiSy:20190630231524p:plain

CFP の応募から当日までほぼ2,3ヶ月ほどの時間があったにも関わらず、結局スライドはギリギリまで作っていた気がする。

一方で、他の参加者とは Discord のチャンネルで細々としたやりとりを(もちろん英語で)していたが、みんなスライドづくりを始めるのが非常に早い。1ヶ月くらい前には、みんな「もう資料はできてるよ!」というようなことを言っていて、すごくペースが早いな、と思った。

日本からフランスへ

当日は日本の夜11時に羽田の国際便に乗ってフランスへ向かった。途中、機内でなんらかの旅客トラブルがあり、乗務員が「お客様の中にお医者様か看護師の方はいらっしゃいませんか」というアナウンスをしていて、初めてドラマや映画でしか見たことのなかった体験をした。また、前に座っているフランス人カップルがものすごい勢いで機内でイチャイチャしていて、カルチャーを感じた。

朝4時にフランスのシャルルドゴール空港へ到着。スピーカーのホテルはその日は15時からしかチェックインできないということで、どうにかそれまでの11時間を過ごさねばならない... しかし Elm Europe の Discord でいろいろ話しているうちに、オーガナイザーのアパートの部屋へ行ってもいいということで、朝7時ごろにパリの街へ繰り出した。

自分が滞在していた期間、パリはずっと晴れで朝は暑すぎもせず寒すぎもせず非常にちょうどよい気温であった。夜のパリは非常に危険らしいが、朝のパリは非常に趣がある。

f:id:IzumiSy:20190626064414j:plain:w550

というわけでオーガナイザーの住んでいるアパートの住所までテクテク駅から歩き、30分ほど待つも一向に Discord で返事がない。さすがにしびれを切らし、もう自分で会場まで向かってしまおう、ということでその場をあとにした。

会場へ

f:id:IzumiSy:20190626083317j:plain:w550

Elm Europe の会場は Efrei Paris という、いわゆる日本でいうところのコンピューター系の専門学校のようなところだった。

校舎のなかは、こんな感じのキレイめな雰囲気になっていて非常によい。 f:id:IzumiSy:20190626083537j:plain:w550

この日はカンファレンスの前日で、会場では Elm と GraphQL を使ったアプリケーションを開発するワークショップが開催されていた。なんと8時間にも及ぶ長いワークショップとのこと。なお、このワークショップで講師をしていたのは elm-graphql や elm-typescript-interop を作っている人だった。こういう人にサクッと会えるのが海外のカンファレンスのいいところだ。

しばらくすると、お昼ごはんとして軽い食事が出てきた。 f:id:IzumiSy:20190626132744j:plain:w550

こちらは、準備中の会場 f:id:IzumiSy:20190626142959j:plain:w550

お昼を過ぎたあたりから、天候の具合がおかしくなってくる。どう考えても暑すぎるのだ。真夏の日本と同じか、それ以上に暑い。半ズボンを持ってきていなかったことを後悔した。日本に帰国してから知ったのだが、どうやら僕が滞在していた週のフランスは記録的な猛暑に見舞われていたらしい。どうりで暑いわけだ...

フランスなどヨーロッパ地域の建造物にはエアコンがないのが普通らしく、このあと向かったスピーカー用のホテルも三ッ星ホテルの癖に部屋には扇風機しかなかった。夜になると、すこしは気温が下がり過ごしやすくなるものの、真っ昼間にエアコン無しで部屋の中にいようものなら、あっという間に脱水して倒れてしまうんではないかと思う。スピーカーホテルは自分含め三人で一部屋という割り振りになっており、なんだか語学留学みたいでおもしろかった。

19時頃からスピーカー限定でディナーが開催され、昼には会えなかった参加者のみんなといろいろな話をする機会があった。丁度隣に座っていた人が SoundCloud のフロントエンドエンジニアで、なんと日本の Elm 勉強会にも参加したことがあるとのことですごく偶然を感じた。この会食には Elm 界隈の超有名なエンジニアであるリチャード・フェルドマンも参加しており(彼は初日のキートーク枠だった)個人的にはとうとう Youtube でしか見たことなかった人が目の前に...! と思ったものの、正直緊張して握手と挨拶しかできなかった。

発表当日

とうとう発表当日を迎える。

会場にはこんな感じののぼりが立てられていて、そこに自分が作っているプロダクトのロゴがあるというのは正直に言ってなんともいえない感動があった。 f:id:IzumiSy:20190627170617j:plain:w550

朝は比較的ひんやりとした天気で、若干半袖だと寒いくらいだった。 f:id:IzumiSy:20190627170658j:plain:w550

iPhoneの紛失

実は発表当日、大きなトラブルに見舞われていた。というのも、スピーカーホテルのルームメイト達と会場にUberで向かう中、なんとポケットから iPhone が滑り落ち、そのままタクシーが行ってしまったのだ。これまで日本で携帯なんか落としたことなんてなかったのにとうとうやっちまった... という失意の念に打ちひしがれながら初日を迎えることになった。

Uber を呼んでくれたルームメイトがドライバーに電話をかけるも、全く出る気配がない。仕方ないのでボイス・メッセージを残してくれたが、これもおそらく気休めにしかならないだろうな、と思った。

しかし、こんなことで凹んでられない。とにかくいまは自分の発表に集中しなくては! と気持ちを立て直す。

自分の番が回ってくる

自分ではナチュラルな笑顔を心がけたつもりだったが、緊張しすぎて引きつった笑顔になってしまっている... 発表前に接続テストがなぜかできず、自分のスライドがまともに映るかも不安だったが、もうここまで来たらやるしかない。

発表中はもう無我夢中だったので、実際どういう感じで自分が話していたのかは全く記憶にない。途中から若干余裕が出てきて、顔を上げて会場を見回したりできたような気がする。発表の直前に、自分の "Review" の発音がちょっとわかりづらいと言われ、正しい発音は日本で言うところの "ウィヴュー" だと教わったが、実際にプレゼンでそのフレーズを話した記憶がない。

下の Age of Empire の壁ユニットを使った型システムのスライドのページはちょっとウケたようで良かった。

発表が終わるとリチャードがステージのところまで来てくれていて「面白かったよ!」と言ってくれた。

こちらからは「僕らのチームも、あなたのカンファレンスでのトークrtfeldman/elm-spa-example を Elm 学習のリソースとして使っていて、すごくインスピレーションをもらっています!」というようなことを伝えたりした。彼は発表中に以下のようなツイートもしてくれていて、わざわざフランスまで来て登壇発表したかいがあったな... という嬉しさがあった。

このツイートは同僚たちにも観測されており、弊社の Elm チャンネルでは「リチャード・フェルドマンがツイートしてる!」と謎の盛り上がりを見せていてウケた。僕らからすれば本当に Youtube の中の存在であった彼が、このようなツイートをしてくれたことには、非常な感動があった。

携帯が帰ってくる

発表の直後、 iPhone のリモートロックの機能を有効にするとスマホ上にメッセージを出せると知り、自分のラップトップからスマホをロックした。

自分は無駄なお金がかからないようにこまめに SIM のローミングを切るようにしていたが、無くしたときはたまたまローミングを有効にしたままだった。スマホの位置情報をチェックすると、どうやらパリの北部にいる。動きが比較的早いところをみると、まだ Uber タクシーの中に残っているようだった。

ダメ押しで端末のメッセージに会場となっている学校の住所を追加する。これでだめだったらもうダメだ、と思いながらあとはただ帰ってくることを祈りながら他の発表を聞いていると、なんと自分の携帯がいつの間にやら学校の教務課(?)へ届けられていた。まさかこんな異国の地でしらない人間の温かみに触れられるとは思わず、とても感動であった。

ルームメイトの二人に「携帯が帰ってきた!」と伝えると、「オイオイマジかよ、信じらんねーぜ。最高の一日だな!」みたいなテンションで、やっぱりこんなふうな落としものが帰ってくるというのはなかなかにレアなことなんだなと再認識した。

感想

Elmの開発者は全世界的に見ても非常に少ない。それだけに、コミュニティがすごく親密で、新しい人に対して開いている。 Elm 本体の開発者を擁する NoRedInk のエンジニア達も大抵会うことができるし、すごくフレンドリーだ。海外の開発者コミュニティに足を踏み入れるのは、確かにこれが初めてだったし、ちょっと英語が話せるとはいえ普段は日本語しか話さない自分が馴染めるのか非常に不安な部分があった。しかし Elm Europe は非常に多様なカルチャーのエンジニア達で構成されていたし、Elmが好きだという気持ちがあれば誰もが楽しめるし、歓迎される場であると思う。

主催者のフランス人である Assus は我々と同じ非ネイティブ・スピーカーで、正直彼の英語は僕から見ても流暢であるとは言えなかった。けれども、参加者のひとりは彼の存在がコミュニティにおける Stress Remover であると言っていた。副次的な効果であるとは思うが、彼自身が Elm Europe のモデレータであるということ、そしてまた彼のキャラクターが Elm Europe の親密で誰もを受け入れるような雰囲気を作っているようにも見えた。このような多様性がコミュニティの中で感じられることは、非常に素晴らしいことだと思う。

下は、アフターパーティで鍵盤ハーモニカを演奏する Assus の写真。こちらも上手いのか下手なのかよく分からなかったが、おもしろかった。

f:id:IzumiSy:20190627185909j:plain:w550

また、今回スピーカーとして参加したことによって、おそらくただの Attendee としての参加では出会わなかったであろう人との出会いもあった。大学を卒業してから、おそらくもう英語を使う機会は無いだろうなと思っていたが、思いがけずこのような形で自分の英語力が生きる機会があり、とても嬉しかった。文化や母語は違えど、プログラミング言語という共通のコンテキストを通してこのような交流ができるというのは、我々ソフトウェア・エンジニアならではではないかと思う。渡航するまでは途方もない緊張感でナーバスだったが、終わってみると想像の200倍は楽しかった。

次はどのカンファレンスで話そうかなぁ。

dayjsと謎の挙動

年と月だけの文字列をDateへ変換すると2月だけおかしくなる

console.log(dayjs('201901', 'YYYYMM').toDate()); // Tue Jan 29 2019 00:00:00 GMT+0900 (日本標準時)
console.log(dayjs('201902', 'YYYYMM').toDate()); // Fri Mar 01 2019 00:00:00 GMT+0900 (日本標準時)
console.log(dayjs('201903', 'YYYYMM').toDate()); // Fri Mar 29 2019 00:00:00 GMT+0900 (日本標準時)
console.log(dayjs('201904', 'YYYYMM').toDate()); // Mon Apr 29 2019 00:00:00 GMT+0900 (日本標準時)

なんで?

github.com

新しいフレームワークを学ぶならTodoMVCではなくRealWorldを参考にしよう

よく新しいフレームワークを学ぶにはTodoアプリを作ってみるのがよい、と言われる。実際、Todoアプリを様々なフレームワークで作ってみたサンプルをまとめたサイトもあったりする。

ところが、実際に業務で作るようなアプリケーションはTodoアプリの範疇を超えている。とくにSPAにもなると、画面遷移やWebAPI連携、大規模な状態管理などなどの条件が増えるので、Todoアプリを作っているときには考慮できていなかった大変さが出てくる。

そこで参考になるのが RealWorld example apps と呼ばれるプロジェクト

f:id:IzumiSy:20190609165127p:plain

端的に言うと、TodoMVCの大規模版

規定のスペックに沿って、様々なウェブフレームワークで作られたアプリケーションのリポジトリがリストアップされている。

f:id:IzumiSy:20190609165323p:plain

スペックについて

"Conduit" is a social blogging site (i.e. a Medium.com clone). It uses a custom API for all requests, including authentication.

要求されているスペックはConduitと呼ばれるMediumクローンを作る、というもので、具体的には以下のような機能を満たしているとのこと。

  • ホーム画面
  • JWTを使ったユーザー登録・ログイン画面
  • ユーザーの設定画面
  • 記事の投稿/編集画面
  • 他ユーザーをフォローする
  • お気に入り記事一覧

ここまでの機能を実装しているアプリケーションとなると、わりとかなり本格派なんじゃないだろうか。

ちなみに、フロントエンド以外にもサーバーサイド・フレームワークによる実装もあるので、サーバーメン的にも参考になると思われる。

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

"初夏のJavaScript祭り2019" にElmのはなしで登壇した

 6/1に開催されたJavaScript祭りというイベントに「jQueryからElmまで」というタイトルで15分枠の登壇をした

 内容はjQueryからJavaScriptを触り始めた自分が、Elmを書くまでにどういう困難を経験してどういう学びを得たのか、にフォーカスを当てたもの。

 フロントエンド界隈はトレンドの変化が早いと言われがちだが、闇雲に新しいフレームワークが乱立しているというわけではなく、どのフレームワークもアプリケーションを作る上での問題を解決するために生まれているのは間違いない。これはjQueryprototype.jsのころから変わっていないし、そもそもテクノロジー自体が問題解決をするためのものであることからも自明だと思う。そう考えると、いまElmを書いている自分は割と遠いところまで歩いてきたなぁ、と感じさえする。

Prop Drilling について

 懇親会の際に、スライドの中で触れていた Prop Drillingアンチパターンなのか? という話になったが、これは正直スライドの表現が悪かったと思っている。

 自分としては、Prop Drilling はその後に触れられるイベント・エミッタを乱用するパターンを説明するきっかけとして使いたいだけで、アンチパターンだとは思っていない。まずモジュール結合度の観点からみても、コンポーネントに渡されるパラメータが増えても結合度は低い状態であるし、コンポーネントに対する入力が増える以外の欠点がないからだ。

余談

 もともと、この発表のインスピレーションは過去のこの記事にある izumisy-tech.hatenablog.com

 ReactのSFCやChoo.jsなどを知ってときに「ビューって関数やん!」と気付いたのを覚えている。

 その後、偶然にもElmを使っている会社へ新卒入社し、前提としてフロントエンド・アプリケーションは関数の組み合せで作れるということが自分の中での当たり前になっていった。一方で、その考えに至るまでに自分が書いていたフロントエンドは全く異なるものだったことを思い出した。一度なにかを知ってしまうと、それを知らなかった頃の自分には戻れない。それでも、どのように自分の考え方が変わっていったかはまだ思い出せる。こんなことを考えながら、今回はスライドを作った。

 登壇にあたっては、最終的にはJavaScriptにトランスパイルされるとはいえ、ElmはほとんどJavaScriptとは別の言語なので参加者層的に楽しんでもらえるかなという不安もあった。事前に主催の方から頂いたアンケートをみてもやはりVue.jsを書いている、という方が多かったし、発表内容にもVue.jsとVuexにフォーカスを当てたものが多かった。

 かくいう自分も、仮に開発対象のアプリケーションがのちのち自分の手を離れることになる場合、あるいは組織自体がElmをキャッチアップできる状態でない場合には、Elmを選択することはいまのところないだろうなと思っている。Vue.jsやVuexであれば、コミュニティの大きさから後任の開発者が確保できる可能性が充分にあるからだ。

 Elmの堅牢な型システムやある意味 "ズル" できないアーキテクチャは、必ず大規模なアプリケーションに必要なものであることには間違いないが、そもそも書ける人間がいない状態になってしまっては元も子もない。とはいえ、JavaScriptを触っている人間であれば、文法がパッと見で目新しいものあるだけで、Elmにはすぐに馴染めると信じている。そのような意味で、自分の発表を聞いてElmの存在だけでも知ってくれる人が増えてくれたとしたら非常にありがたい。

2019年現時点でのElmベストプラクティス6選

先日業務で1からElmアプリケーションを作りきったのでそのときの学びをメモっておく。

1. Model / Msg / View のような分割をしない

  • Rails などのフレームワークからきた人がやりがち。
  • Elm でファイル分割をするのはモジュール単位でのカプセル化をするときだけでよい。
  • なので基本的に1画面につき1モジュールとして、その中に Model / Msg / View / Update などを書いていく。
  • ここからさらにデータ構造として抽出できるものがあれば後述の Opaque Type として切り出す。

2. コンポーネント指向と混同しない

  • Elm は React や Vue.js のようなコンポーネント指向フレームワークではない。
  • 基本的に1画面につき1モジュールとして作る。
  • 再利用したい画面のパーツは関数として作ればよい。

3. Opaque Type の活用

  • Elmにはクラスはないが、モジュールシステムを使うことで公開する型、関数などを制限したカプセル化ができる。典型的なものは以下のふたつ。

3.1. 値オブジェクト

アプリケーションのドメインの固有な型を作ることで仕様をカプセル化する

module Bookmark.Title exposing (Title, new)

type Title =
    Title String

new : String -> Title
new value =
    Title value

ただ String をカプセル化しているだけにも見えるが、このように型を定義することで String をアプリケーション固有のドメインとして特化させることができる。

これには以下の利点がある

  • バリデーションなどのロジックをこのモジュールに実装することで責務分割がしやすくなる。
  • 関数のシグネチャから利用意図が分かりやすくなる
    • String -> String -> StringよりもTitle -> Description -> Bookmarkのほうが、コードに与えられた意味が理解しやすい。

3.2. コレクションオブジェクト

これが意外と使いドコロが多い。集合を型として表現したカプセル化

例えば以下のような Bookmark 型があるとする

-- Bookmark

module Bookmark exposing (Bookmark, isInvalid)

type Bookmark
    = Valid Title Description
    | Invalid
 
 
isValid : Bookmark -> Bool
isValid bookmark =
    case bookmark of
        Valid _ _ ->
            True
      
        Invalid ->
            False

その上で Bookmark のコレクションを扱う Bookmarks 型を定義する

-- Bookmarks
-- 上で定義したBookmarkの集合を表現した型

module Bookmarks exposing (Bookmarks, new, size)

import Bookmark exposing (Bookmark)


type Bookmarks =
    Bookmarks (List Bookmark)


new : List Bookmark -> Bookmarks
new bookmarks =
    Bookmarks bookmarks
  
  
size : Bookmarks -> Int
size bookmarks =
    bookmarks |> List.filter Bookmark.isValid |> List.length 

このコレクションオブジェクトのいいところは利用者側がコレクションの仕様を詳しく知らずに使えること

  • Bookmarks のコレクションが何で実装されているか (List, Set, etc...) は利用者側は意識しなくてよい
  • Bookmark のサイズがどのような基準で計算されるかは利用者側は意識しなくてよい

言い換えれば bookmark のコレクションにまつわるロジックの変更はすべてこのモジュールに閉じたものになる。

4. Record をインターフェースとして使う

Record はデータ構造に別名をつけただけのもの (type alias だし)

0.19からはタプルが2値しかとることができなくなったぶん Record が3つ以上の値をもつタブルの代替になった感がある。

Extensible Record を使った依存の切り離し

Record を部分的に満たすインターフェース (Extensible Record) を使うことによって特定のデータ構造への依存を分離できる

たとえば以下のコードは toSessionが Model に依存している

type alias Model = 
    { session : Session
    , currentUser : User
    , bookmarks : Bookmarks
    }
  
  
toSession : Model -> Session
toSession { session } =
    session

これはよくある例で、Model はデータが多くなればなるほど多くの関数が依存するようになりがちだ

実際には toSession 関数は session だけが存在するレコードが受け取れればいいので、以下のように Sessionable として定義した Extensible Record に依存させ Model の依存を取り除ける。

type alias Sessionable a =
    { a | session : Session }
  

toSession : Sessionable a -> Session
toSession { session } =
    session

この分離の利点は以下

  • テストする際に Model を丸ごとモックする必要がない
  • 依存の方向を統一できる (DIP)

特に Elm は循環参照をコンパイラが許さないので、アプリケーションが大規模になればなるほど Extensible Record の利用シーンは増える。

5. データ構造的な DRY よりも状態網羅性を大事にする

定義上の重複を減らそうとするのではなく、状態の網羅性の観点から適切かを考える

type Page
    = SignIn
    | Bookmarks
    | NewBookmark
    | Loading

type alias Model =
    { session : Session
    , currentUser : Maybe User
    , bookmarks : Maybe Bookmarks
    , currentPage : Page 
    }

上記の Model の欠点は以下の2点

  • Maybe の意図が不明確
    • bookmarkscurrentUser が Nothing なケースが定義から分からない
  • ありえない状態がとれる
    • currentPage が SignIn なのに Bookmarks が存在している、など

これを踏まえた上で、上記よりも以下のような Model がより望ましい

type Model
    = SignIn
    | Loading Session
    | Bookmarks User Session Bookmarks
    | NewBookmark User Session Bookmarks

この定義を見ると、SessionBookmarks を共通化したい気持ちがでてくるが、状態の網羅性が壊れるくらいであれば共通化はしないほうがいい。共通化するよりも堅牢さを大事にする。

6. Parcelを使うと最速で環境構築できる

いまのところこれが最速だと思う。

qiita.com

基礎からわかる Elm

基礎からわかる Elm

  • 作者:鳥居 陽介
  • 出版社/メーカー: シーアンドアール研究所
  • 発売日: 2019/02/27
  • メディア: 単行本(ソフトカバー)

Immutable.jsを使うメリット

 先日、新卒で入ったエンジニアが 「Immutable.jsの研修課題をやってるんですけど、正直なんで必要なのか分かんないっす」 と言っていた。

 たしかに React, Redux と Immutable.js をセットでつかおうみたいなノリの記事はネットでよく見るが、じゃあなんでそのセットなの?という点に関してはあまり詳しく書かれていないことのが多い気がしたので、個人的にその理由っぽいのを雑に書き残しておこうと思う。

イミュータビリティのいいとこ

  • コーディング・バグを減らす
    • 言語仕様上ミュータブルな JavaScript は、大勢で開発してるとこっそりどこかで参照を持ったオブジェクトを書き換えてた、なんてことになりやすい。なのでデータを更新する際にはイミュータブルであることが保証できるとバグが起こりにくいコードを書ける
  • メモリ効率がいい
    • イミュータブルなオブジェクトは中身が同じなのでコピーが参照のみになり、実行時のメモリ効率がよくなる
    • 参照がコピーされるだけなので、例えばコレクションの比較も実質 O(1) になるので速い
  • 地味にWikipediaイミュータブルのページが充実した内容で参考になる

ReactとRedux

  • 仕様的に React+Redux 自体がイミュータビリティを期待したものになっている
  • React が Unidirectional なデータの流れ方をする
    • コンポーネントの中で明示的に setState が呼ばれて初めてビューの更新が予約される。
    • この更新はミュータブルなステートの部分更新などではなく、新しいステートを丸ごと与える。
  • Redux が関数型アプローチ
    • React 界のFlux実装のデファクトスタンダードこと Redux はステートの変更を純粋関数で行う
    • 変更を行う Reducer が React のステート更新と同様に既存のステートから新しいステートを返す(イミュータブル)
  • この辺の前提に加えて、ES6だけで更新処理周りのコードを書いていると、スプレッド演算子Object.assign まみれになるところが、Immutable.jsでスマートに書けたりする。
    • 最近のバージョンでは TypeScript と組み合わせたトランスパイル時のチェックもそこそこいい感じになってきている

他の一部フレームワークとの相性

  • Vue.js で Vuex に載せるデータを Immutable.js のコレクションにしたら微妙だった
    • そもそも Vuex 自体がステートをミュータブルで持つので、どこがミュータブルでどこがイミュータブルなのかを気をつけないと意図しない挙動が起きることがあった
    • そもそも Vue.js では Object.defineProperty と呼ばれる更新検知の機構を使って効率的にオブジェクトの更新を検知しているので、逆に Immutable.js を使わないほうがパフォーマンス的にもよくなる気がするし、むしろ使うべきじゃなかったと思っている。
  • Boost the Performance of an AngularJS Application Using Immutable Data · Minko Gechev's blog
    • ちょっと古いが Immutable.js を AngularJS と使った人の記事
    • AngularJS は Digest Loop の中で scope オブジェクト間の差分チェックをして、もし差分があればそれをビューに適用していく仕組みになっている。これがコレクションになると O(n) になるが、 Immutable.js を使うとコレクション比較が実質 O(1) なのでパフォーマンスが向上する。
    • この作者は immutable というディレクティブを自作したらしいが、 AngularJS 組み込みの filter ディレクティブなどとの相性が悪いらしく率直に言って使いづらそうだ。
  • Immutable.js は JS のプレーン・オブジェクトへ変換する処理のオーバーヘッドがそこそこデカいので、ユースケース上ここがボトルネックになってくるとどのフレームワークと組み合わせていてもイミュータビリティが破綻し始める感がある。
    • Wantedly People のフロントエンドを作ってる人がこのつらみをどこかで書いていた気がする
  • JavaScriptにおけるコレクション(というか配列)操作についての計算量はここに書いた izumisy.work

まとめ

  • React と Redux 自体がそもそもイミュータビリティとの相性がいいフレームワークになっているという印象。他のフレームワークだと場合によっては微妙。 React+Redux でやるなら Immutable.js は入れておいて損がないよ、と言われる理由はだいたいこんなもんかな。
  • 余談だが Redux に影響を与えたと言われる Elm は全ての関数が最初からイミュータブル。もはや言語レベルでこうなっているのは結構嬉しかったりする(チームでコンセンサスを得る必要がなかったりするから)
  • 最近では Immer という Immutable.js オルタナティブが出たらしい。パット見ではコレクション系のクラスっぽいものがなくAPIが非常にシンプルという印象。こっちも要チェックっぽい。
  • おそらくイミュータブルの概念を理解するにあたってはガベージコレクションなどのメモリに関する知識と、データに対する計算量などのアルゴリズム的な知識のふたつが必要になるのではないかと思う。アルゴリズムについて学ぶにあたっては、やはり「アルゴリズムとデータ構造」が一番おすすめであると言える。

「完璧につくらない」という能力

 自分の欠点として、まず「完璧につくろうとしてしまう」というものがあることが分かってきた。

www.wantedly.com

2度現地で参加したリモートハッカソンでは、SAPに勤める若いエンジニア、バークレーで勉強をしている学生とそれぞれペアを組んで開発をしたが、彼らのコードはさほど自分が期待していたような洗練されたものでなかったように思えた。

 自分は、アメリカでハッカソンに参加したときに現地のエンジニアとコードを一緒に書く機会があった。

 そのときの自分は、彼らのコードを見て「ふーん、こんなもんか」と思っていのたが、今思い返してみると、それ自体が彼らの強みだったのではないかと思う。美しい設計や、実装の抽象化を突き詰める前に、まず動くものをつくる。コードはあとからリファクタリングすればよい。そのときの自分は、コードを書くという行為の目的を履き違えていた。

 つまり、コーディングには2種類の能力がある。まずは、品質に敢えて目を向けずに動くものを最速で作る能力。次に、いくら品質が悪いものでも、リファクタリングできる能力。スタートアップやベンチャーでコードを書くには、このふたつが求められるのでないかと思い始めた。

社会人エンジニアに求められたもの

 去年の4月から社会人としてエンジニアをやっている。

 いつのまにやらもう1年が経とうとしているが、自分が仕事としてコードを書くエンジニアになって、これまでにどんなことを学んできたのか? ということを文章として書き残していなかった。タイミング的に「新卒」というラベルが剥がれそうな時期であるので、ここに書き残してくこととする。

 が、なかなか自分自身の成長を文章で書くのはなんとももどかしいものがある。自分は人を褒めることを躊躇したくないし、自分自身を「謙遜」*1と称して蔑みたくないという気持ちがあるが、それでも実際はなんとも言えない感情との板挟みになる。ということで、折衷して自分自身を客観的に「社会人エンジニア」のひとりとして捉えて、彼に何が求められてきたのか、というのを文章にしてみることとした。

言語やフレームワークにこだわらずプロダクト開発ができる

 例えば、新しく会社でプロダクトを作る、となった際に、技術要件として自分がこれまで触ったことのない言語やフレームワークが非常に有用であるということが分かるのであれば、その時点で自分がその言語/フレームワークを触ったことがなかったり、得意ではなかったとしても、そのタイミングで即座に業務で使える程度の技術をすぐに身に付ける柔軟性が期待される。

 もちろん、人には向き不向きがあり、それを個人差として捉えることもできる。けれども、業務でコードを書くというのは最終的にはビジネスを実現するための手段としての位置づけであるということは間違いない。ビジネスというのは、大抵の場合市場競争に巻き込まれるものであるし、そこへ個人差が常に加味されるかと言われると、難しいものがある。

 とは言うものの、ある程度コードを書いた経験があれば、少しづつ横展開できる基礎知識はついてくるものなのではないかと思う。自分は社会人になって初めてScalaとElmを業務で書き始めたが、全く持って手も足もでないということはなかった。なんでもかんでも「まずやってみる」というのが大事だ。

チーム開発を想定できる

 弊社が非常に設計を大事にする社風である、ということはいつぞやの記事でも書いた。設計を大事にする、という点が意味するのは、開発におけるスケーラビリティを大事にしているということだ。この「開発がスケーラブルである」という言葉が表現したいものは、チームがいくら大きくなっても、全体のアーキテクチャが破綻することのないようルールづくりができているということ。

 学生の頃はチームで開発をするなどということは一ミリも考えたことがなかった。それは、10社以上のインターンを経ても変わらなかった。どの会社に行っても、せいぜいインターンでやるのはハッカソン的な開発か、中/長期でもちょっとしたバグフィクス程度のものだった。結局、そのようなタスクをするだけに終始しているようでは、チームで効率よく開発をしていける仕組みづくりや、運用に乗せる際にどういうことを考慮するべきか、のような「業務」としてのものづくりを体験することはできないし、ちょっとコードを書くだけのアルバイトでしかない。

 一方で(ここからはポジショントークになるが)弊社のインターンは学生にもチームの存在前提で設計をさせる。これは夏季の短期インターンでもそうだ。もちろん時間は全く持って足りていないし、思考の負荷も高い。けれども、チームで大きなアプリケーションを作るともなれば、予め負荷の前借りを設計の段階でしておかなければ、あっという間に雪だるま式に負債が溜まり込んでしまう。負債をゼロにし続けることは無理だが、それでも設計指針をきっちりと練っていくことで、負債が溜まるスピードを遅くすることはできる。

大規模トラフィックを想定できる

 これは非常に抽象的な話であるが、例えば自分は社会人になって初めてPub/Subやタスクキューの使い所を学んだ。

 CSVファイルをアップロードして一万人のユーザーを管理画面から登録させる、といった要件があるとしたら、学生のころの自分は全てリクエスト・ハンドラの中でまるごと処理しようとしていたのではないかなと思う。このようなことをしてしまうのは「もしこの機能が〇〇万人に使われるようになったら、どこがボトルネックになるのかな?」というような思考が働いていないからだ。

 このタイプの思考を巡らせるためには、スケールするもの/しないものの知識がまず前提にあり(たとえばCPUバウンドな処理はスケールさせることができるが、IOは一貫性とのバランスをとる必要がある、など)その上で、RDBMSやNoSQLのような道具に関する知識との掛け算が必要になる。もちろん、学生でもGCPAWSなどのツールを大規模のデータと共に運用していれば、勘所は抑えられるのではないかと思う。けれども、自分は全くと言っていいほど経験も、知識もなかった。

特定の言語・フレームワークにロックインされない設計の思想と知識がある

 コードを書くということは、インターネットに転がっているQiitaの記事を読んだり、リファレンスを読んだりすれば、すぐにできることであるが「どのようなコードを書くか」という方向性がなければ、いきあたりばったりで意図の読めないコードを量産するだけになってしまう。

 大事なことは、大局的な方向性として「変化に強いアプリケーションを作る」*2のを前提にすることだ。まさにこれは言語・フレームワークがなんであろうと関係がない。この前提を踏まえた上で初めて「じゃあ今回はクリーン・アーキテクチャでいきましょう」というような決定を下すことができる。逆に言えば、いくら流行っているからと言ってクリーン・アーキテクチャを採用しても、それが方向性にそぐわなければ、単に編集するファイル数が多くて面倒くさいアーキテクチャを採用しただけじゃないですか、という判断になりかねない。

 実際には設計のみならず、実装にも同様のことが言える。たとえば、Scalaのコンパニオン・オブジェクトを使ったコンストラクタ隠蔽やElmのOpaque Type、Golangのパッケージシステムを使ったプライベート化などは、どれも責務分離を表現するカプセル化の実装知識だが、逆に言うとカプセル化がどのようなケースで重要なのか、ということを理解するためには大局的な設計の思想が必要になる。

 言語やフレームワークが変わっても、我々が「変化に強いアプリケーション」を作る必要がある、という前提はこれから変わっていく可能性があるとは言いづらい。その前提を実現するために、様々な「設計」の思想を理解し、知識として持っておくことは言語・フレームワークに落とし込んだ個々の実装表現とは切り離されているという点で独立して重要だと言える。

izumisy-tech.hatenablog.com

*1:謙遜されないと不愉快になる、という人がいるが、このような謙遜を強いる人間というのは相手に自分自身の自己肯定感の低さを押し付けているだけだ。自信を持って悪いことなど何もない。

*2:ビジネスというのは常に同じ形であり続けない。市場が変わればアプリケーションの仕様も変わるし、仮に仕様が変わらなかったとしても、そのアプリケーションを支えるツールが変わる可能性は大いにある。変化に耐えられない組織が市場を制することができないという事実は、多くの有名な日系企業のこれまでの歴史が証明している。