Javaスクールの危険

From The Joel on Software Translation Project

Jump to: navigation, search

Joel Spolsky / 青木靖 訳

2005年12月29日木曜


近頃の若い者ときたら。

勤勉はいったいどこへ行ってしまったんだ?

「近頃の若い者」は我慢がないと不平を言うようになったのは、私も年を取ったということなのかもしれない。

そりゃ恵まれてるね。私は3ヶ月汚水浄化槽の中の茶色い紙袋に住んでいたよ。朝6時に起きて、袋を掃除し、固くなったパンの耳を食べ、工場まで歩いて行くと、1日14時間、毎週毎週働きつづけ、家に帰ると親父にベルトでたたかれて寝床についていたんだ。
——モンティ・パイソンの空飛ぶサーカス 4人のヨークシャー人

私は若い頃、パンチカードでプログラムを作る方法を学んだ。ミスをしたら、それを訂正するためのバックスペースのような近代的な機能は存在しなかった。カードを捨ててはじめから打ち直すのだ。

私は1991年にプログラマの面接をするようになった。コーディングの問題に答えるのに好きな言語をいつも選ばせていたが、99%の場合彼らはC言語を選んでいた。

今日ではみんなJavaを選ぶようだ。

悪く取らないでもらいたい。実装言語としてのJavaに悪いところは何もない。

ちょっと待って、今言ったことは訂正したい。このアーティクルではJavaに実装言語としてまずいところがあると言おうとしているのではない、ということだ。Javaにまずいところはたくさんあるのだが、それはまた別なアーティクルで書くことにしよう。

このアーティクルで言いたいのは、Javaは大体において優れたプログラマと凡庸なプログラマを見分けるのに使えるほど難しい言語ではないということだ。Javaは仕事で使うのには良い言語かもしれないが、それは今日の話題ではない。Javaが十分に難しくないというのはバグではなく、機能であるわけだが、それには1つ問題がある。

私のささやかな経験から言わせてもらうと、伝統的に大学のコンピュータサイエンスのカリキュラムで教えられているもので、多くの人がうまく理解できないものが2つあった: ポインタと再帰だ。

大学では連結リストやハッシュテーブルなどについて学ぶデータ構造の授業が最初にあり、そこではポインタを徹底的に使う。この授業はふるい分けに使われていた。あまりに難しくて、コンピュータサイエンスの学位の知的な挑戦に耐えられない者は脱落していたのだが、それは良いことなのだ。もしポインタが難しいと思っているなら、不動点理論に関する証明で難儀するのを覚悟しておくことだ。

高校ではApple IIのBASICでpongゲームをうまく作れていた子供たちが、大学に入ってデータ構造の授業のCompSci 101を取り、話がポインタのことになると彼らの脳みそは吹き飛んでしまう。そしてこれはロースクールに進むほうが良さそうだと思って政治科学専攻に切り替えるのだ。コンピュータサイエンス学科のドロップアウト率の数字をいろいろ見たが、それは通常40%から70%の間だ。大学はこれを損失だと考えているようだが、私はこのふるい分けを不可欠なものだと思っている。彼らがプログラミングのキャリアで成功したり幸福になることはないだろうからだ。

コンピュータサイエンスの学生の多くにとって困難なもうひとつの授業は、再帰プログラミングを含む関数プログラミングを学ぶ授業だ。MITはこのテーマについて非常に高い基準を設けており、授業6.001を必須にしている。その教科書(サスマン & エイブルソンの計算機プログラムの構造と解釈)は世界の何十何百というトップクラスのコンピュータサイエンス学科でコンピュータサイエンスへの入門に使われている。(古いバージョンの授業がオンラインで見られるので、ぜひ見るといい。)

これらの授業の難しさは驚くばかりだ。最初の授業でSchemeのほとんどすべてについて学び、他の関数を入力とする不動点関数が導入される。ペンシルベニア大学のCSE121で私がそういう授業と格闘していたとき、ほとんどと言わないまでもかなりの学生がクリアできなかった。その課題はあまりに難しかった。こんなのフェアじゃないと、長い泣き言のメールを私は教授に書き送った。ペンシルベニア大学の誰かが私の言ったこと(あるいは他の誰かの不平)を聞き入れてくれたようだ。あの授業が今ではJavaで教えられているからだ。

彼らが聞いてくれなければ良かったのにと思う。

自分に必要な資質があると思う? ここで試してみるといい!

これに関しては議論がある。長年に渡る私のような怠惰なコンピュータサイエンスの学生の泣き言と、アメリカの大学のコンピュータサイエンス学科を卒業する学生の少なさに対する産業界からの苦情が功を奏して、この10年の間にたくさんの大学がJava 100%へと移行した。Javaは流行ってるし、履歴書の評価に"grep"を使っているリクルーターには気に入られており、何よりポインタや再帰を理解する脳みそを持ち合わせていないプログラマをふるい落とせるほど難しい部分がJavaにはないのでドロップアウト率は低くなり、コンピュータサイエンス学科は学生を増やして予算を上げることができ、すべてがうまくいくのだ。

Javaスクールの運のいい学生たちは、ポインタベースのハッシュテーブルを実装しようとして奇妙なセグメンテーションフォールトを目にすることもない。ビットに詰め込もうとして気が狂いそうになることもない。純関数プログラムでは、変数の値が決して変わらず、それでいて絶えず変わっているというようなパラドックスに頭を突っ込まずに済む!

それが理解できる脳みそを持っていなくとも、4.0の成績が取れるのだ。

数々の困難を生き抜いてきたことを自慢しているあの4人のヨークシャー人のように、私は昔気質の頑固者に過ぎないのだろうか?

1900年には、ラテン語とギリシア語は大学で必須科目だった。それが何かの役に立つからではなく、教養のある人間に必須なものだと考えられていたためだ。ある意味で私の議論は(あの4人のような)ラテン語支持者の議論と違わない。スコット・ベイカーが書いている。「ラテン語は精神を鍛える。記憶力を鍛える。ラテン語の文章を解読することは、思考の訓練であり、とても知的なパズルであり、論理的思考のためのよい入門になるのだ」。しかし今ではラテン語を必須科目としている大学は1つもない。ポインタや再帰はコンピュータサイエンスにおけるラテン語とギリシア語になるのだろうか?

ポインタを使うプログラミングは今日書かれるコードの90%には必要とならず、製品コードにおいてははなはだ危険なものであるということは素直に認める。その通りだ。そして関数プログラミングは実務ではほとんど使われていない。それも認める。

しかしそれでも、最もエキサイティングなプログラミング仕事ではこれらは重要なものなのだ。たとえばポインタなしにLinuxカーネルで作業することはできない。Linuxのコードを1行も理解することはできず、実際ポインタの理解なしにはどんなオペレーティングシステムのコードも理解できない。

関数プログラミングを理解していなければ、GoogleをあれほどスケーラブルにしているアルゴリズムであるMapReduceは発明できない。MapとReduceという用語はLispと関数プログラミングから来ている。純関数プログラムは副作用がなく容易に並列化できるということを6.001に相当するプログラミングの授業で聞いて覚えている人には、MapReduceは容易に理解できる。GoogleがMapReduceを発明し、Microsoftが発明しなかったという事実は、Microsoftが基本的な検索機能についてキャッチアップの途上にあり、一方Googleは次なる課題へと進んでいることを示している。Skynet世界最大の並列スーパーコンピュータを構築しているのだ。この流れの中でいかに遅れを取っているかをMicrosoftがちゃんと理解しているとは思わない。

しかしポインタと再帰の明らかな重要性以上に重要なのは、これらの学習から得られる精神的な柔軟さと、これらを教えている授業からふるい落とされないために必要な精神的態度が、大きなシステムを構築する上で欠かせないということだ。ポインタと再帰には、ある種の推論力、抽象的思考力、そして何よりも問題を同時に複数の抽象レベルで見るという能力が要求される。そしてポインタと再帰を理解できる能力は、優れたプログラマになるための能力と直接的に相関している。

オールJavaのコンピュータサイエンス教程では、こういった概念を扱うための頭の回転の良さを持ち合わせていない学生をふるい落とせない。程度を下げた新しい授業はどうにか切り抜けられるが、Java会計アプリケーション以上に洗練されたプログラムを作れるほどには頭の出来の良くない卒業生たちを、Java 100%スクールが量産しており、その様を私は雇用主として目の当たりにしている。そういう学生はMITの6.001やイェールのCS 323を決して生き抜くことはできない。最近オールJavaになったデューク大や、私と友人がひどい目に合ったCSE121の言語をSchemeとMLからJavaに変えたペンシルベニア大の学位よりも、MITやイェールの学位に重きを置く理由がここにある。優秀な学生でもデューク大やペンシルベニア大を出た人は雇いたくないと言っているのではない。ただ優秀なのが誰なのかを見分けるのがすごく難しいのだ。かつては学生の出来がいいかどうかは、再帰アルゴリズムを数秒で書き出すことができるかとか、連結リストを操作するポインタを使った関数を、ホワイトボードに書くのと同じくらいの早さで実装できるか見れば良かった。しかしJavaスクールの卒業生たちについては、彼らが躓いているのが十分な教育を受けていないためなのか、それとも優れたプログラミング仕事をするために必要な脳の部分を持ち合わせていないためなのか、わからないのだ。ポール・グレアムは彼らをほげプログラマと呼んでいる。

Javaスクールが優れたプログラマになり得ない学生をふるい落とせないのは十分まずいことだが、大学からすれば彼らの問題ではないと言えるだろう。産業界や、少なくともgrepを使っているリクルーターはJavaが教えられるべきだと要求しているのだ。

Javaスクールは良いソフトウェアデザインをするための巧みさ、機敏さ、柔軟さを身につけられるように学生の頭を鍛えることにも失敗している(ここで言うデザインは、オブジェクト階層をいじって際限なくコードを書き換えたり、has-a対is-aのような似非「問題」に思い悩むOO「デザイン」とは違う)。デザイナには同時に複数の抽象レベルで考える訓練が必要であり、そのような思考は優れたソフトウェアアーキテクチャをデザインする上で不可欠なものなのだ。

オブジェクト指向プログラミングが、ふるい分けの手段としてポインタや再帰のかわりになると思うかもしれないが、端的に言って、答えはノーだ。それはOOPのメリットがどうという話ではなく、単に凡庸なプログラマをふるい落とすのには簡単すぎるということだ。大学で教えるOOPというのは「カプセル化」とか「継承」といった用語をたくさん暗記したり、ポリモーフィズムとオーバロードの違いについての多岐選択クイズに答えることからなっている。これは歴史の授業で有名な年号や人名を暗記するのよりさして難しいわけではない。OOPは大学一年生を追い払う知的チャレンジを与えるには不十分なのだ。OOPの問題で躓いても、プログラムは依然として動き、ただ保守性に違いが出るだけだ。聞いたところではね。しかしポインタで躓くなら、そのプログラムはセグメンテーションフォールトを起こすことになり、立ち止まって深呼吸し、同時に2つの異なる抽象レベルで考えようと真剣に取り組むのでなければ、何が起ったのかもわからないだろう。

grepを使うリクルーターが騙されるのには理由がある。私の知るSchemeとHaskellとCのポインタが使える人はみな、Javaを使い始めて2日で経験5年のJavaプログラマよりいいコードを書くようになる。しかしそのことが平均的な頭の鈍い人事部の連中には理解できないのだ。

ではコンピュータサイエンス学科のミッションという点ではどうだろう? 自分たちは職業訓練所ではない! 人々を産業界で働けるように訓練するのが役目ではない。それはコミュニティカレッジとか政府のやっている失業者のための再訓練プログラムですべきことだ。そう彼らは言うことだろう。大学は学生に自分の人生を生きるための基本的な道具を与えるものと想定されているのであって、職場で働きはじめる準備をさせるのが役割ではないのだと。

Cs1.PNG

たとえそうなのだとしても、コンピュータサイエンスというのは証明(再帰)、アルゴリズム(再帰)、言語(λ計算)、オペレーティングシステム(ポインタ)、コンパイラ(λ計算)の話なのであり、結論を言うなら、CもSchemeも教えないJavaスクールというのは、本当のコンピュータサイエンスを教えているとは言えないのだ。関数のカリー化のような実世界では役に立たない概念であっても、コンピュータサイエンスの大学院には前提条件となる。プログラマを作れないのみならず、PhDを取れる大学院生さえ作れないほどカリキュラムのレベルを下げることを、コンピュータサイエンスのカリキュラム委員会の教授たちが許している理由が分からない。いや、待って。分かった気がする。

実際、Javaへの大シフトが起きたときに学会で行われていた議論について調べてみれば、最大の関心事がJavaは教育言語として十分に簡単かということだったのがわかる。

なんてことだ、と私は思った。連中はカリキュラムをもっと簡単にしようとしているんだ! いっそのこと学生にスプーンで食べさせてあげたらどう? ティーチングアシスタントにかわりに試験を受けさせれば、アメリカ学に切り替える学生もいなくなることだろう。あらゆることがより簡単になるようにとデザインされたカリキュラムで、いったい何を学ぶことが期待されているのだろう? タスクフォース(PDF)はJavaの単純化したサブセットを作り、単純化したドキュメンテーションを作り、EJB/J2EEのゴミは学生の傷つきやすい心から注意深く隠され、かつてなくやさしいコンピュータサイエンス問題セットでは使わないクラスのことで小さな頭を悩ませることもない。

コンピュータサイエンス学科が授業を簡単にすることにそれほど熱心なことへのもっとも好意的な解釈は、JavaのintIntegerの違いについて教えるような2つの授業に時間を使わずに済むなら、本来のコンピュータサイエンスの概念について教える時間が多くなるということだ。それなら6.001が完璧な答えになる。教育言語のSchemeはとてもシンプルで、この言語を頭のいい学生に教えるのには10分くらいしかかからない。学期の残りは全部不動点を教えるのに使える。

さてと。

私は1と0の世界に戻ることにしよう。

(1があるって? そりゃ恵まれてるね! 私の頃は0ばかりだったよ。)

あなたが再帰アルゴリズムを数秒で書け、連結リストを操作するポインタを使った関数をホワイトボードに書くのと同じくらい早く実装できる大学3年生なら、私たちのニューヨークでのサマーインターンプログラムをチェックしてほしい! 申し込みの締め切りは2月1日だ。


(オリジナル: The Perils of JavaSchools)

戻る

Personal tools