『Coders at Work』まとめ Part 1の続き。
・(プログラマすべてが読むべき本は?)これについては若干複雑な思いがありますが、それでも『デザインパターン』はすべてのプログラマが読むべきだと思います。この本は共通のボキャブラリを与えてくれます。良いアイディアがたくさん詰まっています。一方でスタイルや言語の寄せ集めのようで、古さが感じられるようになりました。それでも間違いなく読む価値はあると思います。
・近ごろではみんな並行性について学ばなければならなくなっています。『Java並行処理プログラミング』はおすすめできます。タイトルにJavaとありますが、内容の多くはどんなプログラミング言語にも使えるものです。
#私からも推薦します。
・(プログラマはなぜ言語について宗教的になるのか?)分かりません。しかし言語を選ぶときには、単に技術的なトレードオフの選択をするだけでなく、コミュニティをも選んでいるのです。これは酒場を選ぶのに似ています。酒場に行くのは良い飲み物を提供してもらうためですが、それは一番重要な部分ではありません。そこにはどんな人がいて、どんな話をしているかということが重要なのです。
・(文芸的プログラミングについて)私が代わりにするのは、コードが読みやすくなるよう、変数名、メソッド名といった識別子の名前を選ぶのに喜んで文字通り何時間も費やすということです。そういった識別子を使った式を読んで、それが英語の文章のように読めるなら、プログラムが正しいものになる可能性は高くなり、ずっと保守しやすくなります。「単なる変数名だろ。時間をかける価値なんてないよ」と言う人は単に理解していないのです。そういう態度では保守可能なプログラムはできません。
#「人の理解」に最適化した名前をつけようとする意図にはうなずけるが、その「人」を実際に使うことなく当てずっぽうだけで最適化しようとするのは、プログラムの実行速度を測定なしで当てずっぽうだけで最適化しようとするのに等しい。APIなどのパブリックな名前については『.NETのクラスライブラリ設計』や後のSimon Peyton Jonesを参照。プライベートな名前の命名に迷うのは、自分がなにをしているかわかっていないことの兆候。
・今日においてさえ、並行処理ユーティリティのためのユニットテストを書くというのはアートに近いのです。
#同期オブジェクト、ダメ! 絶対!
・
今から思うとおかしいのは、現代的な小道具というのはどれも、実際にはより生産的にしてくれるものではないことです。階層的ファイルシステムでどうやって生産的になるのでしょう? ソフトウェア開発の大部分はどのみち頭の中で行われるのです。あのようなシンプルなシステムのほうが、統制のとれた考え方を引き出します。ディレクトリシステムがなく、すべてのファイルを1つのディレクトリに入れなければならないとしたら、非常に統制が取れている必要があるでしょう。構成管理がないとしたら、非常に統制が取れている必要があるでしょう。そのような統制の取れたやり方をするのであれば、階層的ファイルシステムや構成管理システムがそんなにいいものとも思いません。そういったものは自分の問題を解くという根本的な問題を解決してくれるわけではありません。グループの人々が一緒に働くのを容易にはしてくれるでしょうが、個人にとってはそう違いがあるとは思いません。
それから今日では選択の重荷が大きすぎると思います。かつて私にはFortranしかありませんでした。シェルスクリプトさえなかったと思います。実行するためのバッチファイルとFortranコンパイラだけです。それから本当に必要な場合にはアセンブリ。だから選択の苦しみというのはありませんでした。今時の若いプログラマは大変に違いないと思います。20もの異なるプログラミング言語に、何十というフレームワークとオペレーティングシステムがあります。選択のために身動きできなくなってしまうでしょう。昔は選択による麻痺状態なんていうものはありませんでした。単に始めるだけのことで、言語やなんかに何を使うかという選択は、すでになされていたのです。どれにするかと考えることはなく、ただやり始めれば良かったのです。
・(ソフトウェア再利用について)私はある人たちが「これは本当に不自然なことで、OTPフレームワークに合わせるためコードをねじ曲げることになる」と言うのを耳にしました。だから私は「じゃあOTPフレームワークを書き換えたらいい」と言いました。彼らはフレームワークが変えられるものだと思っていないのです。しかしフレームワークだって一種のプログラムにすぎません。変えるのはむしろ簡単です。だから私が手を入れて、彼らが望むことをできるようにしました。彼らはそれを見て「ああ、本当に簡単ですね」と言い、簡単であることは認めてくれましたが、「でもフレームワークをいじったりするのはプロジェクトマネージャが嫌うんですよ」と言うのです。だったら何か別な名前をつければいいんですよ。
#今の時代の最悪の税金は、セキュリティアップデート。セキュリティアップデートに備える必要がある場合は、よほどのことでないとフレームワークをいじれない。
・長い間私は包括的な誤りを犯していました。その包括的な誤りとは、ブラックボックスを開けないということです。ブラックボックスは手を出せない難しすぎるものであり、開けずにおこうというメンタリティです。
・初心者プログラマがそういった抽象化をすべて開いて見るべきだとは言いません。しかし言っておきたいのは、少なくともそれを開ける可能性について考えてみるべきだということです。その考えをすっかり排除してしまわないことです。直接的な方法が、パッケージ化された方法より早いか見てみるのは価値のあることです。一般にソフトウェアを買ったりほかの人のソフトウェアを使う場合、合わせるためにすごく長い時間がかかることを覚悟しておく必要があります。それは正確にこちらのやりたいことをやってはくれず、少しばかり違ったことをします。その違いを解消するのには長い時間がかかるかもしれないのです。
・再利用性の欠如はオブジェクト指向言語から来るもので、関数型言語では話が違います。オブジェクト指向言語の問題は、それが周りに引きずっている暗黙の環境にあります。バナナが欲しかったのに、手に入れてみたら、バナナを握ったゴリラと、それにジャングルまでついてきたというようなものです。
・(コードを書いてみたら「これはおかしい」と感じて書き直すことについて)こう思ったのを覚えています。「こういったことを全部書かなくとも考えられたらいいのにな」。コードを書かずに洞察を得られたらいいですよね。私は今ではそれができるようになったと思います。20年かかりましたが、私はそれをプログラムの書き方を学んでいた期間だと位置づけています。今ではプログラムの書き方が分かるようになりました。以前はプログラムの書き方を学ぶために実験をしていましたが、今ではプログラムの書き方が分かり、もう実験は必要なくなりました。
・私はどちらかというとCを手で書くよりはプログラムで自動生成しますね。そのほうが簡単ですから。
・「ジョーのデバッグの法則」というのがあります。それは、すべてのバグは最後にプログラムを修正した箇所からプラスマイナス3ステートメント以内にある、というものです。
・Prologはほかのどのプログラミング言語とも違っています。まったく驚くべき考え方を持っています。あらゆる問題に適するものではありません。しかし非常に広い範囲の問題に適しています。広くは使われていません。Prologではプログラムをとても短く書けることを考えると、すごく残念なことです。初めてPrologでプログラムを書いた時にはショックを覚えました。衝撃的な体験だったのです。プログラムがいったいどこにあるのか探し回るような感じです。だってプログラムを書いてはいないのですから。ただシステムや問題に関する事実をいくつか記述しただけです。するとPrologが何をすべきか見つけ出すのです。まったく素晴らしいです。私はErlangなんか捨ててPrologに戻るべきなのかもしれません。
・私が見てきたプログラマについて言えるのは、あらゆる言語に優れているか、どの言語もだめかのどちらかだということです。C言語の優れたプログラマはErlangでも優れたプログラマになります。これは非常に確かな予測を与えてくれます。例外がなくもありませんが、1つの言語で優れた者になるために必要な知的能力は、ほかの言語にも適用可能なのです。
・(ハードウェアの並列性について)データ並列化は、本当に並列なわけではなく、キャッシュの振る舞いにかかわることです。Cのプログラムを効率的にしたいとき、*pがある16ビット境界内にあるとき、*pへのアクセスの後*(p+1)へのアクセスは基本的にタダになります。キャッシュに載っているからです。そうするとどれくらいキャッシュラインを広くするかが悩みどころになります。1回のキャッシュ転送で何バイトのデータを持ってくるべきか? これがデータ並列性で、プログラマは利用できますが、データ構造に細心の注意を払い、それがメモリ上で正確にどのように展開されるか把握する必要があります。非常に煩雑で、あまりやりたいとは思わないでしょう。
#あとでFran Allenがこれと関連する話題に触れる。
・(Microsoftが行うプログラマを対象としたユーザビリティテストについて)
彼らはAPIのテストについても興味深い仕事をしています。レドモンドにいるスティーブン・クラークのグループは、プログラマが新しいAPIを提示されたときにどうするかを、何をしようとしているか口に出してもらうことを通して系統的に観察しています。そしてAPIをデザインした人たちに、マジックミラーの裏から見てもらうわけです。
するとマジックミラー裏の人たちが「だめだめ、そんなことしないで! やり方が違うってば!」と声を上げるわけですが、防音になっています。これはとても示唆に富む体験になります。そしてAPIを修正することになります。率直に言って、プログラミング言語の研究はこういう点が弱いものです。ある部分では、そういった疑問が答えるのが難しいからです。そして文化的にもあまりそういったことに慣れていません。これは弱い部分だと思います。しかしこれは私が個人的に良く議論できる領域でもありません。
・両端キューへのシーケンシャルな実装は、大学1年でやるプログラミングの問題です。それがノードごとにロックをつけた並行版の実装となると、研究論文レベルの問題になります。とても大きなステップです。何かがそんなに難しいのは馬鹿げているくらいです。トランザクショナルメモリを使えば、再び学部の問題のレベルになります。挿入と削除の操作を"atomic"でラップするだけで良いのです。これは驚くべきことだと思います。これは質的な違いです。STMを実装する人たちは、メモリに対するたくさんの変更が間違いなくアトミックに1つの操作としてコミットされるようにする必要があります。比較とスワップだけでこれをやるのは簡単なことではありません。可能ですが、注意深くやる必要があります。
・(プログラマが無人島に持っていくべき本は?)クリス・オカサキの本、"Purely Functional Data Structures"も素晴らしいです。アーサー・ノーマンの授業が1冊の本に拡張されたかのようです。副作用なしで、しかも効率よくキューやルックアップテーブルやヒープを実装する方法について書かれています。すごく良い本ですよ。みんな読むべきです。それに短くて読みやすい本でもあります。
・プログラマとしての生活で最もがっかりさせられるのは、もはや修正ができないようなコードに直面することで、ほかの人が書いたものでもきついことですが、さらに悪いのは自分の書いたものがそうなったときです。これは本当にがっかりすることです。
・(学会の先進的なアイディアを産業界が取り入れるスピードについて)業界がもっと前向きであるべき領域があるのは確かです。「今日すぐに移行することはできないが、10年先にどこへ向かうかの計画を持つべきじゃないか? 今と同じ場所でないとしたら、どうやってそこへ行くのか?」と考える必要があります。
しかし改善する領域は大きなインパクトのあるところにしたいでしょう。多くの場合、プログラミング言語が見ているところはおそらくレベルが低すぎ、言語設計者たちが思っているような大きなインパクトはありません。「俺の新しい輝く言語を見てくれ。この6行のコードが2行で書けるんだ」。それは結構だし、それでより生産的にも、デバッグや保守が楽にもなるでしょう。しかしそのコードは稼働しているシステム全体のごく小さな部分にすぎず、本当に大きな問題は、データを毎日更新し、Webをスクレーピングしてその新しいデータを取り込み、適切なフォーマットにすることかもしれません。だから自分の解いている問題は全体の問題に対してごく小さな部分だということを自覚する必要があり、切り替えを起こさせるには大きな障害があるということです。
・(私たちは今でもアセンブリ言語を学ぶべきなのでしょうか?)
分かりません。クヌースは何でもアセンブリでやれと言っていました。Cで書くのは非効率すぎるということで。これには賛成できません。どの命令が非効率か分かるくらいには知っていたいと思うかもしれませんが、問題はもはや個々の命令のレベルではなくなっています。ここが2命令でなく3命令になっているとかいう話ではありません。ページフォルトやキャッシュミスがあるかという話です。アセンブリ言語を知っている必要はないと思います。アーキテクチャは必要です。アセンブリ言語はどういうものかとか、メモリ階層というのがあって階層を1レベル下ると大きなパフォーマンスペナルティがあるといったことは理解しているべきです。しかしこれは抽象的なレベルで理解できることです。
・
私が確信しているのは、1つの言語があらゆる問題を解く上でほかのどの言語よりも優れている、ないしは同等に優れていると考えるのは間違いだということです。アプリケーションの領域ごとに、どの言語が適しているかは違っているものです。
(中略)
問題は、ある小さな一組のアイデアに対して優れた記法を考え出し、それを完全なプログラミング言語にしたいと思った場合、完成させるためにその周りにいろいろなものを構築しなければならず、あらゆることについて良い仕事をしないなら、その1つのアイデアに関しては優れているがほかの部分についてはできの悪い偏った言語を作ることになるということです。
・
Perlは批判できるほど本格的に使ったと言えるか分かりませんが、この言語には引かれませんでした。C++も引かれませんでした。C++のほうは結構書いていますが。今はC++で書こうと思うようなことは、Javaでもっと簡単にできます。効率が最大の関心事というのでなければ。
しかし私はビョーン・ストラウストラップの努力に対する批判者とは見られたくありません。彼は自分で明確な目標を設定していました。それはCと完全に後方互換なオブジェクト指向言語を作るということです。これはとても難しい仕事です。そしてこのような制約の下で、彼は感心するような設計を行い、ずっとよく持ちこたえています。しかしプログラミングにおける目標としてCと後方互換にするという決断には致命的な欠陥があると思います。乗り越えられない困難を生むことになります。Cの型システムは根本的に壊れていますから。ある種の問題を回避するには十分かもしれませんが、完全なものではなく、当てにはできないのです。
・(自身の設計した言語が純粋関数型でないことについて)一方でHaskellはモナドを発見し、I/Oモナドを引き入れ、今度はトランザクショナルメモリモナドを引き込んでいます。関数型言語というのは理論上のことで、助けになることもあるでしょう。一方でどんどん命令的になっています。鏡の国のアリスに出てきた白の騎士を思い出さざるを得ません。「頬髯を緑に染めて、いつも大きな扇を持って誰にも見られぬようにする計画について考えておった」。ある意味で、モナドはこの扇のように見えます。I/Oを引っ張り込んでまた隠してしまうというのは。副作用は本当はあるのか、それとも本当にないのか?
・
私は多様性を支持する方です。今見た例からも、「いや、みんなに好きなようにやらせよう」と言いたいです。無知によって生じる無駄というのもあるでしょうが、自然選択によって整理されます。そして時折このような未来へと連れて行ってくれる新種が現れるのです。
標準化しようと、1つの方向に向かおうと試みることによって、クリエイティビティが疎外されているような領域はたくさんあると思います。私はJavaに支えられている会社で働いているのであまり言えないんですが、Javaの出現というのはその1つの例だと思います。OOPSLAを見ればよく分かります。Javaが現れたことによって、ほかのオブジェクト指向言語のみならず、動的言語全般に至るまで、活動がスローダウンするか、すっかり止まってしまいました。これは損失だったと思います。
・4半世紀前、私たちは人工知能について考えていました。マシンは当時とは比べものにならないくらい速くなったというのに、私たちはその方面でほとんど何もしていません。いまだにFortranに近いところでやっています。Prologができてずいぶんになります。論理プログラミングでなし得ることはたくさんあります。アセンブリ言語を学んで仕組みを知るべきだと思っているなら、もっと枠を踏み出た、未来の可能性の一部であるようなものに浸るべきだと思います。
Posted by hajime at 2012年01月18日 18:55