多言語に親しむ

Ian Bicking の記事を翻訳してくれてたのを見かけた。あとで読もうとなおざりになってた ...

その一節にこんなのがあった。

不思議なことに、プログラマが数日や数ヵ月で新たな言語を身につける方法が話題になるのをよく耳にします。プログラマの知識は、(この例のように)別の言語に応用可能だと考えられているようですが、私は疑問を感じます。独善的な意見でしょうが、こう考える人たちは何かをマスターすることの実際を分かっていないのかもしれません。もちろん新たな言語や環境をモノにするのに、また1万時間をかける必要はないでしょう。それでも確実に数千時間は必要ですし、何年もかかることです。私自身はようやくそのレベルに近づいたと感じています。

Pythonにサヨナラを - HackerNews翻訳してみた

私の周りにはプログラミング言語の仕様を抽象化して語る人がいて、この賛否を一般論として明確にするのは難しい。プログラミングに限らず、言語そのものを抽象化して捉えられる人は、その本質を見抜くのが抜群に速い気がする。もしかしたらプログラミングのセンスというのはそういうのを指しているのかもしれない。もちろんプログラミングの素養というのは、知識によるものや文化的な要素もあるし、実際に頭で分かってるからといって実装できるというわけでもない。論理や設計と実装は別ものだし、コーディングはさらに属人的になる傾向がある。

さて、そういった前置きは置いておいて、私自身は Ian Bicking の意見に賛成だ。以前、転職の面接でこんなことを聞かれたことがあった。

新しくプログラミング言語を習得するのにどのぐらいかかりますか?

この質問には前提が何もないので「習得」というのが何を指すのかは受け取った人によって異なるだろう。私は「2年ぐらいですかね」と答えたら「2年もかかるんですか」と返された。

当時は5年ぐらいプログラマーをしてきた経験から答えていた。感覚的に「習得」という言葉をこんな風に捉えていた。

  • 分からないことがあったときに何を (どこを) 調べれば良いかを知っている
  • 他人のツールやライブラリを修正してパッチを送ったりできる
  • クラッチからツールやライブラリの設計ができる
  • 自分で作ったものをパッケージングして公開できる
  • 開発コミュニティに参加して、その文化を理解している

このぐらいできたら、この言語を使って開発してますと言ってもいいかなと考えていた。一節によると、プログラミング言語の開発環境が無償で配布されるようになったのは Java 以降らしい。インターネットの普及とも関連するのだろうけど、それ以前の古参プログラマーにとってはライブラリを公開したり、開発コミュニティに参加するというのは当たり前ではないかもしれない。

いまの職場で Java を使い始めて1年半ぐらい経つけど、実際のところ、この項目の半分にも満たない。たぶん私はプログラミング言語の習得が遅い、まぁセンスがないのだろう。そろそろ自分で Java のツールやライブラリをスクラッチから書いてみたいと思ってはいるけど、そこまでやる気がなかったり、Java の開発コミュニティにも参加してなかったりする。

技術力の高い人が周りに多いが、OSS のライブラリやツールを使っていて、コミュニティにフィードバックしない人が意外といるんだなというのも分かってきた。私はもともと OSS がやりたい派で SIer から転身してきた方だからこの感覚は自分の方が一般よりズレてるのかもしれない。業務系の開発の人は、普段の業務に忙しくてそこまでのモチベーションはないのが普通かもしれない。実際、私も SIer にいた頃は業務に忙殺されて OSS にコントリビュートしようなんて考えすらなかった。

確かに BTS に既存チケットがないかを調べて登録するのも面倒だし、パッチを書いても reject されることもままある。パッチの approve は自身の技術力の客観的評価に良いと思う。というのは、その対象コードの空気を読まないと、まともなパッチは書けないし、その文化を理解しないとその修正は取り込まれない。何となくだけど、そういうのを1つずつ積み重ねていくうちに自分の目指すプログラマーのキャリアができるような気がしている。これは人それぞれだ。

Web 系の開発の人たちの方が OSS の開発やコントリビュートに活発なのは、Web の技術が業務系の開発においては、まだまだ応用範囲が限定的だし、世の中の業務を全てを Web 化するにはもう少し時間がかかるんだろう。Web 系の開発の人たちは Web の世界で起こってることが全てだけど、業務系の開発の人たちは Web でこんなのが流行ってるから使ってみようぜといった感じ。とはいえ、permissive ライセンスの隆盛にもあるように業務系にも OSS の利用が高まっているからこの感覚は徐々に Web 系の人たちと同じものになっていくと思う。そして、正にクラウド化が拍車をかけてる。

話がずれてきたので戻す。

慣れた Python と慣れてない Java でコーディングしていて、何が違うのかというのをよく考えたりする。最近ちょっと分かったことがある。格好よく言うと、Python で設計するときは未来のことも考えながらコードを書いてる。

  • 後からこんな要望がくるかもしれない
  • 当初はこういう設計方針だったけど、それが変わるかもしれない
  • この処理の影響範囲はここで局所化しておく
  • 低レベルと高レベルの api を設けておく
  • 依存関係を意識して、安定したコードと安定してないコードを明確に分ける

ある程度、未来にどんなことが起こっても大きな変更や工数がかからないように作ってる。実際、本当にそうであるかどうかは置いておいて、そういう自信をもって設計している。いわば、設計原則をその言語の文化に則って明確にするということだ。これをもっと昇華させると哲学的になるんだろうと思うけど、そこまでは至っていない。それは Python という言語に慣れ親しんだところからの、設計や実装の経験からできることだ。

そして、私がプログラミングで一番重要視しているのは保守性だと思う。それは最初に就いたお仕事がシステム運用で、運用のしんどさを経験したせいかもしれない。きれいなコードを書こうと思うのも、テストを書こうと思うのも、リファクタリングしたくなるのも、保守性を高めたいからだ。

理想としては

write once, no update.

なコードを書きたい。

いまの職場では数十万行というコードベース (Java) に対して、修正したり拡張したりしていると意図しないバグにたくさん遭遇する。それは良くないことだけど実におもしろい。いや、他人のコードだとおもしろいけど、自分のコードだと悔しい。でも、そのバグをきっかけにコードを読む、そして関連部分の仕様を理解する。こういう設計/実装をすると、こういうときにバグが発生するんだと学ぶ。CTO が良いプログラムとは分割統治であり、それを実現するキーワードの1つがインターフェースだと言ってるのを何度も読んだが、ある程度の規模のコードベースがあって、その意味が理解できた。

バグを埋め込むのは、自分のプロダクトに対する理解度が足りないことも大きいが、自分よりも経験や技術力の高い先輩や上司をみていても結構なバグを埋め込む。誤解を恐れずに言えば、プログラマーの技術力に関係なく、いじったコードに対するバグを埋め込む量というのはある一定の割合に収束するのかもしれない。そう仮定すると、どうすればバグの埋め込まずにコードを修正できるかという問いの答えに技術力はあまり関係ないんじゃないかとも思う。

世の中に出回っているベストプラクティスは上辺のきれいなところだけ。もちろん学ぶ意義はあるけど、それはほんの入り口に過ぎない。現実のプロダクト品質のコードはもっと複雑で根が深い。単に言語仕様を理解しているだけでは駄目だ。そのヒントは、他人が書いた Python のコードをレビューするときに感じることでもあった。コードレビューでは設計そのものを否定しにくい。このコードで動くし、間違ってないけど、全体としてしっくりこないというときがある。コードに一貫性がなかったり、設計原則が伝わってこないときだ。動くコードを前にして全体的に書き直してとは言いにくいからまぁ大丈夫ですと言う。他人のコードじゃなくても、自分が過去に書いたコードを見直すときにも似たような感覚がある。

その差はどこにあるのか。設計なのか、経験なのか、文化なのか。あるときは分からなかったものが、どうしていまは分かるのか。この認識のズレや違いを明確に意識できれば、いまよりも言語の習得を速められるかもしれない。

また話がずれてきたので戻す。

最近、Ruby のコードをちょくちょく書いてる。スクリプト言語Python (とシェルスクリプト) ができれば十分だからと、あえて同じ適用領域の他言語は避けてきた。社内には Rubyist の方が多く、Ruby ツールも多い。Rspec でテストを書いたりもしている。自分が関わる業務のプログラムが読めなかったり、書けなかったりするのはストレスなので、結局 Ruby も学ぶことにした。

公式ドキュメントと Ruby Styleguide をみてツールを作った後に、初めての Ruby を読んだところ、よく分かってなかったことや疑問に思ったことが解きほぐされて、この書籍は凄く良かった。まだ手習い程度のことしか分かってないけど、コードを書いていて Python よりも Ruby の方がおもしろいと思う。(Python と比べて) 言語仕様は複雑だから、そういうのを調べたり学んだりするのも楽しい。プログラマーの格好良くコーディングしてやろうみたいなところを良い意味で刺激していると思う。

Ruby のコードを書いてみると一貫しなくても良いんだよとばかりに自由気ままに書ける。全てが式で値が返ってくると便利だし、余分なコードも減るけど、調子にのると返り値を誤解したりコードを修正したときにはまる。簡単にクロージャーをブロックで書けてしまうからコードの様相が散らばる。定義済みクラスへのメソッド追加や特異メソッドはそんなことやっていいんだ!?って感じ。でも、やれることが違うと発想も変わってきて、いろんな設計の違いに触れることができそうな気がする。そういう他と違うということ自体がやっぱりおもしろい。

取りとめがなくなってきた、まとめる。

昔、ある人がこんなことを言っていた。

素人にソフトウェアを開発させるな。プロの開発者だけが設計して開発しろ。

そうなんだろうけど、現実の職場では何割かの素人も開発している。自分もあるときはその1人だ。そして、素人がプロになるための方法もこれしかない。決して座学だけでプロの開発者になれない。

1. まず動くものを作る
2. きれいなコードを書く
3. テストを書く
4. リファクタリングする
5. 設計を見直す

そうだ。先週、同僚と Go について井戸端会議してたんだけど、某ブログに Go 始めてましたとか載ってて、始まってたんだと驚いてる。でも、機会があればやってみたい!