2016年振り返りと2017年に向けて考えている事

あけましておめでとうございます。気がつけば2016年もあっというまに過ぎ去り、2017年になりました。

新年明けたばかりで良い機会なので、2016年にどういう事をしたか、どういう事を考えていたかを振り返った上で、2017年に何をしていきたいか考えてみたいと思います。

2016年の仕事の振り返り

まずは仕事面での振り返りです。

僕は2015年4月から新卒のソフトウェアエンジニアとして働き始めたので、2016年は2年目として過ごす事になりました。

取り組む内容として「ソフトウェア開発というアプローチで『サービスを作る』」という部分は変わりません。ただ、2年間働いて積み重ねてきた事の結果として、取り組む内容や責任を持つ範囲が広がった様に思います。

2016年に取り組んでいたのは、主に「新規サービスの立ち上げ」や「小さく始まったサービスをリニューアルして本格的に始動させる」といった事で、エンジニア2人程度の小さなチームではあるものの、「チームのリーダー」として働く様になりました。

ここで「チームのリーダー」と表現したのは、サービスを開発するチームの技術的選択と人事的な評価に責任を持つのが求められる役割で、いわゆるテックリード+エンジニアリングマネージャーみたいなポジションです。初めての経験なのでどんなものかと思いつつ、最近はこの辺の話題がRebuild.fmのおかげでいろいろ盛り上がっていて参考になる情報も多かったので、手探りながらも取り組んでいました。

その他、弊社では会社の文化として「サービスの成長の為の"取り組み"にもエンジニアが責任を持つ」様にしているのですが、そこにはいつも難しさを感じています。弊社では、開発する機能や施策の決定、その効果に対してエンジニアが責任を持ち、サービスの成長を評価するための数字を目標として設定します。このあたりの取り組みは、過去に別のブログにもまとめました。目標に向けてのアプローチを自分で考える為、やりがいや責任感を強く感じる一方、より良い取り組みは無いだろうかと常に頭を悩ませる事にもなります。アイディアなども重要になって来る上に正解は無く、自由と責任はセットだなーと常に感じています。

「意思決定」という言葉はよく聞くものの、それに伴う「責任」について最近は考える様になりました。

2016年のプライベートの振り返り

プライベートを振り返ると、2016年はずっと本を読んだりコードを読んだりしていた様に思います。

僕はHajime Moritaさんという方を勝手に一方的に尊敬していて、彼のブログやツイート、Podcastでの発言をいつもありがたく読んだり聞いたりします。その中でも彼のRebuild.fm ep127に置ける「実装のアイディア(最適化のアイディア)はOSやプログラミング言語RDBみたいな昔から研究されてるソフトウェアの実装から盗める」発言を聞いて以来、コードを読むことに対するモチベーションが増しました。これが、本を読んだりコードを読んだりする事に専念していた主な理由の様に感じます。

備忘録も兼ねて、2016年に興味を持ったトピックをリンク付きでまとめて見たいと思います。(どうでも良いコメントですが、自分が読んでいた本や文章を振り返ってみたら、自分の興味の変遷が分かって面白かったです)

プログラミング言語処理系の実装

プログラミング言語処理系には昔から興味があり、言語処理系作成について記述した書籍(言語実装パターンコンパイラ―原理・技法・ツールなど)を興味ある部分だけつまみ食いしたり、特定の言語処理系について記述した書籍(Ruby under a microscopeなど)を読んだりしていました。

また、オンラインの媒体としては、48時間でSchemeを書こうLambda Calculus - Write You a Haskelを写経してみたり、8ccのcommitを最初から追いかけて写経してみたりしていました。

Parser の実装

プログラミング言語処理系の実装方法の中でも、自分の中で特に興味があったのは「Parser の実装方法」です。JSONSQL、汎用プログラミング言語などソフトウェアの至る所でParserは必要になる(情報を表現するにはその情報を表現する為のフォーマットとそのフォーマットから情報を取り出せるParserが必要になる)ものの、ほとんどの場合には既存の実装を用いて済ましてしまう為、自分で興味を持たない限り「どう実装されてるかを知る機会が無い」と感じていました。重要性の割に、自分はちゃんと仕組みを理解してないと感じたのです。

yaccの文法は昔勉強した事があったのですが、「yaccの使い方」が分かっただけで、内部で何をしてるか、あるいは他の方法が無いのかなどが気になってました。

という訳で書籍を読んだりコードを読んだりしてた訳ですが、結果として自分の中で知識が整理されて、すごく良かった様に思います。

まず、「文法」と一言で言っても、その文法のParserの作りやすさ、実行時間はその「文法」に依存します。文法が許すなら、LL(1)再帰下降Parserの様な「入力文字列長に対して線形の実行時間で処理できる」Parserを作ることができます。LL(1)再帰下降Parserはまた、1字先読みでdispatchすれば良いのでコードも読みやすく、手で書くのも簡単だったりします(JSON Parser くらいなら、自分で書く事も簡単にできます。まあ、僕の実装はmatchの判定しかしない&色々バグはあるんですが。。。)

一方、複雑な文法になると「固定長先読み再帰下降Parser」では次にmatchする文法規則は決定出来ず、matchを試して失敗したらバックトラックしてまた別の文法規則でのマッチを試して、、、といった動作が必要になります。この様にバックトラックが入ると、メモ化などをしない限り実行時間が入力文字列長に対して 指数関数的 に増大し、実装も複雑になります。その為、文法をどう設計するかはparserの実装に対して重要な意味を持ちます。

再帰下降Parserもバックトラックなどが入ると自分で一から書くのは大変になる為、parser generatorを利用したり、parser combinatorなどのライブラリを利用したりします。また、ボトムアップなparseを行う手法(LR法)もあったり、その為のparser generator(yacc など)を利用したりも出来ます。

parser generatorが何をやってるか、また自分でparserをイチから書くならどう書くか、parseが簡単な文法というのはどういったものか、parserを書く為に利用できるツールやライブラリにどういったものがあるか、といった事について自分の中で知識が整理されたので、スッキリしました。

正規表現エンジンの実装

正規表現エンジンの実装は昔から興味があったのですが、正規表現技術入門 がすごく勉強になりました。オートマトン理論ベースの実装とVMベースの実装の概念とコードがどちらも詳しく解説されていて、読むと正規表現エンジンに対する理解が深まりました。

計算理論の話

Parserや正規表現エンジンの勉強をしていたらだんだんオートマトンチューリングマシンに対してしっかりした理解をしておきたいと考える様になり、一時期計算理論の基礎を読んでいました。個人的に一番良かったのは非決定性に対する理解が深まった事だと思います。以前までNPの説明がイマイチピンと来てなかったのですが、非決定性チューリングマシンの動作やツリー状の探索パスがイメージできる様になった事で、しっくり来る様になりました。

変化に強いシステムを作る方法

仕事をする様になると「大きなコードベースに触れる機会」が増加し、コードを整理して「変化に強い状態を保つ重要性」を実感する様になりました。その為のテクニックには様々なものがありますが、特に同僚にオススメされたオブジェクト指向のこころという書籍が「デザインパターンというアプローチで変化に強いシステムを作る方法」を大変わかりやすくまとめていて、良い本だなーと思いながら読んでいました。個別のパターン以上に、「インターフェース・集約の利用、流動的要素のカプセル化」みたいな原則とその理由がまとまってるのが良かったです。

Concurrency

ムーアの法則の終焉が噂される現代において、Concurrencyの重要性は高まり続けています。しっかりと理解しておきたいと考えて、Concurrencyにも興味を持っていました。

Concurrency を実現しようと考えた時、最も一般的な方法はthreadを利用する事です。特にマルチコアを並列で動かそうと思うとカーネルthread(ここではgreen threadと違いカーネルにschedulingされるthreadという意味でこの用語を用いています。Unixであればpthreadを意味してます。)の利用が必要で、pthreadの利用方法についてインターネットサーバでのPthreadとepollPthreadsプログラミングを読んだりしていました。

また、その他のConcurrencyのプリミティブ、特に有名なのはEarlangのアクターやGoのgoroutineですが、それぞれの利用方法に加えて、どう実現されているのか、特にschedulerの実装がどうなっているかを解説した記事(How Erlang does schedulingThe Go scheduler)を読んだりもしてました。どちらもカーネルthreadをうまく利用してマルチコアを活用してくれるので、とても便利な道具だと思います。data raceやrace conditionといったthread programmingの複雑さに生身で立ち向かうのは辛いので、これらの抽象化はうまく活用したいです。

ちなみに、concurrency primitiveには他にも色々なものが存在しているらしく、Concurrent Programming for Scalable Web Architecturesの5章が良い感じにまとまっていました。通して読めてはいないですが、興味深いと思ってます。

分散システム

コアレベルでの並列化に加えて、マシンレベルでの並列化の重要性も高まっています。計算リソースの確保という意味ではHadoopやSparkが、またデータベースの地理的な分散や可用性の確保、書き込みのスケーラビリティの実現という意味ではCassandraなどがオープンソースの分散システムとして注目されていると思います。

自分はkuenishiさんのブログを読んで分散システム自体には興味を持っていたものの、具体例を知らないためにイマイチ理解できていませんでした。そこで一念発起してCassandraを読んで見たのですが、これがとても良い本でした。

まず、自分の中であやふやだった知識が明確になりました。結果一貫性、因果一貫性、強一貫性といった用語の明確な定義(読み込み時に、最新の書き込み結果を反映している事を保証するかどうかが違う)、CAP定理が意味する事、Cassandraがネットワーク分断時にどういった動作をするのか、コントロール可能な一貫性とはどういう事か、そういった事について理解を深める事ができました。それらはまた、分散システムの複雑さに Cassandra がどう立ち向かっているかについての理解でもあって、具体的な例を知れたのはとても良かったです(今後、別のシステムの説明を見たときの比較対象になるので)。

ちなみに、Cassandraは他のNoSQLや内部の細かいアルゴリズムの説明もしたりしていて、内容がとても充実していたのも魅力的でした。

その他、興味深かった本

Unix考古学という本を気まぐれで読んでいたのですが、これがかなり面白かったです。UnixC言語が生まれる時代的背景も興味深いですし、Unixベンダーが1980年代後半に争っていた話なども噂でしか知らなかったので面白かったです。

ピクサー流 創造するちからという本もかなり良かったです。これは、ピクサー、ディズニー社長のエド・キャットムルが映画制作というクリエイティブな作業を行うチームをどう作りあげてきたか、またどういう取り組みをしてきたかをまとめた本なのですが、エドが「常によく考え続けてる」ことを強く感じる本となっています。

個人的に強く印象に残ったのは、「ピクサーで作られるどんな映画も、作り始めた段階では例外なく駄作」という話です。彼らは毎回挑戦をするからこそ最初はひどい出来で、しかしそこから何度も何度も修正を加え続けるからこそ「素晴らしい映画」を作り上げられる事、それを経験からくる実感と共に語っているのが興味深かったです。映画制作の最中には「どうしようもないと行き詰まるタイミングが必ずやって来る」というのも、それを何度も経験して乗り越えてきたからこそ言える事だと思います。その為のプロセスを確立していて、プロセスやチームを信じられるというのもすごい話だと思いました。

2016年振り返りまとめと2017年の取り組み

2016年は「知りたい事、興味のある事についてちゃんと理解を深めよう」と思って過ごしていました。それはそれで学ぶことが多くて良かったのですが、一方で本を読んだりコードを読んでそのまま満足してしまうケースが多すぎた様に感じています。

2017年は、コードを書く事、特にそれをpublicにする事を強く意識していきたいと思っています。OSSへの貢献などは、興味がありつつも全く出来てない分野なので、取り組みたいと思っています。

仕事面では、取り組んでる内容に習熟することに加えて、「責任」というものとの付き合い方にも慣れていきたいと思っています。