POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

Uncle Bob

本記事は、原著者の許諾のもとに翻訳・掲載しております。

世界初のプログラム内蔵方式コンピュータに搭載された、最初のプログラムを書くのに使われた言語は何だったでしょうか?

もちろん、バイナリの機械語です。

なぜですか?

えー、当然ながら、シンボリックアセンブラがなかったからです。最初期のプログラムは、バイナリで書かなければなりませんでした。

バイナリの機械語と比較して、アセンブリ言語でプログラムを書くと、どのくらい簡単ですか?

ずっと 簡単です。

数字を言ってください。何倍ぐらい簡単ですか?

えー、まあ、アセンブラは、あなたの代わりに面倒な事務処理を全てしてくれますからね。つまり、全ての物理アドレスの計算です。全ての物理的な命令を構築するわけです。あなたが範囲外にアドレス指定するなど、物理的に不可能なことをしないよう確認します。そして、簡単にロードできるバイナリの出力を生成します。

それによって、軽減されたワークロードは、 膨大 です。

どのくらいですか?数字を言ってください。

分かりました。では、もし私がPDP-8のような古いマシンのアセンブラで、例えば、前から25個の整数の2乗を出力するというような、簡単なプログラムを書かなければならないとしましょう。すると、2時間ぐらいかかるでしょう。もし同じプログラムをバイナリの機械語で書かなければならないとしたら、恐らくその倍かかるでしょう。

2倍 と言ったのは、たぶん最初に紙の上にシンボリックのシンタックスでプログラムを書くからです。そして、その後、そのバイナリコードをコンピュータに手入力しなければなりません。その余分な作業で、恐らくちょうど最初にプログラムを書くのにかかるのと同じぐらいの時間がかかると考えられます。もっと長いかもしれません。

ありがとうございます。では、シンボリックアセンブラを使うと、ワークロードが1/2に減るのですね?

実際、私はもっと減ると思います。整数の2乗は、非常に簡単なプログラムです。もっと大きなプログラムであれば、ハンドアセンブルして、手でロードするのは、もっとずっと大変です。ですから、ワークロードの軽減量に関しては、実際のところ、プログラムサイズの関数だと思うのです。大きなプログラムでは、 多くの 時間を節約できます。

説明をお願いします。

えー、シンボリックアセンブラのプログラムの1行を変更するとします。紙テープを使用する古いPDP-8で20分かかるかもしれません。しかし、もし、ハンドアセンブルする場合は、手で全てのアドレスを再計算し、さらに再度全ての命令をハンドアセンブルしなければならないのです。プログラムのサイズによっては、何時間もかかるでしょう。その後、手でロードするのにさらに数時間かかります。

プログラムをモジュールに分けて、前後にギャップを残すよう指定した固定アドレスにロードすると、ある程度の時間は節約できます。大きなプログラムのロードを楽にする小さめのプログラムを書けば、さらにもう少し時間を節約することができます。しかし、事務処理にかかるワークロードは、それでも非常に多いのです。

分かりました。では、数字を言ってください。平均で、アセンブリ言語はバイナリ言語よりどのくらい簡単ですか?

はい。10倍ぐらい簡単と言うべきでしょう。

では、シンボリックアセンブラを使うと、プログラマ1人でバイナリの機械語を使うプログラマ10人分の仕事ができるというわけですね?

はい。恐らくそんなところです。

シンボリックアセンブリ言語でワークロードが1/10に減ったのであれば、Fortranではどのくらいワークロードが減ったのですか?

えー、まあ、もし1950年代のことを言っているのであれば、Fortranは、当時非常にシンプルな言語でした。つまり、シンボリックアセンブリに関しては、アセンブラとあまり変わらなかったでしょう。お分かりいただけますか?

では、ワークロードがさらに1/10になったということですか?

違いますよ! 記号アセンブラの事務負担は、それほど高くなかったのです。Fortranがそれ以上にワークロードを減らす量は少ないでしょう。恐らく、30%。

では、10人のFortranプログラマは、アセンブリ言語プログラマ13人分の仕事ができるということですか?

そんなふうに考えたいなら、そうです。恐らくそんなところです。

では、Cのような言語では、Fortranのような言語と比較してどのくらい作業量を軽減できますか?

えー、そうだな、えーと、C言語では、Fortranよりは事務処理が軽減されます。古いFortranでは、行番号やCOMMON文の順序のような項目を覚えなければなりませんでした。それに、 go to 文があらゆるところにやたらとありました。C言語は、Fortran 1よりもプログラムしやすい言語です。ワークロードが20%減るかもしれません。

分かりました。では、C言語プログラマ10人で、Fortranプログラマ12人分の仕事ができるわけですね?

えー、これは全て成り行きからの当てずっぽうです。しかし、経験に基づいた妥当な推測でしょう。

ありがとうございます。では、次に、C++ではCと比べてどのくらいワークロードが軽減されましたか?

はい。えー、ちょっと待ってください。もっとずっと大きな影響を無視しそうになっています。

そうですか?何でしょう?

それは開発環境です。1950年代は、パンチカードと紙テープを使っていました。簡単なプログラムをコンパイルするのに、少なくとも30分はかかりました。それも、もしマシンを利用できた場合の話です。しかし1980年代後半にC++が普及し始める頃になると、プログラマはソースコードをディスク上に保存し、簡単なプログラムなら2、3分でコンパイルできるようになりました。

それはワークロードの軽減と言えるのでしょうか。それとも、単に待ち時間が少なくなっただけでしょうか。

なるほど、言いたいことは分かりました。確かに当時は、かなり長い時間マシンの処理を待っていたものです。

それではワークロードを見積る際に、待ち時間は考慮しないでください。言語そのものが、どれだけワークロードを減らせるのかということだけを知りたいのです。

分かりました。さて、C++についての質問でしたね。率直に言って、C++でワークロードが劇的に軽減されたとは思いません。確かに いくらか は軽くなったでしょうが、せいぜい5%程度でしょう。C言語の事務処理のオーバーヘッドはそれほど多くないので、相対的に見て、C++のワークロード軽減の度合いはそれほど大きくありません。

5%ということは、100人のC++のプログラマは、C言語のプログラマ105人分の仕事ができるということですね。妥当ですか?

まあ、そんなところでしょう。でもそれは、小規模や中規模のプログラムの場合に限ります。 大規模な プログラムの場合、C++にはさらに利点があります。

どんな利点ですか?

ちょっと複雑なのですが、要するにそれは、C++がオブジェクト指向であるという特徴、とりわけその多相性という側面のおかげで、大規模なプログラムを分割して個別に開発したり、モジュールをデプロイしたりできることです。巨大な規模のプログラムでは、そのようにして深刻な事務処理のオーバーヘッドを軽減しているのです。

数字で教えてください。

どうしても聞き出すつもりですか…。1980年代、1990年代に開発されていた非常に大きなプログラムを考えると、全体的に見てC++は恐らく、7%程度のワークロードを減らせたのではないでしょうか。

自信が無いようですね。

確かに自信はありませんが、7%ということにしましょう。

分かりました。つまり、100人のC++のプログラマで、C言語のプログラマ107人分の仕事ができるということですね。

そういうことになりますね。その数字でいいでしょう。

Javaでは、C++のワークロードがどのくらい軽減されたでしょうか?

さあ、どのくらいでしょう。少しでしょうね。Javaはよりシンプルな言語です。Javaにはガベージコレクションがあり、ヘッダファイルがありません。また、Javaは仮想マシン上で実行されます。Javaには多くの利点があります(欠点も少々ありますが)。

数字で表すと?

まるで泥沼にはまり込んだみたいですね。しかし、どうしても数字で表せと言うのなら、(あり得ないことですが)他の条件が全て等しいとして、C++の代わりにJavaを使うことでワークロードを5%減らせるでしょう。

つまり100人のJavaのプログラマは、C++のプログラマ105人分の仕事ができるということですね。

そうですが、違います。そうとは言えません。標準偏差が高過ぎます。無作為に選んだJavaのプログラマ100人と、同じように無作為に選んだ105人のC++のプログラマを比較しても、結果は予測できません。本当の利点を知るには、もっと大きな数字が必要です。

どのくらい大きな数字ですか?

少なくとも100倍は大きな規模の数が必要ですね。

ということは、無作為に選んだ10,000人のJavaのプログラマは、無作為に選んだC++のプログラマ10,500人分の仕事ができるということですね。

そういうことですね。

よく分かりました。では、Rubyのような言語ならJavaのワークロードはどのくらい軽減されるのでしょうか。

やれやれ(ため息)。何ですって?いいですか、Rubyは実に優れた言語です。単純でありながら複雑で、エレガントでありながら風変わりです。Javaに比べると非常に遅いのですが、コンピュータはとても安いので…

そんなことは聞いていません。

そうですね。分かりました。Javaのような言語に比べて、Rubyでは主にどんなワークロードが軽減されるかと言うと、それは です。Javaでは型の形式的な構造を作成し、構造の一貫性を維持しなければなりません。Rubyでは、型の扱いはかなりいい加減でもいいのです。

それなら、かなりワークロードを減らせそうですね。

それがそうでもないんです。型の構造をいい加減に扱えることで、Javaのプログラマなら経験することの無い、実行時エラーといった問題に直面することになります。ですからRubyのプログラマは、Javaのプログラマよりも多くのテストとデバッグをしなければならないというオーバーヘッドがあるのです。

ワークロード軽減の効果は相殺されてしまうということですか?

それは、誰に質問するかで答えは変わりますね。

あなたに聞いているのです。

そういうことなら、効果は相殺されません。RubyはJavaに比べてワークロードが軽減されます。

どのくらいですか?20%ですか?

その程度だと考えられていました。実際に1990年代には、SmalltalkのプログラマはC++のプログラマの何倍も生産性が高いと考えられていたのです。

ちょっと分かりにくいですね。なぜ他の言語の話をするのですか?

C++はJavaによく似ていて、SmalltalkはRubyによく似ているからです。

そういうことですか。では、RubyはJavaのワークロードを何倍も軽減したのでしょうか?

いいえ、恐らく違うでしょう。1990年代当時、待ち時間の問題がまだかなり報告されていたことをご存じでしょう。典型的なC++のプログラムのコンパイル時間は何分もかかりました。Smalltalkのコンパイル時間は、うーん、 ゼロ でした。

ゼロですか?

事実上はゼロです。問題は、JavaやC++のような言語は全ての型を調整するために行わなければならない作業がたくさんあるということです。SmalltalkやRubyのような言語では、気にすることはありません。このように、1990年代当時、その時間は数分から数ミリ秒でした。

分かりました。これはあくまで待ち時間の問題なので、無視できますね。

必ずしもそうではありません。もし事実上、コンパイル時間が ゼロ の時は、異なるプログラミング形式や手法が促進されるようになります。 とても 短いサイクルでの作業が可能です。数分ではなく数 です。これにより 非常に 迅速なフィードバックが可能となります。コンパイル時間が長い時には、迅速なフィードバックは不可能です。

迅速なフィードバックが、ワークロードを軽減しますか?

はい、見方によれば。サイクルが極めて短い時には、各サイクルの事務処理のオーバーヘッドは非常に小さなものになります。経過を追跡し続けるのに頭を悩ませる必要はありません。より長いサイクルでは、非線形的に事務処理のオーバーヘッドが増加していきます。

非線形ですか?

はい、事務処理のオーバーヘッドは、サイクルの時間に比例することなく増大します。それはオー記法の計算量 O(N^2) よりも高い値かもしれません。よくは分かりません。しかし、それが非線形だということは断言できます。

では、これで、Rubyがかなり先行しましたね!

いいえ。まさにそこが重要です。この20年で、ハードウェアが格段に進歩したので、Javaのコンパイル時間は、事実上 ゼロ になりました。Javaプログラマのサイクル時間は、もはやRubyプログラマのサイクル時間以下です。(というより長い 必要 はありません)。

話の内容が良く分かりません

「短いサイクルの手法を使うプログラマにとって、JavaとRubyにワークロードの差はほとんど(あるいは全く)感じられない」と言いたいのです。ワークロードにどんな違いがあるのかを測定する意味はないでしょう。

測定できる差は無いということですか?

統計的な差を測定するには、何千人ものプログラマがテストを実行する必要があると思います。

しかし、先ほど、RubyではJava以上にワークロードが軽減されたと言いましたよね。

その通りだと思います。しかし、それはサイクル時間が長い時だけです。もし、編集/コンパイル/テストのサイクル時間がとても短い場合は、その影響は無視できます。

ゼロですか?

いいえ、違います。おそらく、5%程度でしょう。しかし、標準偏差はとてつもなく大きいものです。

ということは、10,000人の短いサイクルのRubyプログラマは、短いサイクルのJavaプログラマ10,500人分の仕事ができるということですね。

サンプル数を10倍すれば、そうだと言えるでしょう。

Rubyよりも出来の良い言語はありますか?

そうですね、Clojureのような言語なら、もうあと5%稼げるかもしれません。とてもシンプルだし、関数型の言語ですから。

関数型言語に見出す価値がたった5%だということですか?

いいえ。短いサイクルの手法が最近の言語の生産性の差分を事実上帳消しにすると、言っているのです。

短いサイクルで作業する限りは、どの最近の言語を使用するかはあまり重要ではありません。

それじゃあ、Swiftは? Dartは?Goは?

差はごくわずかです。

ScalaやF#は?

同じようなものです。

私たちは最高点に到達したと言っているのですね。未来の言語のどれも現存する言語を超えることはないということですね。

必ずしもそうではありません。私が言わんとするのは、収穫逓減点を越えてしまったということです。アセンブラがバイナリに対して1/10であるのと同じような利点を、未来の言語は与えてはくれないでしょう。未来の言語は、現存する言語のワークロードの50%、または20%、いえ10%の軽減さえ実現しないでしょう。短いサイクルの手法は仮想の不可測性の差分を縮小しました。

じゃあ、どういうわけで常に新しい言語が開発され続けているのでしょう?

それは、 聖杯 探しの旅なのです。

ああ、それなら実際のところ、好みの色の問題に過ぎないということですね。