口が悪いエンジニア論争
通勤の暇にかこつけて今話題の「口は悪いが凄腕の技術者を雇うべきか」論争に対する自分の考えを残しておく。
まず大前提として「技術力も人間力もある」のがベストというのは揺るぎのないものであり、僕もここを目指したいと常々考えている。
その上でだけど、僕は「そうすることが必要な場面では口の悪さに目を瞑って技術力を取る」選択もありだと考える。
みんなこれには一家言あるようだけど、結局のところ全員前提としている状況が違うので意見が異なるのは当然のことだ。ただ僕が言いたいのは「ある種の問題はそれを解決することがそもそもできない絶対的な壁がある」ということだ。
本件に関して様々なツイートを拝見したが「そもそも技術力は育てられるが人間性は中々変えられない」という意見には、後半こそ賛同するものの前半には両手をあげて賛同できない。ある種の課題、プログラマのコンテキストで言えばいわゆるNP困難な問題は中庸なプログラマを100人並べても対処できない。ゼロだ。
なんでもいいんだけど例えば事業の課題としてGoogle Mapを超える最強の地図アプリを作ろうとするじゃない。そしたら最短経路とか求めないといけないけど、これそういう教育を受けてない人には無理じゃないですか。
ダイクストラ法ぐらいならググれば出てくるけどダイクストラ法はコストが負のノードがひとつでもあったら成り立たない。じゃあそれの改良版のコレコレを使いましょうとかね。
こういうのって数ヶ月から数年の教育と訓練と実務で身につける類のもので、人間性の優れた素人プログラマを10人集めても倒せない。こういうとき、酒癖も女癖も最悪だけど一騎当千の呂布みたいな武将に力を借りざるを得ないのは仕方ないと思う。
なのでまとめとしては最初に書いたとおり、場合によっては口の悪さぐらいでは引き換えにならないぐらい技術力には壁があるんじゃないかしらということだ。それからこれが1番言いたいことなんだけど、みんな人間性の優れた呂布になろうな。僕も頑張る。
近況と2018年の抱負
ご挨拶
新年明けましておめでとうございます。
このブログは普段のAndroid開発の気付きとかを他ならぬ未来の自分(最近つとに忘れっぽい)のために書き残していたのであるが、人生について書いたエントリが随分バズってしまったのでやっていきブログと思われているかもしれない。なのでこの辺で意図的に本来予定していたゆるさに戻していく。
元同僚の定期的なブログ更新の良さについて - 滞舎路日記というエントリに賛同する部分が多かったので僕もとりあえずネタがなくても何か書いていこうと思う。
渡米準備
ビザの書類には数え切れないほど用意するものがあってもちろん会社や代行業者がサポートしてくれるんだけどそれでもめっちゃ大変(語彙の喪失)
あとは引っ越しの準備とか手放すものの整理とか郵便の転送とかそれから仕事の引き継ぎとか英会話とか娘の保育園の手続きとかDroidKaigiのスライドとか毎日目も回らんばかりだ。
子育て
僕はフルタイムお父さんであってパートタイムプログラマである。とにかく子供たちと毎日精いっぱい生きている。やはりプログラマの端くれなので新しいことに挑戦する時間が取れなくなると切なさを感じないではないが、これまでは夜9時に寝て朝4時に起きるなどして何とかしてきた。ところが次女が昨夏生まれて以来ふたたび夜泣き対応を経験しており「あ〜、あったな〜こんな時代」としみじみしている。まあそんでも子供がお父ちゃ〜んと背中にまとわりついてくれるのなぞせいぜい満4-5歳ぐらいと考えたら最後の一滴まで味わいつくしたい。
ベンチャーキャピタルさんと新規事業
2018年は米国のラボで新規事業やらなんやらをやる。弊社がLP出資しているVCがあってその縁で彼らがこちらの新規事業のアドバイスを定期的にしてくれているようだ。で、こないだ初めてこのVCとこちらのMTGに参加させてもらったんだけどこれは詳しくは書けないけどまあひどい内容で、思わず間に入って最初から最後までずっと通訳*1と狂言回しをするハメになった。この先のことを考えると暗澹たる気分になったが、その後VCのメンバーとの会食で「君は一番印象に残ったよ。これからもよろしく頼む」と褒めてもらってそれは自信になった。これは正直僕が頑張らないとどうにもならんという感想だし、まあ結局のところだからこそ僕が送り込まれるのだと腹をくくった。とにかく結果を出したい。
ともかく楽しくなりそうではある。2018年もよろしくお願いいたします。
僕は僕にどういう教育を授けたか
まえがき
会社の若い子に「情報系出身でもないのに一体どうやって勉強してきたんですか?」と聞かれたのでランチを食べながら「こんな本読んだ。これもタメになった。あ、これもタメになった」とKindleを広げながらリストアップした。思い返せばたくさん本を読んだ。その中には役に立ったものもあれば時間の無駄だったものもある。すると「あ、役に立った本だけ抽出したら有益かもしれないな」と思ったのでエントリにする。
僕は文章を簡潔に分かりやすくまとめる才能が致命的にないのでこのエントリもげっそりするほど長い*1が、2017年も暮れなのでここはひとつ日本酒でもかっ喰らいながら自分の人生を振り返ってみようと思う。
無理やり要点をまとめるならば、
を身につけたらどんなに低く見積もっても僕と同程度のプログラマをつくるレシピには充分だと思う。具体的な書籍名も挙げてあるので誰かの人生に勇気を与えられたらいいな。
僕について
あー超言いたくないので今まで隠してたんですが僕は英文学部出身*3なんですよ。チョムスキーとか読んでました。割と自由な学科だったので英文学と英語学に飽きてからは通訳の授業を取ったりしていた。
数学は1A2Bまでしかやっていない。生物と化学はちょっとだけ覚えている。物理はまともにやった記憶すらない。コンピュータサイエンスの教育は1秒も受けていない。
ピアノと耳コピが趣味でMIDIにハマったのがきっかけでそれを発表するためのサイトを始めた。そのうち第三者の作品投稿を募るようになってPerlでCGIを書き始めた。どこかで買ってきた本*4を見ながら無料公開された掲示板CGIを元にコピペと改造を繰り返してサグラダファミリアを建築していた。
3年次に大学を中退。前述のプログラミングもどきをきっかけに知り合った大学の先輩が起業したのでその会社で働き始めた。
インフラ
会社での僕の業務は雑用全般だったのでクビになることを恐れて誰もやり手がいなかったLinuxサーバ管理をし始めた。当然すべて物理サーバ。当時使っていたのはRedHat 9。そして出たばかりのFedora Coreに乗り換えてyumコマンドで依存ライブラリも含めて一発でインストールできることに感動したのを覚えている。ここではいくつか重要な知識を身につけた。
- サブネットマスクの概念*5
- TCP/IPの知識とルーティング
- Linuxのコマンド群
- Linuxのプロセス、ジョブ、init、ランレベル、パーミッション、ユーザ管理
- iptablesでファイアウォール
- ウェルノウンポートを利用する代表的なサーバ群の基本的な使い方
- シェルスクリプト
- Xen/KVMを使った仮想化
この業務に5年間たずさわったが、ほぼ次の本を読めば同等の知識を獲得できる。
右も左もわからない人がざっとインターネットプロトコルスイートについて雰囲気を知るのに良い。
ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識
- 作者: 戸根勤,日経NETWORK
- 出版社/メーカー: 日経BP社
- 発売日: 2007/04/12
- メディア: 単行本(ソフトカバー)
- 購入: 31人 クリック: 372回
- この商品を含むブログ (99件) を見る
ルーティングの基礎がちゃんとわかる。
- 作者: 竹下隆史,村山公保,荒井透,苅田幸雄
- 出版社/メーカー: オーム社
- 発売日: 2012/02/25
- メディア: 単行本(ソフトカバー)
- 購入: 4人 クリック: 34回
- この商品を含むブログ (37件) を見る
マスタリングTCP/IPを入門編でも読めればTCPダンプも怖くない。
CentOS7で作るネットワークサーバ構築ガイド (Network server construction gu)
- 作者: サーバ構築研究会
- 出版社/メーカー: 秀和システム
- 発売日: 2015/03/25
- メディア: 単行本
- この商品を含むブログ (3件) を見る
ここだけ、この本を手放しに推奨するということじゃなくて「自分の使ってるLinuxディストリビューションでApache/Nginx, Postfix, Bind, Samba等々を『全部入りで』解説されてる本」で自分にあうものを1冊探して欲しい。僕は現在はもっぱらDebianばかり使っておりRedHat系を推奨するという意図はない。
プログラマ転身
インフラのかたわらで会社のサーバサイド開発を手伝うようになってちょっとずつプログラマとしての経験値を貯めていった。僕のおすすめのアプローチは「何かひとつ『これさえあればとりあえず安心して何か書ける』ようになるまでひとつの言語を集中して頑張ること」だ。僕の場合はそれはJavaだった。
Java、なぜか今日では古くさくてイケてない言語の代名詞みたいに若い人に思われてそうだけど2017年現在ですら充分有力な選択肢ですぞ〜。
- C++やRustを除くと最速の部類の実行性能を誇る
- JVMはGCのチューニングや運用実績も豊富
- コアライブラリの代表的なデータ構造*6は種類も豊富だし実装も参考になる
- ジェネリクス
- 強力なスレッドサポートとconcurrentパッケージ
- 昔でいうとAWTやSwing、いまならJavaFXとかでスタンドアロンGUIアプリケーションも書ける
- AndroidはJavaライクな言語で開発できる
- 巷に開発者が多く、枯れた知見や強い静的型付けのおかげでチーム開発にも向いている
- 別にやりたきゃFat Jarにして配布したりスクリプト処理だってできる
ちょっと最後は無理やりか!ほとんどのプログラミング言語は本質的にやろうと思えばなんだってできるね。
とにかく僕の場合はJavaだったわけだ。ジェネリックプログラミングやマルチスレッド処理、GUI開発の知見なんかは僕の現時点での最大の武器であるAndroid開発にも非常に役立った。
いまからJavaを身につけるのは何がいいんだろうな…とりあえず
Javaメモ目次(Hishidama's Java Memo)
の2つには大変お世話になった。Javaは「とりあえず使い始める」という点でちょっと分量が多いように感じられて*7初学者はウッ…となるかもしれないので何でも良いので本屋さんで簡単なのを買ってみるというのも手です。
これを手放しに推奨というわけではないけど何も知らない人は一旦ざっと俯瞰できる本を何か買ってください。始めた頃の僕みたいな実力だったらもっと入門的なものでも良いかもしれない。
EFFECTIVE JAVA 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: 丸善出版
- 発売日: 2014/03/11
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (11件) を見る
これはJava書きのバイブル。Java 8, 9時代の内容を反映した3rd Editionも原著(英語)はすでに予約を開始してる。
新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)
- 作者: Martin Fowler,児玉公信,友野晶夫,平澤章,梅澤真史
- 出版社/メーカー: オーム社
- 発売日: 2014/07/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (11件) を見る
僕はリファクタリングをチーム開発、使いやすいAPI設計、テストを書きやすい構造等々のすべての高品質なプログラミングの基礎だと考えており、この本は一歩前に進むために必読であった。Javaが題材なので手に取りやすい。
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
- 作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/06/23
- メディア: 単行本(ソフトカバー)
- 購入: 68人 クリック: 1,802回
- この商品を含むブログ (138件) を見る
言語に依らずシンプルで分かりやすいコードを書くためのテクニックが簡潔にまとまっている。新入社員には必ず薦めている。
Java並行処理プログラミング ―その「基盤」と「最新API」を究める―
- 作者: Brian Goetz,Joshua Bloch,Doug Lea
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/11/22
- メディア: 単行本
- 購入: 30人 クリック: 442回
- この商品を含むブログ (174件) を見る
これ絶版なのが惜しくて惜しくてしょうがない。Javaが持つ強力なマルチスレッドプログラミングをjava.util.concurrentパッケージを使って安全に使うためのテクニックがすべて詰まっている。また「スレッドセーフとは何なのか」という観点から、単純にロックを安全に取る方法のみならずトラバースを安全に行うことに特化したアプローチなども学ぶことができる。
無職、そして東京へ
さて5年経って会社もIPOを目指すスタートアップからただの中小企業と化してしまったし僕も自分の人生に行き詰まりを感じて最初のスタートアップを退職した。*8
僕はちょっとだけ無職をしつつ自分が次になにをすべきか考えていたが、ふと「そういや大学3年まで取った単位もったいねえな。どっかに入り直すとして1回生からやり直すカネはないし引き継げたりせんかな」と思って中退した大学の教務課に行ったところ「確かに中退してるけど、キミ、5年以内なら無試験で復学できるね。ああ、来月末で5年だね。」と言われ、そのあまりのタイミングの良さに運命を感じて大学に戻ることにした。この時は手に職があったので知人経由で割のいいプログラミングのバイトを貰って働きつつ1年で卒業した。*9
この間に後に嫁さんになる女性とコミケで出会った。向こうは同人誌を作る側、こちらは同人誌を買う側である*10。奇しくも冬コミ初日の今日これを書いているのは感慨深いな。大学卒業後よめさんを追いかけて東京で職を探した。
ネイティブアプリ開発
ウェブの会社に拾ってもらってここで技術者としての基礎を全て叩き直された。京都時代にちょっと触ってたAndroid開発を本格的にやるようになった。ネイティブアプリ開発にはいくつかコツがあることを知った。
スレッド間通信
ネイティブアプリ開発のコツというとライフサイクルコールバックとか非同期処理とか貧弱なネットワークやハードウェアリソースなんかが挙げられると思うけど、最も大切かつ既存のほとんどすべてのGUIフレームワークに共通する仕組みがある。それがイベントループとメッセージパッシング機構でありこれらは取りも直さずスレッド間のメッセージのやり取りために存在している。
イベントループ
あるスレッドに関連付けられイベントやメッセージを待ち受けてる人。AndroidではLooperがこれに相当する。MessageQueueというその名の通り届いたメッセージをキューに積んで処理したりする。
メッセージ
スレッド間でやり取りされるメッセージ。AndroidではMessageというそのままの名前。
ハンドラ
イベントループにメッセージを届けたり処理を記述するための仕組み。AndroidではHandlerというこれまたそのままの名前のクラスがある。
なんでこれらの知識が必要かというと、こういった仕組みはGUIフレームワークに普遍的な考え方であり何かトラブルが起こった時の調査の取っ掛かりになるばかりか、まったく新しいGUI開発に従事した際にも充分に応用が効くようになるからだ。ここに挙げたものはiOSにもまったく同じものがあるしJava Swingにもあったし未来に生まれる次世代のスマホOSでも同じものが提供されるであろうことが想像に難くない。
ここまで分かるようになってくると、UIスレッドというのがそういう名前が付いただけのシングルスレッドであることも分かるし、反対にメッセージループの機構が単に別スレッドからUI部品を更新するためだけのものではなく任意のスレッド間の柔軟なメッセージングに使えることが分かる。
ちょっと脱線したけどAndroid開発の参考書籍をいくつか。
いきなり書籍じゃないけど「Androidの入門書なにがいいか?」って一番困る質問なんだよね…すでに僕はAndroid入門者じゃないので当時の気持ちが思い出せない…
ただこのトレーニングコースは無料で簡潔かつ本質的であり、今なお色褪せぬAndroid開発の極意をごく短期間で身につけることができる。
どうしてもIDEのインストールから手取り足取りやりたいひとはAmazonで適当に検索して評判の良さそうなものをなんでも1冊手にとって見ればいいと思います。
黒帯エンジニアが教えるプロの技術 Android開発の教科書(ヤフー黒帯シリーズ)
- 作者: 筒井俊祐,里山南人,松田承一,笹城戸裕記,毛受崇洋
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2016/06/18
- メディア: 単行本
- この商品を含むブログを見る
ヤフー黒帯本。Androidに限らずiOSもそうだと思うが公式の方法と現場で使われているデファクトスタンダードの乖離が初学者の挫折ポイントだったりすると思うので、最近の知見をサッと1冊で詰め込めるのはおいしい。
Androidを支える技術〈I〉──60fpsを達成するモダンなGUIシステム (WEB+DB PRESS plus)
- 作者: 有野和真
- 出版社/メーカー: 技術評論社
- 発売日: 2017/02/22
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
Androidの内部に切り込んだ世界でもこれ以上の書籍はないと思われる名著。I巻はGUIにフォーカスを置いている。前述のHandlerのような話題もはるかに深く掘り下げられている。
Androidを支える技術〈II〉──真のマルチタスクに挑んだモバイルOSの心臓部 (WEB+DB PRESS plus)
- 作者: 有野和真
- 出版社/メーカー: 技術評論社
- 発売日: 2017/03/24
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
II巻はActivity(iOSのViewControllerに相当)に関する内容。普段何気なく利用しているActivityが誰によってどのように生成/破棄されているのかと言ったライフサイクルの心臓部の解説がある。
Androidを支える技術の別冊「詳説 Binder」。すいませんこれ怒られるかもしれないけどまだ読んでなくて正月休みに読む予定なんだけど、AndroidにはBinderというプロセス間通信の仕組みがあって普通にIDEの参照ジャンプで辿っていくだけだとこのBinderの層でプッツリと途絶えてその先を見つけられないのだ。
ここを読むにはAndroidのなかみ InsideAndroidという書籍*11の解説とかを見ると助けになるんだけど、著者の有野さんも
あっちの解説よりは大分良いつもりです!(ステマ
— karino2@貴族階級 (@karino2012) 2017年12月26日
と仰っているしdex.fmでご本人が熱弁しておられた様子をお聞きしても名著であることを確信したのでここで紹介した。
アルゴリズムとデータ構造
たぶんここまで来るだけでモバイルアプリ開発者としてなんとなく食っていくには充分だと思うんだけど外資に転職したくて勉強したアルゴリズムとデータ構造について理解を深めるにつれ「これは順番が逆だった!これを知ってからプログラミングをやるべきだった」という思いに強く駆られたので紹介しないといけない。
アルゴリズム
アルゴリズムはある問題を解くためのアプローチだ。数列を昇順に並べ替えるアルゴリズム、木構造から目的のデータを素早く探すためのアルゴリズム等がある。
データ構造
アルゴリズムを実装する際に効率的に処理するためにデータの集まりを都合の良い状態に整えたもの。整列済みの配列は立派なデータ構造だし、平衡二分木もB+木も赤黒木もデータ構造である。
で、普段こんなの使わんでしょ?と思いきや全然そんなことなくて、自分で実装することはほとんどないかも知れないけど普段のプラグラミングやサービス開発でよく使うものでこれらアルゴリズムとデータ構造の恩恵を受けていないものは存在しないほど身近で重要なものだったりする。
普段使ってるRDBMSやファイルシステムはB+木のお陰で挿入も削除も検索も高速だし、全文検索エンジンはトライ木の一種のサフィックス木で実装されてるかもしれない。
身近なプログラミングでダントツに重要なデータ構造としてHashMap(Dictionary)があると思うけど、普段これがどうやって実装されてるか*12考えたことがあるだろうか?
このあと紹介する参考書籍とかを読めば分かるけど、HashMapはキーのハッシュ値をモジュロ演算して固定長配列*13に割り当てて、ハッシュ値の衝突は連結リストの後ろにつなげていくだけで実現されている。それぞれは非常にシンプルなデータ構造とシンプルなアルゴリズムを工夫してこのようなベンリなデータ構造を作ってるわけである*14。
またAndroidにはキーが任意の型Tではなくint固定の代わりにメモリ効率が良いとされているSparseArrayというデータ構造があるが、これは内部では2分探索木が使われている。つまりエントリが爆発的に増えればおそらく挿入時にはSparseArrayの方が有利だし検索時にはHashMapの方が有利であることを示唆している*15。
こういう知識はいざ自分で新しい何かを生み出せばならないときに強力な持ち駒として力を発揮するはずだ。
新・明解 Javaで学ぶアルゴリズムとデータ構造 (明解シリーズ)
- 作者: 柴田望洋
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2017/05/17
- メディア: 単行本
- この商品を含むブログを見る
この本は何個か読んだ中でも比較的とっつきやすかった。使い慣れたJavaだし。
この本はアルゴリズム本の中で特別読みやすかった。図もたっぷりで軽妙な語り口。それでいて動的計画法のナップザック問題あたりまでもカバーする骨太さ。言語はPythonだが読めないということはまずないだろう。
- 作者: George T. Heineman,Gary Pollice,Stanley Selkow,黒川利明,黒川洋
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/12/24
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る
僕が読んだ中で最も広範かつ深くアルゴリズムについて学べる本。いきなり「アルゴリズムの数学」と題して計算量とは、最良・最悪・平均性能とは何なのかみっちりと解説してくれる。その後他のアルゴリズム本にもあるような整列、探索、グラフに始まりAI、ネットワークフローの深きまでがっつり入っていく。これをマスターすれば怖いものなし。僕はマスターしていない!
最強最速アルゴリズマー養成講座 プログラミングコンテストTopCoder攻略ガイド
- 作者: 高橋直大
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2013/08/14
- メディア: Kindle版
- この商品を含むブログを見る
AtCoder代表のchokudaiさんによるTopCoderのSRMに挑むための訓練本。やや難易度が高いけど実際のプログラミングコンテストに挑むための力をつけることができる。外資企業の面接で間違いなく力を発揮する。
UNIX/Linux力
個人のPCレベルだとWindowsがまだ世界で90%ものシェア*16を持っててまさに圧倒的という言う他ないんだけど、ことサーバ環境においては7割近くがUNIX系OS*17という調査もあるようで元インフラ出身の僕の肌感覚とも近い。それにiOSはDarwinというUNIXだしAndroidはLinuxをベースにしていることを考えるとUNIX/Linux力は非常に重要だと思う。
ここでUNIX/Linux力といった場合単純にコマンドを扱えるよりもうちょっと踏み込んだ点を指していて、具体的には次のようなことだ。
で、これらは普通にコマンドを利用してるぐらいでは中々身につけるのは難しくて、やっぱりglibc越しにシステムコールを呼ぶようなプログラムを書かないといけない。
かつて一回だけ本番環境のMySQLが原因不明のタイミング*18でネイティブクラッシュを繰り返して生きた心地がしなかったんだけどstraceコマンドでシステムコールトレースをつぶさに追ったところRDSのホスト名が長すぎて名前解決キャッシュのテーブルの最大バイト長を超えて書き込もうとしてセグメンテーション違反を起こしていたのを突き止めたことがある*19。
- 作者: W. Richard Stevens,Stephen A. Rago
- 出版社/メーカー: 翔泳社
- 発売日: 2014/06/05
- メディア: Kindle版
- この商品を含むブログ (7件) を見る
上に挙げたようなことをすべて身につけることができる本。900ページぐらいあってめっちゃムズイけどCを書いてコンパイルしてっていうのは実は生まれて初めてだったので楽しかった。全部やるのは無理だった。
ふつうのLinuxプログラミング 第2版 Linuxの仕組みから学べるgccプログラミングの王道
- 作者: 青木峰郎
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2017/09/22
- メディア: 単行本
- この商品を含むブログを見る
詳解UNIXプログラミングのLinux版かつテーマをグッとしぼった感じの本。初学者はこちらの方がずっとオススメ。grep等のよくあるコマンドを自分で実装してみることができる。
教養
直接なにか利益を受けるつもりで学んだものではないんだけど回り回って血となり肉となった知識がいくつかあって、その中のひとつが関数型プログラミングだ。
特にHaskellでモナドを学んで将来確定する計算結果をパイプライン処理するというような考え方はAndroid開発時にRxJavaを見た時にすんなり理解できる助けになってくれたりして大いに役立った。また昔は特に苦手だった再帰も、スタックフレームを消費する末尾呼び出しとアキュムレータを用いた最適化可能な末尾再帰を使い分けることができるようになったりと得るものが多かった。再帰的な考え方は再帰的なデータ構造やアルゴリズムを考える時に脳の体操になるので非常に役立つ。
- 作者: Miran Lipovača,田中英行,村主崇行
- 出版社/メーカー: オーム社
- 発売日: 2012/05/23
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 580回
- この商品を含むブログ (73件) を見る
たぶんHaskellの入門書で圧倒的に一番分かりやすい。Haskellの機能をシュールな絵とともにのらりくらりと解説してくれるんだけど、Functor, Apprecative, Monoidとステップを踏んで最終的にMonadを作るところまで学ぶことができる。
Scala関数型デザイン&プログラミング ―Scalazコントリビューターによる関数型徹底ガイド (impress top gear)
- 作者: Paul Chiusano,Rúnar Bjarnason,株式会社クイープ
- 出版社/メーカー: インプレス
- 発売日: 2015/03/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (7件) を見る
ScalaをBetter JavaというよりはかなりHaskellっぽく使うための様々なアプローチが紹介されている。随所に練習問題があって難しいが素晴らしい本。
- 作者: M.D. ConradBarski,Conrad Barski,川合史朗
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/02/23
- メディア: 大型本
- 購入: 1人 クリック: 18回
- この商品を含むブログ (19件) を見る
スポンジボブのようなシュールな絵でLispの歴史の解説に始まり最終的にCommon Lispを使ってちょっとしたゲームまで作ってしまう面白い本。S式という連結リストと関数だけというかなり割り切った言語設計とカッコだらけの見た目でかなりぎょっとするが、再帰を使って連結リストに関数適用していくという関数型プログラミングの醍醐味のようなものを学ぶことができる。
フロントエンド開発
むしろ僕が教えていただきたい…僕のフロントエンドの知識はjQueryとprototype.jsで停まっている化石状態だ。
ただ来春の僕のミッションに素早いプロトタイピングが加わるのでReact Nativeでクライアントサイドを、Cloud Functionsでバックエンドを書いていこうかなと思っているので双方に共通する技術スタックとしてTypeScriptを速習予定だ。
(後日修正)
速習ECMAScript6: 次世代の標準JavaScriptを今すぐマスター! 速習シリーズ
- 作者: 山田祥寛
- 出版社/メーカー: WINGSプロジェクト
- 発売日: 2015/08/28
- メディア: Kindle版
- この商品を含むブログを見る
速習TypeScript: altJSのデファクトスタンダートを素早く学ぶ! 速習シリーズ
- 作者: 山田祥寛
- 出版社/メーカー: WINGSプロジェクト
- 発売日: 2017/06/21
- メディア: Kindle版
- この商品を含むブログを見る
この2冊が時間的にも金銭的にも最もコスパが良かった。
数学
数学の出来なさがかなり僕のコンプレックスになっており自分なりに少しずつ努力している。僕はビッグオー記法のO(logN)の意味が最初わからなくて指数対数からやり直したレベルだ…こちらは完全に教養として本当に少しずつ進めているので進展があったら共有したい。
このエントリで拝見した高専の数学は良さそうである。
やっていき
いや〜長すぎてもう誰も読んでないと思うので最後にちょっと好きなことを書きます。
自分がこれだけ路傍の石ころみたいな状態からプログラマになってこうしてなんとか食ってこれたのは、やっぱり諦めなかったからだと思う。僕は常にいまの自分が許せなかった。いまの自分の不甲斐なさが悔しかったのだ。これは裏を返せば自分の可能性を信じているわけだ。まだやれるはず、まだ道は続いているはずだと信じている。
ちゃんと教育を受けた人が大学で4年、修士で2年、博士で3年だとしてざっと10年。僕はこのような専門教育は受けていないがかれこれ12年自分で自分にコンピュータサイエンスを教え続けてきた。努力を積み重ねれば彼らに追いつくのも不可能とは限らないのだ。毎日は1㍉1㍉の積み重ねだが12年経って振り返った時に「気付かないうちに随分登ったなあ」と小高い丘から目を細めながら過去の自分を見下ろせればそれで良い。
22歳からでも、いや30歳からでも遅すぎるということはないのだ。自分が今日より若い日は今後一生ないのだと思うと何歳からはじめても今日が最善の日だ。やっていこう!
- 作者: Chad Fowler,でびあんぐる
- 出版社/メーカー: オーム社
- 発売日: 2010/02/26
- メディア: 単行本(ソフトカバー)
- 購入: 24人 クリック: 683回
- この商品を含むブログ (126件) を見る
技術書以外はめったに読まないんだけどとても好きな本。オフショアでの衝撃的な経験や生きるためにコードを書くということ、採用に対する考え方、エンジニアとしての幸せなど示唆に富んだ本。
最後に
2017年は本当にお世話になりました。来年はちょっと今まで目を背けつづけてきた機械学習にチャレンジせねばと思っています。どうか良いお年を。
*1:マジで長くて1万字を超えちゃって笑ってしまった
*2:身も蓋もないけどコレはホント。しかし運は待つのではなく無理やりつかみ取りに行くのです。
*3:だから英語に苦手意識がないんですね〜。けどこの時の英語力はハナクソみたいなもんだったのでその後のトレーニングの方が大事。
*4:これはもはや記憶にない。何でも良かったのだ。
*6:List, Set, Hash, Dequeなんでもいいんだけど、Arrayを元にしたものやLinkedな実装など用途に応じて自在に使い分けできる。僕はアルゴリズムとデータ構造を学んでからJavaのコアライブラリの凄さを見直した。
*7:リテラルも弱いし配列やコレクションもRubyやPythonとかより使いにくくてとっつきづらいよね…
*8:僕を引っ張ってくれた恩人の先輩もそれからほどなく共同創業者に株式を売り払って東京に出ていった
*9:思えばこのとき2年かかってもいいから理学部情報学科にでも編入試験を受ければよかったな〜。でも学士を取れてよかった。
*10:「ここここのあとののの飲みにいきませんか」みたいなことを言った。通報も逮捕もされなくてよかった。
*11:こっちは読んだ!
*12:もっというとどうやってO(1)の検索を実現しているか
*13:ホントは然るべきタイミングでリサイズしないといけない。卜部先生のブログに詳しい。
*14:これを理解するとどうしてMapが挿入順序を持たないか簡単に分かるだろう
*15:ただし一般的なアプリで現実的なデータ量では2分探索木でもO(1)に近い性能が出ると思われる。参考サイト
*16:https://news.mynavi.jp/article/20170904-a057/
*17:https://w3techs.com/technologies/overview/operating_system/all
*19:これは --skip-name-resolve オプションを付けていればそもそも起きなかったミスではあるが…
現職のままシリコンバレーに赴任する
電撃的な展開により会社からシリコンバレーのラボへの異動を命じられた。現職のまま任期付き(恐らく2年)の赴任となる。
オフィスはパロアルトだが家賃が高く到底住めないのでサンマテオとかその辺りに安アパートを借りることになると思う。何ひとつ分からないのでどうかご指導賜りたい。
それから東京の家を完全に引き払う予定なのでドジョウの里親を探している。もし助けてやっても良いという方は本エントリの一番最後までスクロールしていただければ幸いである。
(14時23分追記:里親見つかりました。本当にありがとうございました。)
経緯
12月も半ばになろうという頃、突然すごいエライ人に呼び出されてパロアルト赴任に興味はないか訊かれた。ちょうど失意のどん底だったので「行きたいです!」と答えた。翌週経営会議で承認されてそのまま内示となった。スピード感!
葛藤
ただここからウジウジとナメクジのように悩むことになる。
ラボといっても技術者の赴任は弊社初とのことだ。当然プログラマは僕しかいない。業務内容は
- 新規事業の発掘およびそれに関わる技術調査、助言
- プロトタイピング
- 現地企業との共同研究、連携
等と聞いている。プログラミングをしている時間はざっと50%以下になるそうだ。必要な英語力や交渉力もプログラマとして求められるそれとは別次元のものになる。
2017年は僕にとっては確変状態みたいな年で信じがたいほど多くのチャンスがあった。
モバイルアプリバブルの最末期。34歳。恐らくキャリアの絶頂。2年後同じような好条件で引き合いのある可能性の方が低いのだ。そんな状況で内資企業の、プログラミングを主としない業務に2年間を費やして良いのだろうか?
ビッグボス
赴任先で二人三脚でやっていく予定のボスが一時帰国したので面談した。次のような失礼千万な問いを率直に投げかけた。
「僕は元々アメリカに行きたかったので2年後任期が切れたときにそのまま別の会社に転職しちゃって帰ってこないかも知れないです。そんな男をわざわざ行かせますか?」
「うーんそんじゃあさ、新規事業がうまくいきすぎて現地にジョイントベンチャーでも設立してそこの社長になって帰れないぐらいのところを目標にしない?君だって2年間ずっと受け身で言われたことだけをやって終わるつもりはないだろう?」
このひと言に震えるほど感動した。必ずこの2年間で会社に利益をもたらすのだと誓った。僕は身勝手な人間だったと反省した。プログラムを書くとか書かないとかではなく、どこに居て何をしようが自分の向き合い方次第で僕自身もきっと成長することができる。
キャリア感
2017年は30代前半最後の年であり自分のキャリアについて深く考えさせられた。僕はスタートがどん底*1だったのでこの10年とにかく這い上がるだけだった。
ようやく「これがプログラミングの世界か」とその入口に立った頃、こりゃ大学からちゃんとビジョンを持って然るべき教育を受けてきた連中と今から素手で殴り合うのは得策じゃないかも知れんとちょっと考え始めた。別に自分のプログラマとしてのキャリアを諦めた訳ではなくステータス振り分けの問題で、要するに三国志で許チョを知力に振るのは無駄な努力ってもんなので、僕はもうわずかにしか残っていないパラメータを僕を最も輝かせる方向に賭けるしかないのである。
そのひとつとしてビジネスデベロップメント力をこの2年で養うのはきっと悪くない選択だと信じたい。どの道止まっている時間はない。いのち短し歩けよ中年!
これ名言だと思う pic.twitter.com/HVVPdyJfPC
— まちゃまー (@masaki01192001) 2017年10月18日
ドジョウの里親を募集しています
東京の家を引き払う予定で色々調べたが米国まで生体を持ち込むのが法的にもロジスティクス的にも著しく困難であることが分かったのでドジョウの引き取り手を探しています。内訳は次の通りです。
- マドジョウ * 2
- シマドジョウ * 1
- ミナミヌマエビ * 3
- ヒメタニシ * 3
- ヒメダカ * 6
水槽、LEDライト、外掛けフィルター、水交換ポンプ、バケツ、予備の川砂、予備の餌等あります。
引き取りはこれらまとめて1セットです。引き取って育ててくださる方は @fushiroyama までDMください。DMはフォロー関係になくとも送受信できるよう解放しています。東京23区内は僕が車で直接お届けできます。もし直接引き取り*2に来てくださった方には技術書が2冊買える程度のAmazonギフト券を寸志として贈らせてください。
(14時23分追記:里親見つかりました。本当にありがとうございました。)
アメリカ就職に失敗したはなし
前口上
アメリカで就職できなかった。華々しい成功譚は見かけるが、夢と散った話はあまり表に出てこない。
なんというか「三振したバッターが相手ピッチャーのことを語る」みたいでまるっきり時間の無駄かもしれないが、もしかしたら参考になる人もいるかも知れないし、実際に就職した人に「お前のアプローチはまったく的外れだ」と言われるかも知れない。僕も何が悪かったのか教えてもらいたい気持ちもあるし、迷ったがこのエントリを公開する。
ちなみにめっっっっちゃ長いので、要点だけ知りたい人は、アメリカで就職するにはとにかく
就労ビザ>技術力>学歴>>>>>>>>>>>>(越えられない壁)>英語力
だというのだけお伝えできればと思う。
アメリカで働くために英語を頑張るぐらいなら、それより大学(院)に入り直してコンピュータサイエンスの学位をとり*1、同時に技術力を磨くほうがよほど近道だと感じた。
それから、現職の同僚はこのエントリをみて微妙な気持ちになると思うので、その点について最後に「現職について」で補足する。
秋風五丈原
じいちゃんが死んだ。大正・昭和・平成の3つの時代を生き、たくさんのひ孫に囲まれて90年超の幸せな人生を脱稿した。しかしそれでもなおこのことは僕にはショックだった。「あー人生ってマジで1回なんだ。知ってたけど知らなかったわー」という感じ。
漠然とした概念としての死が、自分の人生が必ず最後に到達する終着駅だとやっと実感をもって気付いた。
ここで僕は、やりたいことはとにかく何でも試してやりきってから死のうと決めた。そのとき思いついたのが「アメリカでソフトウェア技術者として通用するか試したい」ということだった。僕にはそれに至るちゃんとしたロジックとかはなくて、とにかく自分の目で見て自分の足でアメリカの大地を踏みしめ、自分の鼻でSFの雑踏のマリファナまみれの風を吸い込み、自分の手でソフトウェア技術者としての痕跡を残したかった。
ちょうどその頃堤修一さんのフリーランスを休業して就職しますというエントリを発見したり、身近な何人かのプログラマが渡米したりして僕もあのようになりたいとトランペット少年のように思った。早速Creators Learning English Meetupというイベントに帰国中の堤さんが登壇されるということで、突撃して彼を捕まえて質問攻めにした。
それから具体的な就職活動について考えた。
就職活動
どうしていいかさっぱりわからなかった。どこに応募したらいいのか分からない。
とりあえずこの時はアホだったので、さる世界的な多国籍企業の東京支社にソフトウェア技術者として応募した。なんか、そのうち転籍でもできるんじゃとか思ったのである。いま振り返ると筋が悪すぎる。
ちなみに割と早い段階で早々に落とされた。ただこの経験はしておいてよかったなと後に思う。ここの面接でアメリカ企業というのは基本的にコンピュータサイエンスの基礎力を応募者に強く求めるということがわかったからだ。
それからもしばらくは具体的なアクションが起こせず、うーんどうしたらいいんだ?とかつまらないことを考えていたんだけど、事件が起きる。ある日LinkedInに海外企業のリクルーターから「当社のSenior Android Engineer職に興味はないか?」と直接コンタクトが来たのである。
この会社は事前に課題として、実際にその会社のフラッグシップアプリで問題が起こりやすい部分をスマートに解決するための簡易な実装を提出するように求めてきた。僕は自分が優秀であるとアピールするために、組み込みライブラリを組み合わせればまあサラッとできそうなものをわざわざ自前でドバーッと書いて提出したところ、採用担当者はこれを痛く気に入ってめでたく本面接に進むことができた。
面接はすべてSkypeやGoogle Hangoutsを使ってリモートから英語でなされた。この時も英語なんてカタコトかつ単語の羅列で何の問題もなくて、とにかくコーディングにつぐコーディングだった。ある人は整列や探索の簡単なアルゴリズム*2の実装を求めてきたし、HashMapがどう実装されているかかなり踏み込んだ説明*3を求めてきたりしたし、あるいはわざと罠を仕込まれた作りかけのAndroidアプリを共有されて、画面共有ツールで僕がどうやって正しい実装にたどり着くか監視されたりした。
この会社は2人ぐらい突破したんだけど、その後急にリクルーターが代わって
「ところでビザのステータスは?」
「え?ステータスとは?君たちがサポートしてくれると思ってた」
「うーん残念だけどいまはUSの就労ビザはサポートできないんだ」
と言われてなんとそこですべてのプロセスが終わってしまった。
このときもしかしてビザとはとんでもなく重要な要素なのでは…?と初めて気付いた。
ビザ
それからアメリカの就労ビザについて色々調べた。僕がお世話になる可能性のあるビザは次の3つ*4だ。
- H1B(専門職ビザ)
- L1(駐在員ビザ)
- E2(投資家、またはそれを補佐する専門職ビザ)
H1B
専門職ビザの花形である。米国の企業が発行する。
米国はITの聖地であり、技術者は全然足りていないんだそうで「その足らない技術者を海外の人材で賄うため」というお題目でGoogleとかMicrosoftみたいな世界に冠たるIT企業はH1Bをバンバンサポートしてくれるらしい。
就労する業務に深く関連のある学士以上の学位を持っている必要がある。望むらくは修士以上。博士は優遇される。
L1
日本企業の社員が駐在員として米国支社に転籍するような場合に発行してもらえるビザ。その会社に1年以上在籍している必要がある。
日系企業がアメリカ支社に社員を送り込む際の最も一般的な方法のひとつ。
E2
日本の起業家が自分自身に投資してアメリカで起業したり、それを補佐する専門職者に対して発行される可能性があるビザ。L1と違って最低在籍期間のようなものがなく、すぐに発行することが可能。
他にもトレーニングビザというものがあるらしいが、詳しいことは僕は知らない。
また、Diversity Programといって、アメリカが移民の多様性を推進するために移民の申請が少ない国の人を対象に申込者の中から純粋なるくじ引きを行って当選者には永住権の申請権を与えるという面白いプログラムがある。こちらはまさに運任せなのと当選率が低い*5ので参考程度に。
転機、そして内定
さて、その頃たまたまGoogle I/OでSFに行ったときにDeploy NIKUというイベントでお会いしたDrivemodeのCEOの古賀洋吉さんにどうやったらアメリカでソフトウェア技術者として採用されて就労ビザを発行してもらえるか相談したら、
「片っ端から応募しまくりました?してない?どうして?LinkedInとかで募集している会社に『初年度は給料はこのぐらいで我慢してやるから就労ビザだしてくれ』って100社ぐらいにメール送ったら5社ぐらい返事くれるんじゃないですか?」
と言われた。なるほど、ぼくは全然行動力が足りていなかったのだ。
それからちょっと気が楽になって、少しずつ友人のツテとかを頼ってアメリカの会社に応募するようになった。具体的には
- 僕がアメリカで働くことに興味があること
- 出向ではなくアメリカ企業からの直接雇用を望んでいること
- そのためにたとえば即時解雇のリスクがあることや試験内容が現地基準で難しくなっても問題ないこと
- その代わり待遇は現地基準にして欲しいこと
を伝えた。
また、同時にLinkedInのプロフィールを英語で充実させて、自分が経験豊富なプログラマであり転職の意志があることを明示した。具体的には
- 自分が経験のある言語、フレームワークを年数込みで列挙
- 転職に興味があること
- これらを英語で詳述
した。これはもっとも効果のある施策だった。
LinkedInは転職斡旋リクルーターからのコンタクトばかりくるが、1割ぐらい企業のHRが直に連絡を取ってくれる。リクルーターが「弊社に興味がないか?」と聞いてくるのは「試験を受けないか?」と言ってるだけなのでそれ自体に特に意味はないのだが、僕のように関連学位をもたない人間は書類審査でバンバン落とされるので、少なくとも相手企業のHRが連絡を取ってくれた場合は電話面接を受けることができる。そうすれば実力次第で次のステップにすすむ希望が生まれる。
実際に数ヶ月でヨーロッパのスタートアップから数社、アメリカのスタートアップから数社、国際的な多国籍企業からもいくつかInterviewのお誘いを受けた。ひとまずは友人のツテとこの中から興味のある3社ぐらいに絞って面接を受けた。
面接は相変わらずコンピュータサイエンスの基礎知識とアルゴリズムクイズが中心で、対策のしがいがあった。少なくとも、
- アルゴリズムクイックリファレンス等の本で「整列」「探索」「グラフ」あたりのアルゴリズムとデータ構造を理解しておく
- TopCoderのSRM Div2ぐらいのレベルのコーディングテストはスラスラ解けるようになっておく
- UNIX/Linuxの理解。権限、ユーザ管理、プロセス、スレッド、入出力、システムコールなど。詳解UNIXプログラミングとかふつうのLinuxプログラミングとかはおすすめ。
のような準備が有効だった。
そしてついに、行きたい会社から内定がもらえた。オファーレターを見てその金額や福利厚生に興奮したし、「いかなるときも当社都合で解雇できるものとする」というような内容に戦慄したりした。
挫折
内定はゴールではなかった。ビザがおりないのである。
ビザの手続きは先方の弁護士に任せていたのだが、H1Bが簡単にいかなそうで他に色々利用できる可能性はないか探っているようだった。これはたぶん本当で、向こうも採用という莫大なコストをかけて内定を出した候補者はどうにかして入社までこぎつかせたいようだった。
これは推測にしかすぎないが、自分の学位が足を引っ張ったのではないかと想像する。僕はコンピュータサイエンスの学位を持っていない。数学や物理学といった関連学位も持っていない。
アメリカは日本以上の学歴社会である。学歴がひとつの「免許」として機能している。「おれ無免許だけど車の運転うまいっす」とかいう奴を誰も相手にしないのと同じだ。これはとても健全なことだ。大学というのがきちんと社会の求める役割を果たしているのだ。H1Bが業務に関連する学位を必須条件として定めていることは非常に合理的だが僕にとっては悪いニュースだ。
もしかしたらトランプ政権もタイミングが悪かったのかもしれない。トランプ政権下では移民ビザをとにかく制限する方向に動いている。H1Bもアメリカ人の雇用を守るためにかなり厳しくなるという話だ。
先方の人事とやりとりしつつ半年待ったが「率直に言って、来年4月のビザは絶望的だ」という話を受けて、こちらから正式にお断りの連絡を入れた。こちらは4歳と0歳の子供がおり、僕の身の振り如何で保育園も妻の復職もすべてが左右される。いつまでも宙ぶらりんで居るわけにはいかなかった。無念だ。人生はままならぬ。
こうして僕のアメリカ就職は一旦頓挫することになった。
振り返り
とにかく就労ビザがどれだけ大切か思い知らされた。どれだけ面接でうまくやってもビザがなくては何も始まらないということがよくわかった。
学歴もかなり大切で、僕が安易に「自分が行けそうなところで偏差値が高い大学をなんとなく選ぶ。学部はどこでもいい」というようないい加減な高校生活を送ってしまったことを非常に強く後悔した。
突出した技術力や実績があればこれらは挽回のチャンスがあるが、僕のような凡人が凡人なりに就職するには大学の勉強とそこから必然的に導かれる就職先というストーリーは非常に大切だった。
家族のこともありしばらくはこういったアクションは起こさないが、もうあと5歳でも若ければコンピュータサイエンスの大学院を受けていたかもなーという感じ。
現職について
ここまで書いて、現職を辞めるわけでもないのによくもまあいけしゃあしゃあとこんなエントリを書けるなと呆れる向きもあるかも知れない。これには少しフォローを入れたい。
まず、僕は現職を非常に気に入っているし採ってもらったことを深く感謝している。優れたボスと同僚に恵まれ、プロジェクトはいつも創造意欲を掻き立てられるし、みんなメリハリをつけて働いていて余程のことがない限り残業もない。待遇も日本にいる限りにおいては申し分ない。
それとは別で「会社と従業員は対等だ」という僕のキャリア感がある。
僕は僕にしかなしえない技術力を提供し、会社はそれの対価として報酬を払う。僕は常にプライドを持って問題を解決し、素早くアプリをつくり、会社に貢献してきたつもりだ。そしてその度合というのは「勤続年数」で測られるものではないと思っている。
会社が僕に居て欲しいと思い、僕が会社に居たいと思う。両者の利害が一致して契約が持続される。これがシンプルで良いのではないか。
祖父の死でカッとなって色々足掻いてみたが、結局僕は現職に残ることを選んだ。そして会社はまだ僕に力を貸して欲しいと言ってくれる。もう少しお世話になります。
*1:金銭に余裕があるならアメリカの大学(院)を出るとインターンシップ等で利用できる就労ビザが取得できるようだ
*2:NDAにサインしたので詳しい内容は書けないが、ソートのアルゴリズムを直接実装せよというようなものはなかった。ただ、O(n log n)の代表的な探索アルゴリズムついて基本的なアイディアを問われたことはある。
*3:Arrayとキーのハッシュ値を用いた基本的なアイディアや、コリジョンの解決方法の複数のアプローチ等
*4:これ、僕はど素人なので微妙に間違ってたりするかも知れないし、詳しくは自分で調べるか弁護士に相談して欲しい。
*5:応募総数と当選者から割り出した当選率はたしか公式サイトに公開されていて、それによると0.8%ぐらいだが、実際には当たったひと全員が永住権を申請するわけではないのでもう少し多めに当選を出しているとの噂
エンジニアの英語力
TL; DR
- どれだけ努力しても"ネイティブ並"は無理なので諦めが肝心
- エンジニアは英語ができなくても話を聞いてもらえるので「伝える意思」と「分かったか分かってないかを絶対に曖昧にしない」こと
謝辞
このエントリは弊Android Projectのビルド待ち時間を使って書かれています。Android Studioさんに感謝します。
ビルド待ち時間にブログを書かれたくない場合は弊社は僕に全部盛りiMacを買ってください。
前口上
英語力に関するエントリは盛り上がりやすく荒れやすい気がするんだけど、それはやっぱりみんな英語は出来たほうがいいに決まってるしさりとて英語を身につけるのは難しいよねってことが分かってるからだと思う。
僕はエンジニアの中では比較的英語が得意な部類に入ると思うけど、それでも全然充分だとは思わない。ただ、これでやっていけないか?というと全然そんなことはないので、一番重要なのはエンジニアには何が期待されているのかというのを改めて認識しなおすことで、手持ちの英語力でも幸せに生きていこうではないかということが言いたい。
僕について
僕はもう10年以上プログラマをしている。職種はソフトウェアエンジニアである。
旅行を除いて1週間以上海外にいたことがなく、外資系企業での勤務歴もない。
英語力はTOEIC最高点が890。ここはサバを読んでTOEIC900マンとしてくれ、頼む。英検も準1級を持っている。
ここまで書いて「英語強者だ。解散!」とか「出た、ただの自虐風自慢」というのは簡単だけど、このエントリには僕がTOEIC900に至るまでの道のりと、実はそれは不要であることの両方を記した。良かったら読み進めて欲しい。
エンジニアの英語力について
まず、一番最初にエンジニアに必要な英語力について書いておきたい。
エンジニアにとって英語力はあるに越したことはないが、なくても別に死なない、ソフトクリームのあのカラフルなつぶつぶチョコレートぐらいのもんだということだ。
で、最初に言い切ってしまうと、エンジニアはエンジニアリングができるというただ一点においてすでに価値があるので、エンジニアが英語ができなくても相手は辛抱強くコミュニケーションを取ってくれるという事実だ。
弊社にはイギリス人、アメリカ人、ニュージーランド人といった英語を母国語とする同僚が多数いるが
- エンジニア同士の場合、コードは英語より雄弁なコミュニケーション手段となる
- 相手が非エンジニアの場合も、作るのはこっちなので無碍にはしてこない
ことが分かっている。
従って僕はエンジニアは
- 英語の一次情報(ライブラリやRFC等)をいかなる手段を用いても構わないので読めること
- 相手とどうしても英語を話す必要があるときはいかなる手段を用いても構わないのでゴールについて合意できること
が達成できればなんだって構わないと考える。
いかなる手段を用いても構わないので、前者はGoogle翻訳を使えばいいし、後者は同僚に通訳を頼んでもいい。僕はふざけてなどいない。エンジニアとのコミュニケーションミスで本来とは違うものを作ってしまう損失は通訳のそれよりゼロ2桁ぐらい大きい。
肝心なのは、君にコミュニケーションの意思があることと、いま訊かれており合意しなければならないことが分かったかどうか確実にすることだ。
相手が日本人ですら「ちょっとそこ仕様がフワフワしててわかんないっす」とか確認するじゃないですか。相手が違う言語を話してたら尚更だ。「よくわかんないけどウンって言ってきた」って、文字で書くとアホなの?と思うけど実際には多くの人がやっちゃう。
「わかんなかった」
「あ、そこはわかった、後半わかんない」
「こういう理解でいい?」
ってしつこく確認すること。これは英語力の問題ではなくコミュニケーション意思の問題だ。そしてそれが何より大事だと思う。
僕は海外企業で働いたことがないけど、実は海外企業に内定をもらった*1ことがあって、その時の面接で「英語で困る」なんてことはまったくなかった。
もちろん流暢にはしゃべれるわけないんだけど、別に単語の羅列でも相手が求めているアルゴリズムをホワイトボードにスラスラ書けることの方が肝心だ。
僕は周りのものすごいエンジニアたちが英語ができないという思い込みで海外に挑戦しない例を見てきて「なんてラッキーなんだ!エンジニアの価値はエンジニアリング力にあるのに、そんなことで諦めてくれるなんて!ライバルが減った!」ぐらいに思っている。
このエントリで書いちゃったけど、このエントリを読んで海外企業受けたよありがとうと言ってもらえる方がもっと嬉しいかな。
どうやって実践的な英語力を身につけるか
とはいえ英語は出来たほうが有利だ。ここでは僕がいかにしてTOEIC900の英語力を身に着けたか紹介する。
僕のアプローチはただひとつ。「理解できる英語をひたすら繰り返す」だ。
僕はスピードラーニングの完全否定者である。英語は聞き流すだけでは絶対にできるようにならないが持論だ。想像してみてよ、なんでも良い、例えばアラビア語の音声を10年間毎日聞いたとして、アラビア語が理解できるようになると思うか?
僕が考える良い英語の教材は次の条件を備えていることだ。
- 英語母国語話者が英語で解説する
- 内容はゆっくり平易で、辞書なしで9割理解できる
- 1レッスンに2〜3個わからない単語が出てくる
英語母国語話者による英語の解説
これが非常に肝要で、英語を読み上げて日本語で解説するタイプの教材は日本語の解説を聞いた時点で満足しちゃって記憶に残らない。
英語を英語で解説することがどれだけ大事かというと、これは知らない単語を別の平易な説明で言い換えることができるということだ。これはいざ自分が直接知らない単語をどうにか相手に説明しないといけない場面で役に立つ。
内容はゆっくり平易で辞書なしで理解できる
これはある程度意味がわかった状態で「単語の字面」と「ネイティブな音」とを結びつける必要があることを意味する。実は知っている単語が、ネイティブの発音ではそれと認識できなかったという経験はしばしばすることになる。
単語と音が結びついてくると、今度は未知の単語を「聞いただけで」だいたいのつづりが想像できるようになる。あるいは、けったいなつづりでも辞書に向かって音声入力で聴いたとおりしゃべりかけるとスペルを教えてくれるようになる。
いきなりABC Newsを聞くようなトレーニングは速すぎて取りこぼしの方が多いと個人的に考える。平易でゆっくり過ぎると中級者は「ちょっとこれは簡単過ぎるのでは…」と不安になるかも知れない。
人間は9割わかると前後から内容を類推することができるのでほとんど理解できたような気になるが、逆に言うと1割分かっていないということは各レッスンで1割ずつ未知の内容を習得できるということだ。
僕のオススメはESLPodである。
サイトが分かりにくいのが難点だが、僕は15ドル/月の有料会員で、Select Englishというコースから15本好きなプログラムをDLできるので「Daily English」という、日常でよくあるシチュエーションの会話を通じて単語や表現を学ぶコースから10本、「Cultural English」という、アメリカの歴史や偉人といったアメリカの文化を学ぶコースから5本それぞれ毎月DLしてスマホに入れてウォーキングしながら聴いている。
僕はこのサービスが有料化する前からのユーザで、実に7年間このレッスンを聴いている。人間、7年間も続けたら大抵のことはできるようになるのだ。
月15本で1本20分ぐらいなので、毎日聴いていると10日ぐらいでやりきってしまう。その場合は繰り返し聞く。何度でも繰り返し聞く。そうすることで記憶が強固になる。イディオムが勝手に口をついて出るようになる。
僕がこれまでにした英語のトレーニングにはESLPodただひとつだけだ。他に何一つしていない。それだけでTOEIC900取れる。TOEICなんてTOEICの点数を上げるための対策すらしていない。そんなことは無意味だ。TOEICの点を上げることそれ自体には何の価値もない。
シャドウィングと英語思考
前述の英語リスニングに慣れてくると、今度はそれに合わせて気になる表現や単語をブツブツとシャドウィングしてみよう。聞くのと話すのはやっぱり違う。聞こえたのと同じように言えるようになるまで何回でもブツブツしゃべる。英語には日本語にない音がいくつもあるので、最初はうまく口が動かない。冗談みたいだけど口が攣ったりする。練習あるのみである。
ゆっくりしゃべってくれるのに合わせて自分でも言ってみるのを繰り返していると、対面で英語話者とスピーキングのトレーニングをしていないのに不思議としゃべれるようになる。とにかく重要なのは
- 言葉のシャワー(理解できるものじゃないとダメよ!)を浴びまくって、イディオムが脳内でスッと出てくるようになる
- 何回もシャドウィングして口が慣れてくる
これを繰り返すとしゃべるほうも結構イケるようになってくる。
僕のオススメは日常生活で「これ英語で何ていうかな」と妄想しながら生きるトレーニングだ。普段からそういうことを考えていると、いざ英語話者を前にしたときに自然な流れで言いたいことが言える。
「まずは日本語で考えてそれを英訳する」ステージから「脳内で英語で直接考える」ステージに移行できればしめたものだ。あとは少しずつ教材の難易度を上げていくだけだ。グッドラック!!!
TOEIC900について
さて、これまで散々言ってきたTOEIC900ってどのぐらいの英語力なんだろうかと思った時に、自分の例で言うと
- 英語母国語話者と知的な会話は無理
- ジョークを言い合うなんてとても不可能
- ニュースや新聞も満足に視聴できない
レベルである。
たとえば、ABC NewsやBBC NewsはPodcastで無料で視聴できるのでいますぐ聴いてみて欲しい。TOEIC900程度ではたぶん7割ぐらいしか分からない。
新聞も、例えばFinancial Timesを買ってみて欲しい。辞書なしに1コラム満足に読むことができないと思う。
TOEIC900ってこれっぽっちの英語力なのだ。英語ができるという物差しにしては短すぎる。
ニュース、新聞は日本でもそうだと思うけど、格式張った知的な単語や言い回しが頻出する。そしてその新聞やニュースの内容を議論するようなビジネスマンが、知的な単語を使ってないわけがないのである。同僚のイギリス人同士が政策について議論しているような場では、まるっきり何をしゃべっているのかチンプンカンプンだ。
同僚の英語母国語話者が久しぶりに同郷の同僚と話していて「いや〜、久しぶりに"Intellectual(=知的)"な会話をしたよ^^」って彼に言ってるのを聞いてちょっと傷ついたものだ。
ただ、ことエンジニアと仕事をする上では、彼らはちゃんと「第2外国語としての英語話者」に向けて平易な単語や表現をわざわざ選んでしゃべってくれるし、こちらが分からなくてもある程度譲歩してもらえる。これは僥倖だ。我々エンジニアは恵まれた世界線にいるのだ。
まとめ
最後にまとめると、やっぱり英語は極めようとするには難しすぎるのである程度妥協しないとキリがないということかな。
英語ってたぶんエンジニアにとって目的ではなくて手段であるはずで、目的というのはエンジニアとして幸せに仕事したいとかそういうことだと思うから、手段にこだわりすぎるあまり目的がおろそかになるのはやっぱり不幸なことだと思うので、エンジニアリングの方にフォーカスしていきましょうということです。
最後とっ散らかっちまった…
ビルドしつつちょこちょこ書いたのでつながりも悪いかもしれないけどまあいいや。じゃあの。
*1:この会社はビザがおりず、半年待ってついに諦めることになった。この悔しさとその時の経験はいつか別エントリにする。
Android 4系(API16-19)のTLS1.1, 1.2対応
TL; DR
- API16-19はデフォルトでTLS1.1, 1.2が有効になってないので適宜ONにしてやる
- TLS1.1, 12を有効にしたとて、強いCipher suitesが使えるかは別問題
知ってる人は知っている。知らない人は覚えてね。
前口上
さて、iOS 9からTLS1.2が必須になったのは記憶に新しい。このタイミングで社内のAPIサーバの設定が変わって芋づる式に対応に追われたAndroiderも少なくないはずだ。
本件、僕自身もすぐ忘れるのでAndroid 4系(API16-19)のTLS1.1, 1.2対応について改めてまとめておきたい。
Default configuration for different Android versions に書いてあることが全てなんだけど、AndroidのAPIレベルとSSL/TLSの関係は次のとおりだ。
- SSLv3…使うな
- TLSv1…API 1からサポート、API 1から有効
- TLSv1.1…API 16からサポート、API 20から有効
- TLSv1.2…API 16からサポート、API 20から有効
TLS 1.0で検索すると、各社サポートを打ち切る方針を打ち出していることが分かる。
このタイミングで最低でもサポートするAPIレベルを16を下限としたいところだ。
サーバの設定を確認
さて、TLS 1.0を切ると決めたらApacheなりNginxなりでサポートするTLSのバージョンを設定するはずだ。ここではそれについては解説しない。ここではcurlコマンドでちゃんと設定が正しくなされているか確認してみる。
MacOSデフォルトのcurlはOpenSSLが組み込まれてないので再インストールする。
% brew install --with-openssl curl
% cat<<'EOS'>>~/.zshrc
export CURL_HOME="/usr/local/opt/curl"
export PATH="$CURL_HOME/bin:$PATH"
EOS
% source ~/.zshrc
% curl --version | grep -i openssl
curl 7.57.0 (x86_64-apple-darwin16.7.0) libcurl/7.57.0 OpenSSL/1.0.2n zlib/1.2.8
これでOK。
curl -I --tlsv1.2 -s -v "https://your_server"
こんな感じで --tlsv1.1, --tlsv1.10 でそれぞれ試してみよう。
サポートしていないバージョンで
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
みたいになればOK。
Android側でどうするか
で、Android側でどうするかが関心事だと思う。
ここではOkHttpをHTTPクライアントに使った場合に絞る。
まず、SSLSocketFactoryを拡張して、TLS 1.1, 1.2を有効にする以外はほとんど処理を元のクラスにdelegateするだけのファクトリクラスを作る。
private static class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}
次に、X509TrustManagerを取得する処理をコピペする。
private X509TrustManager getTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
return trustManager;
}
あとはいつもどおり。
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS).build();
OkHttpClient okHttpClient;
try {
okHttpClient = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.sslSocketFactory(new TLSSocketFactory(), getTrustManager())
.build();
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
throw new RuntimeException(e);
}
return okHttpClient;
これでこのOkHttpClientを使ったHTTPリクエスト/レスポンスはTLS1.1, 1.2を使って行われる。
なお、Builder#sslSocketFactory に
Most applications should not call this method, and instead use the system defaults. Those classes include special optimizations that can be lost if the implementations are decorated.
と明記されているので、この部分を自前で書き換える場合はパフォーマンス上の不利に留意しつつ、 Build.VERSION.SDK_INT で条件式でくくったりする方が良さそうだ。
Cipher suites
冒頭で書いたように、TLS 1.1, 1.2に対応することと、充分に強度のあるCipher suitesを使えることは別問題である。
サーバ側で低APIレベルでは対応していないCipher suitesしか許容しない設定にした場合、本記事の内容を適用してもSSL Handshakeに(当然ながら)失敗する。
SSLSocket | Android Developers
を見て、どのCipher suitesを許容するかAPIチームと相談しつつ、最低APIレベルをどこで妥協するか決めるのが望ましそうだ。以上。
参考リンク
- https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
- https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
- https://github.com/square/okhttp/issues/2372
- https://github.com/square/okhttp/issues/1934