Web エンジニア 6 年 5 ヶ月やってたどり着いた価値観
Web エンジニアとして経験を積むことでいくつかのプログラミング言語やツール・ミドルウェアの使い方を覚えたりもしたけど、それらのうちいくつかは 10 年後ぐらいには陳腐化してしまっているかもしれない。
だけどそれらを通じて身につけた価値観や哲学はもっと普遍性を持っているような気がする。
大学を卒業し、Web エンジニアとしての職を得て 6 年 5 ヶ月、日数にして 2344 日経ったので、現時点での頭の中にあるもののダンプを残しておく。
どこかで聞いたようなことばかりで新鮮味はないと思うけど、自分で実感を持ってたどり着けたことには意味があるはず。
プログラミングについて
言語はいろいろなものを試してみる
毎年新しい言語に挑戦せよ、というのは確か dankogai さんの講演をまとめた記事で読んだはずなんだけど、記事が見つからない。
キーワードをもとに検索してみたら達人プログラマーにもそういうことが書いているらしい。 (読んだことないけど)
あとはプログラマが知るべき97のことにも学び続ける姿勢に同じようなことが書いてあった。 (これは昔読んだ)
振り返ってみると僕が社会人になって覚えた言語は PHP/Ruby/JavaScript/Golang の 4 つだけなので、毎年は覚えられていない。
一応つまみぐいしてちょっと書いてみたり、読むぐらいならなんとなくできるものでいうと C/C++/Perl/Python/Haskell/Clojure なんかもあるし今は Elixir に手を出している。
まぁこれらで何かを作ることはほぼできないし、明らかに足りてはいない。
そんな中途半端な状態だとしても、まがりなりにもやってきた価値は感じている。
Rubyist を自称する人が好んで引用する (というのは偏見かもしれないけど) サピア=ウォーフの仮説によると、言語は考え方に作用するとされていて、複数のパラダイムのプログラミング言語を体験したことのある人なら、結構納得できるんじゃないかと思う。
異なる文法を覚えることも大事だけど、それによって同じ問題に対して異なるアプローチができるようになることはもっと大事。
もちろん、アプローチが違うからこそ文法も違うのだろうけど、その点はよく意識する必要がありそう。
言語設計者の思想や、コミュニティの共通認識を理解することも大事。
最近でいうと、個人的には「なくていい抽象レイヤはない方がいい」ということを Golang に教わったと思っている。
そして、言語ごとによく使われているツールやフレームワークについてよく知ることも、問題解決や発想の幅を広げてくれる。
Python の WSGI や Ruby の Bundler を知り、それらが解決しようとしている問題を理解できれば、その知識はあらゆる言語で再利用できる。
小さくて組み合わせられるものを作る
まぁ UNIX 哲学ですね。
オブジェクト指向においては単一責任原則というものがあるし、関数型プログラミングは小さな関数を組み合わせて大きな問題を解決するスタイルが一般的。
モノリシックアーキテクチャに対するマイクロサービスアーキテクチャが持つ価値というのも、レイヤは違えどかなり似ているんだと思う。
(という話を先日 Kyobashi.go という Golang の勉強会でしてきた)
もちろん、より専用性の高い、複雑で大きなソフトウェアにだって価値はあるし、そういうものが必要なケースだっていくらでもある。
だけど日々出会う問題の多くはもっと汎用的な、grep とか awk とか sort とかでもかなりのレベルで解決できる。
専用のツールに比べて多少パフォーマンス上のオーバーヘッドがあったとしても、使い方を思い出すのに苦労しない分、むしろ効率だっていいのかもしれない。
実装よりもインターフェイスに注意を払う
これも UNIX 哲学に関連する。
小さくて組み合わせられるものというのは UNIX 的なコマンドに限らない、ということは既に書いた通り。
UNIX コマンドにおいてこれを実現しているのはパイプやファイル、終了ステータスといった標準的なインターフェイスである。
そういったインターフェイスをうまく使いこなすことが、組み合わせやすいツールの実装を可能にする。
インターフェイスといえばオブジェクト指向言語にはまさにそのままの名前の機能が備わっている。
PHP でいうと Traversable というイテレータを入出力にする関数を組み合わせることであらゆるリスト効率的に行えるし、PHP 5.5 で実装されたジェネレータもまた Traversable を実装したイテレータなので、まったく同じように組み合わせることができる。
(ということを去年の PHP カンファレンスで話した)
HTTP をリクエストを引数としてレスポンスを返す関数として抽象化し、各プログラミング言語レベルのインターフェイスを与えることで WSGI/Rack/PSGI ミドルウェアとして Web アプリケーションを効率良く拡張できる。
RESTful な Web サービスにおいては、GET/PUT/DELETE といったインターフェイスごとにべき等性や安全性といった制約を持たせることで、リトライやキャッシュ化が容易になる。
そして URI というインターフェイスを通じてリソースが表現できることによって、あらゆる情報を簡単にリンクでつなげたり、API として機械的に処理することもできる。
インターフェイスさえ正しければ、中の実装がどれだけ複雑でわかりにくくても、それを利用する限りにおいては何の問題もないし、なんならテストを書いてリファクタリングすることもできる。
だけどインターフェイスが間違っていれば、その実装がどれだけ正しくて頑健でも、それを組み合わせて利用するのはすごく難しくなってしまう。
その問題を解決するにはリファクタリングではなくリストラクチャリングが必要で、そのためにはより多くの苦労やリスクが伴う。
情報共有について
情報は有用なだけでは広まらない
苦労して書いた社内ドキュメントが読まれないと、社内のどこかで無駄を生むかもしれないし、起こってほしくない間違いが起こるかもしれない。
そういう有用・重要なドキュメントでも、意外と読まれていなかったりする。
社内用に Gyazo クローンを作って、クライアント (Gyazowin+ というのを使った) のインストール方法や使い方を社内 Wiki に載せたことがあった。
周囲のエンジニアはすぐに便利さを理解して使ってくれたが、それ以外の部署の人達にあまりリーチできていないことに気づいた。
画像を表示するページの脇に使い方の Wiki にリンクを貼ってはいたけど、アクセスログを調べてみるとそこまで来た人が半年で数人に満たなかった。
そこでとにかく社内 Gyazo の存在に気づいてもらおうと、Wikipedia のジミー・ウェールズ風に自分の似顔絵 (社内 Gyazo を積極的に使っていた同僚に書いてもらった) バナーを作って、画像を表示するページの上部にデカデカと表示した。
これだけだと社内 Gyazo を使う人のいないクラスタだとやはりリーチできないので、そのバナーを印刷して、QR コード付きのポスターを他部署の壁に勝手に貼ったりした。
まぁこれはちょっとした奇行みたいなものだけど、それなりに話題になって DAU/MAU ともに着実に増加した。
あとは部署ごとに簡単なエヴァンジェリストみたいな人を決めて、新入社員に積極的に社内 Gyazo の存在や使い方を知らしめてもらうようお願いしたりもした。
入社間もない、人となりも知らない人が社内 Gyazo を使ってくれていることが増えて、スクリーンショットがないせいで問題点の伝わらないバグ報告に苛立つことも減ったような気がする。
インターネットな人たちの間では Gyazo の便利さは自明だけど、普通の企業だとそうじゃなかったりする。
そういう文化差を考慮したり、攻めるべきポイントを押さえて戦略的に情報を広める努力が必要になる。
シェアするのは自分の為
社内の Wiki を書いたり、ブログに記事を書いたり、ライブラリを GitHub に公開したり、勉強会で発表したり。
これらが周囲のメンバーや技術コミュニティの人達を助けることはあるし、逆に他の人がシェアした情報に助けられることはよくある。
そして他人の役に立っている、と実感できるとそれがエネルギーになることもある。
だけど単にシェアするだけでこういう効果が得られるとは限らないし、効果を心のそこから実感できることは少ないかもしれない。
効果を実感できないと、モチベーションもだんだんと下がってしまう。
こういうときは他人のためとかはとりあえず置いといて、ただ自分のために、将来の自分に向けてシェアすれば良い。
作ったソフトウェアの最初のユーザが自分であるように、シェアした情報に最初に助けられるのは自分。
人間はすぐ忘れるので今日役にたった Tips を 2 ヶ月後には思い出せないかもしれない。
そして情報を記事やスライドとしてまとめることで、自分の不理解が浮かび上がってきたり、理解をより進化させることにも繋がる。
他人の発表を 10 回聞くよりも、1 回だけ自分で発表する方が身になる。
問題解決について
仕事は問題解決の連続
Web エンジニアやプログラマに限るまでもなく、全ての仕事は問題解決であって、それによって価値が生まれ、対価が発生する。
プログラマが他の職業と比べて特殊だとすれば、その特殊性は解決のための手段をものすごく安価にハックできるというところにあると思う。
だからプログラマは問題解決に自覚的になることで仕事の価値を文字通り何倍・何十倍にもしていけるし、それができないと競争上すごく不利になる。
問題を解決するには、前提として問題発見と問題定義が必要になる。
それぞれを意識することで、より効率良く、意味のある解決にたどり着ける。
面倒くささに自覚的になる
Larry Wall のプログラマの三大美徳のひとつに「怠惰」というのがある。
労力を抑えるための努力を惜しまないことがプログラマに必要な資質である、ということのようだ。
言い方を変えれば、面倒くささに自覚的になれば、解決すべき問題が見えてくるし、単純な作業を無意識に繰り返しても苦痛でない人はあまりプログラマに向いていないように思える。
僕は周囲を見回すと、面倒くささへの無自覚さに驚かされることが多かった。
面倒な手続きの多いインターフェイスを、みんな文句ひとつ言わずに使いこなしている。
多分、最初は多くの人が面倒に感じていたんだろうけど、繰り返し利用するうちに慣れてその面倒を忘れてしまったりするんだろうと思う。
身の回りにある面倒の多くはそんなに大したことではなかったりする。
例えば検索するためのフォームだったら、入力欄にフォーカスを当てるためにクリックするのが面倒なので autofocus 属性を付ける。
画面上の値をコピペして検索ボタンを押すのが面倒だったら、値自体をリンクにして、クリックするだけでよくする。
「1-clickを0-clickにすると革命になる」という言葉もあるけど、そういうチャンスは滅多にないし、技術的にも簡単ではない。
「n-clickを1-clickにする」だけでもいろんなことがなかなか快適になるし、そういう細かいところに気づけるだけでも他の人に差を付けることはできる。 (商売になるならそれでも十分)
「問題は何か」を常に意識する
小さな問題点に気づけること、それらを丁寧に正していくことは大事だけど、そういう小さい改善を積み重ねても全体としての問題の解決につながるとは限らない。
より大域的に問題を意識し、その解決にとって意味のある改善なのかを見極めないと、時間ばかり失われてしまう。
「問題は何か」ということは名著ライト、ついてますかの中でもしつこいぐらい繰り返し問われている。
それぐらい人間は手段と目的を履き違えやすいし、あらゆる手段が安価に手に入りやすかったり、手段の追求が知的好奇心を刺激したりするので、プログラマは特にそういう状況に陥りやすい。
そういう目的と手段の逆転がモチベーションを生み、そうやって新たな技術が生まれているということも見逃せないけど、今すぐ目の前の問題を解決する必要のある状況かどうかは見極める必要がある。
面倒を技術で解決するのも「怠惰」だし、一見問題だけど解決してもしょうがないものを解決しないのも「怠惰」だ。
問題解決は枝刈り
これは特にデバッグのときに役に立つことで、必要のない枝を刈ることを意識することで、素早く問題を解決できる。
例えば Web API にアクセスするスマートフォンアプリが思った通りに動作しない場合、まずは問題がクライアントサイドなのかサーバサイドなのか、というところから切り分けられる。
クライアントサイドだとしても例えば WebView の中の問題なのかネイティブ層の問題なのかそれともそれらのブリッジ層の問題なのかということに切り分けられるし、サーバサイドであればプログラムの問題なのかミドルウェアやネットワークの問題なのかとなる。
こういう切り分けを常に正しく行えるとは限らないし、そのための情報が足りていないということもあるかもしれない。
それでも一旦問題を仮定し、それ以外の可能性を排除することで、その仮説の検証にフォーカスできる。
仮説が間違っていることが検証できれば、それはそれでひとつ枝を刈れたことになるので、一歩前進したことになる。
そして仮説は高いレイヤから作り、その検証は低いレイヤから行う。
サーバサイドの問題だと仮定した場合、例えば mitmproxy のような HTTP プロキシで HTTP 通信を覗くことが役に立つだろうし、クライアントサイドの問題だと仮定した場合は Web インスペクタで DOM を覗いたり、デバッガのブレークポイントで変数の中身を覗くことが役に立つ。
低いレイヤから考えると見るべきポイントは無限にあるので、やはり高いレイヤからの枝刈りによって対象箇所を絞ることが大事ということになる。
まとめ
これらのことを学ばせてもらった EMTG 株式会社を昨日 2015 年 8 月 31 日をもって退職しました。
次の職場は全然違う業界ですが、これらの価値観はきっと役に立ってくれることだろうと思います。
それではまた。