Runner in the High

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

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 オブジェクト間の差分チェックをして、もし差分があればそれをビューに適用していく仕組みになっているので、 Immutable.js を使うとコレクション比較が実質 O(1) なのでパフォーマンスが向上するらしい。
    • この作者は immutable というディレクティブを自作したらしいが、 AngularJS 組み込みの filter ディレクティブなどとの相性が悪いらしく率直に言って使いづらそうだ。
  • Immutable.js は JS のプレーン・オブジェクトへ変換する処理のオーバーヘッドがそこそこデカいので、ユースケース上ここがボトルネックになってくるとどのフレームワークと組み合わせていてもイミュータビリティが破綻し始める感がある。
    • Wantedly People のフロントエンドを作ってる人がこのつらみをどこかで書いていた気がする

まとめ

  • 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のパッケージシステムを使ったプライベート化などは、どれも責務分離を表現するカプセル化の実装知識だが、逆に言うとカプセル化がどのようなケースで重要なのか、ということを理解するためには大局的な設計の思想が必要になる。

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

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

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

最近読んだ太平洋戦争に関する本4選

戦争、とくに太平洋戦争に関する本を読んでいる。

大学生のとき語学留学でフィリピンに行ったり、卒業旅行でグアムに行ったりしたが、やはり東南アジアの島国をめぐると様々な形で戦争の形跡を目にする。戦争を経験していない世代として、戦争とはどんなものであったか、というものに興味が湧く。

吉村昭戦艦武蔵

戦史ドキュメンタリーの大御所、吉村昭の綴る定番中の定番。 太平洋戦争を知っている人であれば戦艦大和は誰しも知っているが、その兄弟艦である戦艦武蔵知名度はさほど高いとは言えない。自分も武蔵は名前しか知らなかった。

武蔵の建造までの長い歴史と、いかにしてあの巨艦の進水を成功させたのか、そしてどのようにして最期を迎えたのかが丁寧に描かれている。

日本海軍による最後の実戦投入で、連合軍戦闘機から猛烈な攻撃を受けて撃沈される様は冗談抜きで手に汗握る描写だった。

吉村昭 「零式戦闘機」

最強の戦闘機と呼ばれたゼロ戦の、開発と活躍からその凋落までを描いたドキュメント。

自動空戦フラップや沈頭鋲、アクタン・ゼロの存在をこの本で初めて知った。

戦争はテクノロジーの進歩を促す大きな要因である、というのは例えばインターネットを見ても本当に実感するところではあるけれど、本書の中でも日本海軍がいかに戦闘機開発に心血を注いでいたかがよく分かる。もちろん毎度毎度、新しい戦闘機に求める要求は厳しくなるが、それに応えていた技術者もすごい。

初期のゼロ戦の無双具合を知った上で、後半の連合軍戦闘機によるサッチウィーブ考案以降のゼロ戦のエピソードを見るのは、なかなか心にくるものがある。

源田実 「海軍航空隊始末記」

吉村昭のドキュメンタリはどちらかといえば現場の話がメインになっているが、この本は太平洋戦争中に航空参謀を務めた源田実の目線で描かれた真珠湾攻撃から終戦までのドキュメンタリになっている。後から知ったのだが、この人がブルーインパルスを創設したらしい。

航空参謀だけあって、太平洋戦争に活躍した日本の戦闘機パイロットとのエピソードがたくさん出てくる。

中盤のミッドウェー海戦を超えたあたりから一方的な負け戦が延々と描かれはじめ、しんどい読み物になってくる。特に空母を一気に失ったあたりのやっちまった感は、読者として読んでいるだけでも痛いくらい伝わってくる。

日本人のことを「勝ち戦には人一倍強く、負け戦には案外脆い所がある」と表現しているのが、なぜか心に残っている。

戸部良一、その他 「失敗の本質」

ちょっと前に話題になった本。上の三冊とは若干毛色が違う。ドキュメンタリとは異なる客観的なアプローチで、太平洋戦争における日本軍の組織的特性から「なぜ負けたのか」を考察している。

この本で取り上げられているのは「ミッドウェー海戦」「ガダルカナル作戦」「インパール作戦」など、いわゆる太平洋戦争において激戦とされた戦いの数々で、これを読むだけで太平洋戦争の雰囲気が分かる。

まえがきで「できるだけ多くの人々に読んでもらうために読みやすさ、平易さをも心がけた」と書いているが、正直な所、そこそこ難しいところがある。何が難しいかというと、やはり地名に馴染みがないものが多かったり、そもそも日本軍の組織構造が分かっていないと難しかったりする。それでも、各章にアナリシスとして、その戦いで何が日本軍の敗けへと繋がったのかを要約するものがあるので、それを読むだけでも学びがある。

この本を読んでいると、逆に日本軍と対峙したアメリ海兵隊がいかに戦いの度に組織改善に取り組んでいたかが分かる。著者のひとりである野中郁次郎アメリ海兵隊に関する本を書いており、組織としてどのような点で勝っていたのかを研究している。

プログラミング・インポテンツ

紛れもない事実として、学生の頃よりも明らかにプライベートの時間でプログラミングをするのが億劫になった。 後輩にこのことを話すと「それってインポみたいですよね」と言われたので、これをプログラミング・インポテンツと名づける。

いまの生活に関して

朝9~11時くらいに出社して、働いて夜8~10時くらいに帰ってくる。
先週千葉に引っ越したので、より朝の時間が早くなり夜も遅くなった。

つまり、平日は仕事をして返ってきて寝るだけ。

プログラミングが嫌いになったのか?

いや、そんなことはない。

いまでも業務でコードを書いている時間というのは幸せだし、コードを書けるという能力によって組織に貢献できていると自分でも思っている。もちろん、それ以外にもちょっと英語ができるなどのはなしもあるが、それでもコードを書くというスキルが自分のアイデンティティの一部であることは間違いない。

じゃあなぜか?

おそらく、理由は以下の2つ

  • 会社で充分プログラミングしているのでもうお腹いっぱい
  • 設計が気になってサクサクとコードをかけない

会社でプログラミングをしているのでお腹いっぱい

会社では主にGolang, Scala, Elmのコードを書いているが、バグフィックスや新規機能開発である程度毎日コードを書いているので、そこそこ自分の中でのプログラミング欲のようなものは満たされている。僕は自分の中のプログラミング欲というものの上限値みたいなものを信じているので、それが満たされるとそれ以上プログラミングがしたいという気持ちが湧かなくなってくると思っている。これは食欲と同じで、一旦食事をしてお腹いっぱいになれば、それ以上何かを食べたいという気持ちにはならない、というやつだと思っている。

ところが、学生時代にプログラミングをしていたときは、朝10時に出社して夜返ってきてもまだプログラミングをしてやろうという気持ちがあった。いま思うと本当にプログラミングが好きだったんだろうなと思う反面、じゃあいまはなぜ...と思うことさえある。これが老いというものなのか。

設計が気になってサクサクとコードをかけない

自分の中ではこれが本当の理由なのではないかと思っている。弊社は非常にアプリケーションの設計/アーキテクチャを大事にする風土だ。サマー・インターンのときから徹底して柔軟なアプリケーションを生み出すための設計をやっていこうという気概に満ちていた。もちろん、自分はそんな風土に対する憧れにも似た感情を持って新卒入社をしたわけだ。ところが、設計というのは事実泥臭い作業で、コードを書く云々以前のはなしになる。よく言われるのが、開発業務は設計とコーディングで8:2くらいが丁度いい、というやつだが、これはあながち間違っていないと思う。

自分はまだ設計に関してはペーペーで、まだまだ大局的なアーキテクチャ設計から、実際のコード表現としてのデザインパターンまで満足のいく知識・経験があるとは言い難い。それだけに、きっちり設計に関して頭を使って考えていく必要がある。もちろん、これには非常に頭を使う。

一方、プライベートで書くコードなどというものは適当に流してコードを書くタイプのものであるはずだが、少しコードを書いているとすぐに「ここ、あとで拡張するときにちょっと不便そうだな...」とか「IOレイヤの責務がドメインに漏れ出してるな...どうしようかな」とか考えてはじめてしまうのだ。もちろん、設計に関して頭を使うことは悪いことではないし、そういうトレーニングをするのは間違いなく素晴らしいことだと自分でも思っている。が、プライベートでもまた頭を使うようなことをしたいかと言われると、正直微妙である。

逆に言えば、学生の頃は設計などというものを一ミリも考えていなかった。とりあえず動いて見た目がいい感じになるものが完成すれば満足だったし、レイヤの責務だとかオープン・クローズドが守られているかは全く持ってどうでもよかった。それはそれで、知らなかったという幸せだったのかもしれない。

これからに関して

そもそも、プライベートでプログラミングをする気が起きないのだからどうしようもないと思う。

世の中的には、仕事だけでプログラミングをしているやつはモグリだ、みたいな風潮がTwitterの観測上では強いようだが、実際仕事を始めてみるとそこそこ腹一杯になってくる。

秋ごろには自分でElmアプリを作ったり、Railsをちょこちょこ書いたりしていたが、ぶっちゃけなんか疲れてきてしまった。とりあえずここしばらくは不動産投資の本でも読んだり、英語のリスニングの勉強でもしてゆっくり過ごそうと思う。深刻に考えすぎるほうが良くないからね。