ハッカーの哲学とネットワーク社会の構造(1)Hacker’s Philosophy and the Structure of Network-society.




 Amazonのジェフ・ベゾス、Googleのセルゲイ・ブリンとラリー・ペイジ、Facebookのマーク・ザッカーバーグ、Microsoftのビル・ゲイツ、Appleのスティーブ・ジョブズ、Oracleのラリー・エリソン、Tesla,Space Xのイーロン・マスク、Twitter,Squareのジャック・ドーシー…。

彼らは自らのビジョンのもと、新たな市場を切り開いていった創業経営者です。


 そして、彼らにはもうひとつの共通点があります。


彼らは皆、「プログラマ」出身者であるということです。



 現代はコンピュータの時代です。

身の回りのすべてのものがコンピュータへと変わりつつあります。

そして、現代社会における技術革新の多くの部分がプログラマたちの貢献によって成されています。プログラマたちの仕事抜きでは、現代人の生活は決して成り立たないでしょう。


 プログラマの中でも、特に創造的で、好奇心に溢れ、技術的にも優れ、問題を解決し、物事を築き上げる能力が高いプログラマのことを、プログラマたちは敬意を込めて

ハッカー(hacker)」と呼びます。


コンピュータに侵入し、データを盗んだり、システムを破壊するような行為を行う人間、集団は「クラッカー(cracker)」であり、ここで説明するハッカーとは明確に分けておく必要があるでしょう。


基本的な違いは、ハッカーは新たに創造し、クラッカーは破壊します。


 インターネットが大きな役割を果たしている現代ネットワーク社会を理解し、更にそれに貢献しようとするならば、その起源であるハッカーたちの創造性に触れることは、示唆に富み、あなたにとっても大いに有益で、インスピレーションを刺激し、新たな喜びを知るきっかけにすらなるでしょう。


フリー、シェア、IoT、人工知能、仮想現実/拡張現実、FinTech、暗号通貨、ブロックチェーンなどの新しい概念を理解するためにも、ハッカーの考え方を知っておく必要があります。



 では、ハッカーたちの倫理と哲学、そして彼らの卓越した思考方法によって生み出されたネットワークの構造、それらについて考えてみましょう。


そして、コンピュータの時代にふさわしい形にどのように自社をアップグレードしていくべきなのかを検討していきましょう。




ハッカー精神の偉大な成果、Linux



 あなたは、Linux(リナックス、GNU/Linux)というオペレーティングシステム(OS)をご存知でしょうか?


Linuxは、ハッカーたちによって創られ、育てられてきたOSです。


OSとは、コンピュータを動かすのにあたって最も基本的、中核的な役割を担うソフトウェアです。OSは、ユーザーとハードウェアの間を取り持ち、アプリケーションソフトウェアを使用するにあたってのメモリ(記憶領域)の割り当て、プロセスのスケジューリングを管理します。


 世界で最も有名なOSはWindows(ウィンドウズ、Microsoft)でしょう。

多くの方が、この記事もWindowsを通して読んでいるのではないでしょうか。

それともスマートフォンからこのサイトに入ってこられたのであれば、OSはAndroid(アンドロイド)でしょうか。

または、iPhoneを使っていればiOSでしょう。



 しかし、あなたの端末が何であれ、あなたはおそらく毎日Linuxを利用しています

なぜなら、いまやLinuxはWindowsを圧倒する市場占有率を誇るOSとなっています。あなたは気づかぬうちにLinuxを使っていることでしょう。


 LinuxがWindows以上の市場占有率を獲得しているのは、サーバー(集中処理向けコンピュータ)OS市場とスマホ・タブレットOS市場においてです。


サーバーOS市場においては、Linuxは74%、Windowsは18%(2016年1月時点)の市場占有率となっています。

スマホ・タブレットOS市場においては、Androidが70%以上(2017年6月時点)の市場占有率となっていますが、実はAndroidはLinuxベースで作られているOSです。


Linuxはインターネットの世界で、あなたが見るほとんどのウェブページを提供し、あなたが使うほとんどのアプリケーションを動かしています。GoogleやWikipedia、そしてFacebookもLinuxで動いています。


さらにスーパーコンピュータにおいては90%以上がLinuxをOSとして利用していると言われています。そのことからも機能の信頼性も推し量られるでしょう。



 しかも、Linuxは、無料で自由に使える《フリーソフトウェア》です。


望めば誰でも自分のコンピュータに無償でダウンロードすることができ、完全に自らの管理のもと稼働させることができます。有償の追加サービスに誘導されることも、広告を浴びせかけられることも、自分のLinux上のデータを他者に利用されるようなこともありません。自分の使い方にあわせてカスタマイズすることもできます。そのため、自分のマシンを完全に理解し、自由に使いたいと考えるハッカーたちから支持されました。



 そして、Linuxの特筆すべき点は、その開発マネジメント方法にあります


下の写真は、Linuxの開発本部の写真です。



リーナス・トーバルズ(Linus Benedict Torvalds、1969年12月28日 ー )は今でも自宅の一室でLinuxの開発指揮をとっている。リーナス・トーバルズは、1991年にLinuxの開発をたった一人で自分の趣味として始めた。ネットワーク上でソースコードを公開し、GPL(ジー・ピー・エル、一般公衆利用許諾書/フリーソフトウェアとして誰でも自由に利用できることを保証したライセンス)を採用したことによって、当時著作権の係争で身動きがとれなくなっていたUNIX及び他のUnix系システムに代わって、瞬く間に世界中にユーザーが拡大した。現在でも数千人規模のプログラマたちと、Linuxを協働開発している。モットーは「楽しむこと(Just_for_fun)」。



 サーバーOS市場のチャンピオンであり、世界のAndroid端末15億台上で実際に使われているOSの開発本部は、さぞ大層な施設かと思いきや、Linuxはいまでも開発者であるリーナス・トーバルズの簡素な自宅の一室を中心として開発されています。


しかし、Linuxの開発は、密室で孤立した天才たちによって行われたのではありません。むしろ逆に、公然と大規模にオープンに、情報は世界中に公開・共有されて開発されました。


 はじまりは1991年、当時ヘルシンキ大学の学生であったリーナス・トーバルズの個人的な趣味プロジェクトとしてLinuxは始まりました。個人プロジェクトであったにも関わらず、ごく初期の段階でソースコードが開示されたことによって、飛び入り参加自由の完全に開かれたネットワーク環境を通じて世界各地のプログラマが自主的に開発に加わっていきました。Linuxは、いわば騒々しいバザールのような中で大規模に、混沌すら自らのうちに取り込んで成長し、いわゆる正統な開発チームが舌を巻くスピードで書き上げられていったのです。


インターネットの普及というグローバル規模のネットワーク化の流れに乗って、世界各地のハッカーコミュニティと繋がって加速するLinuxの成長は、Microsoftそしてビル・ゲイツに脅威を感じさせるのに十分なものでした。(ビル・ゲイツの後任のスティーブ・バルマーもCEO就任間もない2001年のインタビューで「Linuxはガンだ」と発言しLinuxへの警戒心を隠さなかった)



 The Linux Foundationの2017年の発表によれば、Linuxの核となる「カーネル」部分のプログラムの開発には2005年公開のバージョン2.6.11以降(正確な開発状況が把握できるのがこのバージョン以降)、1513社の企業に所属する1万5637人の技術者が携わったと公表されています。


いまでも世界各地に散らばった数千人規模のプログラマたちが、自らの自由な時間をプログラミングに費やし、協働しながらソースコードを書き加えていっています。そして、そのために、ソースコードは開示されています。また、各プログラマが書き加えたプログラムは元のプログラムも含めて、第三者に自由に配ることもできます。


 このようなソフトウェア開発の方法は《オープンソース》と呼ばれています。Linuxはオープンソースの代表格です。オープンソースの利点は、誰もが無料で利用・改変できるため急速に進化し、急速に広まることです。



 そしてLinuxは、いまやWindowsにも劣らない、いや汎用性や自由度においては圧倒的に優れ、安定性においても引けをとらない最高峰のOSとして育っていきました。(そしていまも進化を続けています。)


そして誰でも自由に使えて、機能を付け加えたり改変でき、変更を加えたものを自由に再頒布できるオープンソース・オペレーティングシステム「Linux」は世界で最も重要なコンピュターソフトウェアのひとつとなりました。


ひとりのコンピュータオタクの学生の趣味から始まったプロジェクトが世界を変えたのです。



 この偉業を成し遂げるにあたっては、Linuxの根底に流れる、ハッカーの哲学が大きな役割を果たしました。


Linuxの実現を支えたコラボレーション(協働)に基礎を置くハッカーの哲学、倫理について、その起源から見てみましょう。




電脳化のはじまり


PDPー7。DEC(ディジタル・イクイップメント・コーポレーション、Digital Equipment Corporation)が1965年に発売したミニコンピュータ。ケン・トンプソンとデニス・リッチーらは、PDPー7に最初のUNIXを開発、実装した。



 1969年、AT&Tのベル研究所に勤めるケン・トンプソンデニス・リッチーらによってUNIX(ユニックス)というオペレーティングシステムが開発されました。


 開発のきっかけは、ケン・トンプソンが余暇に書き上げ、夢中になっていた「Space Travel(宇宙旅行)」という自作の宇宙シミュレーションゲームが、研究所の大型コンピュータの撤去にともないプレイができなくなるのを避けるために、当時研究所で使われずにいたDECのPDP-7というコンピュータに移植する必要性があったためだと言われています。


移植のために、トンプソン、リッチーと数人の人たちが黒板のうえに、自分たちが快適だと思えるようなプログラミング環境の設計図と、その根幹となるすっきりとした考え方を描いたところから、すべてが始まりました。



UNIX及びUnix系の系統樹。UNIXの移植性の高さと自由度の大きさが、多くの派生的なシステムを生みだすことにつながった。緑色はオープンソース、ピンク色はクローズドソース、オレンジ色は両者の折衷ライセンスとなっている。特にビル・ジョイが開発をとりまとめたBSD UNIXは多くの派生OSを生みだし、UNIXの大きな支流の一つとなった。AppleのmacOSもBSDがベースとなっている。ビル・ジョイは天才的なプログラマとして知られ、vi(UNIX環境で人気の高いテキスト編集プログラム)を一週末で書き上げたなど、数多くの伝説的逸話がある。現在でも使われているUNIXとしてはmacOS、iOS、AIXHPUX、Solarisなどがある(いずれも商用)。また認証を受けていないUnix系としてはLinux(派生OSにAndroid他)やMINIXBSDの派生OS(FreeBSD、NetBSD、OpenBSD、DragonFly BSDなど)、Raspbianなどがある。



 UNIXシステムはケン・トンプソンとデニス・リッチーらによって開発されると、使い勝手の良さとシンプルで美しい設計が熱烈に支持され、また要望があれば無償で大学や研究機関に配られたため、多くのソフトウェア開発チームにも使用され、世界中に広まっていきました。(しかしまだこの段階では、UNIXはあくまでハッカー、研究者、オタクたちの楽園であって、一般的には知る人ぞ知るシステムでした。)


リーナス・トーバルズによるLinuxもUNIXのように使えるOSを目指してつくられたOSです。同じようにUNIXのコンセプトをもとにつくられたOSはFreeBSDなど多種多様に存在します。



 では、なぜUNIXシステムはコンピュータマニアたちの間で、熱狂的な支持を得ることになったのでしょうか?


その理由はいくつか挙げることができますが、まず第1にUNIXが様々なコンピュータに搭載できたという「移植性」の良さがあげられます。そして第2に、システムのユーザーにプログラムのソースコードが開示されていたため「誰でも自由に」各々の用途目的にあわせて新たなプログラムを加えたり改良ができて、さらにそのプログラムをコピーして再配布できた点です。そして、最も重要なことは、UNIXがユーザーたち自らによって開発されたために、特にプログラマにとって「生産性の高いプログラミング環境」を提供できたということでしょう。


初期のユーザーで、開発者の一人でもあるブライアン・カーニハンは著書『The UNIX Programming Environment: UNIXプログラミング環境』の中で次のように述べています。



“UNIXシステムは、数多くの革新的なプログラムや技法をもたらすとはいっても、どれかひとつのプログラムあるいはアイデアでシステムをうまく動かしているのではない。UNIXを効果的にしているのは、プログラミングへのアプローチの仕方、つまりコンピュータ利用の哲学である。この哲学を一言で書きつけることはできない。しかしその核心にあるのは、システムの力というのは、個々のプログラムよりも、それらのつながり方にあるという考えである。UNIXの多くのプログラムは、それぞれ独立に極めて細やかな仕事をする。しかし、他のプログラムと結合すると、汎用的で役に立つツールとなるのである。”


(Brian W. Kernighan, Rob Pike 著、石田晴久 訳、『UNIXプログラミング環境』、アスキー出版、1984、1985)



 多くのハッカーたちが(ブライアン・カーニハンと同じように)、UNIXの存在理由であり最も重要な特性は、プログラムそのものではなくプログラムの「つながり方」、さらに言えばプログラマ同士の「結びつき方」(=コラボレーション)にあると考えました。


環境にあわせて柔軟に対応できる「つながり方」に重きをおく設計思想が、UNIXをプログラマたちのプログラミングツールとして、そしてコラボレーションのためのプラットフォームとして特別なものにしたのです。




UNIXのプログラミング哲学


ケン・トンプソン(左、Kenneth Lane Thompson、1943年2月4日 ー )とデニス・リッチー(右、Dennis MacAlistair Ritchie、アカウント名はdmr、1941年9月9日 ー 2011年10月12日)は1969年にUNIXの原型となるOSを開発した。1972年には、デニス・リッチーはプログラミング言語Cを開発し、それまでアセンブリ言語(各ハードウェア固有の特性に依存する低水準言語)で書かれていたUNIXを高水準言語であるCによって書き換え、システムの移植性を飛躍的に高めた。長い髭からは当時のヒッピー・カルチャーからの影響も感じられる。ハッカー文化とヒッピー文化は既成概念からの脱却を唱える反中央集権的な考え方、自由な気風、多様性への共感など共通点も多い。ケン・トンプソンはUNIXを希望者にはソースコードと共にメディアのコピー代だけで発送し、“Love, Ken.”と添えたという。



 UNIXは、ケン・トンプソンとデニス・リッチーも関わっていたMulticsという重厚長大なOSプロジェクト(頓挫した)から一部のアイデアを「借用」してつくりあげられました。Multicsの巨大なアーキテクチャに対してUNIXはよりコンパクトに、よりシンプルな設計を目指したことから、その名称もmulti(複数の、多くの)に対してuni(単体の)と対比させて名付けられました。


Multicsからアイデアを借りてくるにあたってトンプソンが採用した方法は、後のUNIXの開発者たちへの重要な先例となりました。



よいプログラマは素晴らしいプログラムを書く。偉大なプログラマは素晴らしいプログラムを借りてくる。



このことは、すべてを自らゼロから書き上げるのではなく、すでにあるものにクリエイティブな付加価値をつけることによって、より効率的に優れたプログラムをつくりあげるという、UNIX開発者にとって重要な指針となりました。また「借用」するという考え方は、優れたアイデアは皆で分かち合うことが重要なのだというハッカーたちの基本姿勢とも合致しました。


また、(巨大で複雑な)Multicsの失敗から学んでいたトンプソンとリッチーは、UNIXをシンプルでわかりやすいシステムにしようと努めました。そのことは「シンプルであることは美しい」というハッカーたちの重要な指針を示すことになりました。



 UNIXのプログラム開発に関わっていたマイク・ガンカーズは1994年に、UNIXから得られた経験と、他のUNIXプログラマとの議論を経て、UNIXの哲学を9つの定理に集約しました。


ガンカーズのUNIX哲学(Gancarz,1994,1996)の9つの定理には、「もっとシンプルに」「早めに試作する」「移植性(ポータビリティ)」「梃子(レバレッジ)」「フィルタ」など、プログラマ以外の知識創造に携わる職種の人間にとっても、有益なコンセプトが凝縮されています。




/******** The UNIX philosophy ********/



1.Small is beautiful.  小さいものは美しい。


小さいものには大きいものにはない利点がいくつもある。小さいプログラムはわかりやすく、保守もしやすく、資源の無駄遣いもない。そしてなにより、小さいプログラムはほかのプログラムと組み合わせやすい。小さいプログラムを組み合わせることで、予測のできない将来の課題にも柔軟に対応することができるだろう。未来は思っているより早く来る。



2.Make each program do one thing well. 一つのプログラムには一つのことをうまくやらせる。


ひとつのことに集中することで、不要な部分をなくし、やろうとしていることの本質をつかめる。多機能主義の誘惑は強いが、拡張を続けているうちにプログラムは大きく複雑なものとなり、もともとのコンセプトを見失い本来持っていた魅力も失われてしまうことに注意が必要だ。



3.Build a prototype as soon as possible. できるだけ早く試作する。


状況は刻々と変化する。しかも、まだ誰も試みたことのないことに挑むのであれば、暗闇を手探りで進むようなものだ。ならば、最初からうまくやろうとするより、「最初はうまくいかない」と考えて対処したほうが賢明といえるだろう。早い段階で試作をつくることによって、リスクを減らすこともでき、チームの目標を明確にすることもできる。



4.Choose portability over efficiency. 効率より移植性を優先する。


最大限に効率を重視したソフトウェアは、特定のハードウェア上で動かすことが前提となり、ほかのハードウェアでも動作させることのできる移植性が犠牲となる(すなわち最適化)。逆に移植性を優先すれば、しばしば効率が犠牲となる。しかし、次世代のハードウェアは考えている以上に早く現れ、もっと速く、もっと安価になる。移植性のあるソフトウェアは新しく、より強力なマシン上で動かすことができ、ソフトウェアの性能も向上し成長していく。ソフトウェアが生き残るには、次世代のハードウェアに移植される必要がある。早すぎる最適化、過度な最適化はむしろソフトウェアの寿命を縮める可能性が高い。移植可能なソフトウェアを書こう。



5.Store numerical data in flat ASCII files. 数値データはASCIIフラットファイルに保存する。


ソフトウェアにとって移植性が死活問題であるのと同様に、データにも移植性を持たせる必要がある。動かせないデータは、死んだデータだ。データの移動への障害となるものは、そのデータの潜在的な価値に限界を設けてしまう。データが移動できない期間が長ければ長いほど、その最終的なデータの価値は小さくなる。データはできる限り、ASCIIフラットファイルに保存して、ほかのシステムへの移植性を高めておこう。



6.Use software leverage to your advantage. ソフトウェアを梃子(てこ)として利用する。


プログラムを再利用することで、より効率的に新たなプログラムをつくることができる。既にあるものを、独自に書くことは非常に効率が悪い。自分の仕事に他人の仕事を取り込むことで、先人の成果を活用して、コードの有用性を一段と高めることができる。かつて、科学者アイザック・ニュートンは論敵への書簡で次のように述べている。「私がかなたを見渡せたのだとしたら、それはひとえに巨人の肩の上に乗っていたからです。」



7.Use shell scripts to increase leverage and portability. シェルスクリプトによって梃子の効果と移植性を高める。


UNIXにはシェルと呼ばれるコマンドインタープリンタが実装されている。シェルは一種のプログラミング言語の機能を持っており、ユーザーはシェルを通して、LISP、C、Perl、Python、Ruby、Javaといった高水準のプログラミング言語を使わずともコンピュータを動作させることができる。シェルを用いて作成された簡易プログラムのことをシェルスクリプトと呼ぶ。シェルはコマンド入力によってコンピュータを操作するための日常的なツールではあるが、ソフトウェアの梃子の効果を高めるために最適なツールとなる。シェルの簡易な記述による操作で、他人のつくったプログラムを活用し、目的が達成できるのであれば大いに活用すべきだ。シェルスクリプトを使えば、世界中の人々の仕事を合成することができ、小さな努力で大きな成果を上げられる。



8.Avoid captive user interfaces. 拘束的なユーザーインターフェイスを避ける。


拘束的なユーザーインターフェイスを持ったプログラムは、例えばディスプレイ上から、ユーザーに様々な選択を求める。このことは一見、ユーザーに複数の選択肢、または自由度を与えることで、ユーザーフレンドリーな設計のように思える。しかし、拘束的プログラムは、ユーザーからの回答が返ってくるまで、動作を止めることになる。様々な入力に対応できるようにするために、プログラムも大きくなる。そして、インターフェイスが人間を対象としているため、プログラム同士の結合が難しくなる。それによって拘束的プログラムは「単体型の大きく複雑なプログラム」となってしまうケースが多く、避けたほうが良い。



9.Make every program a filter. すべてのプログラムをフィルタとして設計する。


フィルタはデータがシステムを流れていくときに、いくつかの単純な変換を行うプログラムだ。フィルタは何か入力を読み込み、それに単純な変形を加え、何らかの出力を書き出す。そして、個々の小さいプログラムが他のプログラムと結合することによって、より複雑な処理を可能にする。プログラムがデータそのものを作り出すことはない。単に変更するだけだ。すべてのプログラムをフィルタとして作ろう。



/******************************************/




UNIXの考え方は、常に将来を見据えています。そして、常に変化し続ける世界が想定されています。


 将来は不確実で予測できません。しかし、柔軟であり続けることによって、環境の変化に適応しながら前進することができるという、将来へのアプローチ方法の一つをUNIXは示しています。


 このような考え方が、ハッカーたちのプログラミング哲学でありコンピュータ利用の哲学です。

ハッカーたちは彼らの哲学に従って、小さなプログラムを集め、柔軟なコラボレーションによって環境に応じて結合させることによって、効果的で汎用性のあるソフトウェアを生みだし、成長させていきました。


しかし、ハッカーの領域はソフトウェアだけではありません。彼らはコンピュータそのもの(=ハードウェア)もつくりあげてきました。更に奥深くハードウェアの世界まで潜っていきましょう。



Raspbian(Unix系OS)でシェルを開いた画面。Unix系のOSでは、シェルと呼ばれるコマンド・インタープリンタを通じてコンピュータを制御する。ヴィジュアルで直感的な操作を可能とするGUI(グラフィカル・ユーザ・インターフェイス)環境とは異なり、シェルはCUI(キャラクタ・ユーザ・インターフェイス)環境となっており、コマンドをタイプしてマシンを対話的に操作する。CUIGUIに比べ操作の自由度が高く、プログラミングに適している。シェルのコマンドはls(list)、cat(concatenate)、sed(stream editor)、wc(word count)、vi、awk、grepなど無数のツールからなっており、組み合わせて使うことで大きな成果をあげる。コマンドは、それぞれが過去のハッカーたちのプログラミング作品でもあり、時を超えて引き継がれている。






コンピュータの階層構造と抽象化



 コンピュータは、いままで人類が創り出したものの中で、最も複雑な道具です。


コンピュータの総部品数は数十億個にもなります。ジャンボジェット機の総部品数は、コンピュータ部分を除けば、数百万個です。このことからもコンピュータがいかに複雑な機械であるのかがわかるでしょう。


仮にコンピュータの配線図をすべて描いたとしたら、図書館のすべての蔵書のページを埋めつくしてしまうほど膨大なものになります。


 しかし、コンピュータはとてもシンプルな原則に従って設計されています。そのため、私たちはコンピュータの構造を理解するために膨大な配線図を描く必要はありません。途方もなく複雑なコンピュータを理解し取り扱うために、私たちは配線図を描く代わりに、「コンピュータの階層構造」について理解することで対処することができます。





私たちは、まずコンピュータの複雑な構造をいくつかのモジュール(基本部品)として機能別に分割して考えることによって全体を把握する道筋を得ることができます。


そして、各モジュールの技術的な側面(どのように行うのか?)と、論理的な側面(何をするのか?)を別々に考えることで、各モジュールに対して、それぞれのモジュールのことだけに集中して、全体または他のモジュールとは独立して取り組むことで複雑性に対処することができます。


モジュールの入力と出力を絞り込み、連結部分(インターフェイス)を明確化することによって、モジュール外部からは中身の詳細な設計を意識することなく全体を考え、組み立てることができるのです。


 全体をモジュールに分割して、それらを幾層も積み重ねてコンピュータの階層構造を実現しているのが、人間だけに与えられた特別な能力、つまり物事を「抽象化」して考える能力です。「抽象化」とは、物事の本質的な要素を簡潔な方法でとらえて、それを抜き出し、他の要素とは分離して考えることで、より高次の概念(コンセプト)を創り出すことです。



 ハッカーたちは、「抽象化」という思考方法を用いることによって「コンピュータの階層構造」を幾層も重ねて積み上げ、コンピュータのハードウェアとソフトウェアをデザインし、実装します。


それぞれの階層が抽象化された機能の「ビルディング・ブロック(構成要素)」の組み合わせによって実現されており、一つの機能を実行するビルディング・ブロックが別のビルディング・ブロックと組み合わされて、より複雑な機能を実現します。


下位のビルディング・ブロックの集合体(=モジュール)が、上位の階層を形成するためのビルディング・ブロックとなり、さらにそれらが組み合わされて上位の機能が構成されます。そして階層が重なっていくごとに、システムの能力も増していくことになります。



私たちの使っているコンピュータは上位の階層から順に、おおよそ以下のモジュール、階層によって構成されています。



・プログラミング言語(高水準言語)

・オペレーティングシステム(OS)

・コンパイラ

・バーチャルマシン

・アセンブラ

・機械語

・コンピュータアーキテクチャ

・回路

・論理ゲート



 私たちが普段使っている各種アプリケーションは、プログラミング言語とオペレーティングシステム上に搭載されています。高度な計算処理を行い、色鮮やかなグラフィカル・ユーザー・インターフェイスを持つアプリケーションも、プログラマーたちの優れた抽象化によって幾層にも積み重ねられた、コンピュータの階層構造の上に乗ることによって実現しています。


まるで点と点がつながり線となり、線と線が結び合わさって面となり、そしてさらに立体を構成していくように、ハッカーたちはシンプルなひとつの基本回路から抽象化の糸を織り重ねて、階層構造を織り上げて、システムの有用性や能力を高めてきたのです。




プログラミング言語と機械語



 では実際に、コンピュータの階層構造における最上位の階層であるプログラミング言語のコードから見てみましょう。





 このコードは、ディスプレイ(モニター画面)上に、hello, worldと表示するプログラムのソースコードです。おそらく、プログラミングを学ぶときに誰もが最初に目にするコードです。


このプログラムは、stdio.h(Standard Input/Output header、標準入出力ヘッダー)というライブラリ(関数の集まり)を呼び出し、その中にあるprintf関数を用いてhello, worldとディスプレイに出力する簡単なコードです。このコードは、C言語というプログラミング言語によって書かれており、人が読める記述形式になっています。プログラミングの経験がない方でも、なんとなく読んでも意味が分かるのではないかと思います。


 しかし、hello, worldのように一見すると簡単なコードも、実際には複雑な処理が重層的に組み合わさってコンピュータを動かすことになります。まず第一に、上記のプログラミング言語で書かれたコードをコンピュータは直接理解することができません。


コンピュータが理解して実行できるのは、下記のような0と1、つまりバイナリ(2進法)で記述された機械語(マシン語)のみです。機械語の0と1は、スイッチのONが1、OFFが0、とそれぞれ対応しています。



 機械語は0と1の組み合わせによるビット(bit)、つまり2進法で表現されています。ビットは情報理論を確立した科学者クロード・シャノンによって定義された情報量の最小単位で、 シャノンはあらゆる情報は0と1の組み合わせに置き換えて表すことができることを示しました。(Shannon, 1948)





 Cのようなプログラミング言語は、人が読み書きすることが前提となっているため、コードを読んだり書いたりすることができますが、機械語は0と1の羅列となっているため、読むことも書くこともほとんど不可能です。逆にコンピュータにとっては、私たち人間には厳密過ぎるぐらいに思えるCなどのプログラミング言語も、まだ曖昧で「抽象的」なのです。


元来、コンピュータは厳密な機械です。具体的で明確な指示しか受け付けません。コンピュータに指示を出すのであれば、「00番の装置の記憶している数値の内、48050番のメモリの数値を1に設定せよ」という形での指示を行う必要があります。しかし、hello,worldとディスプレイに出力するために、膨大な量の指示をすべて「00番の装置の…」と書いていたのでは、途方に暮れてしまいます。

そこで、コンピュータの世界の先人達は膨大で厳密な指示を目的ごとにひとまとめにカプセル化して、つまり例えば「ディスプレイにテキストを出力する」といった機能を「抽象化」することによって、様々な機能を人間にもわかりやすく使いやすくコンピュータに備えていったのです。プログラミング言語もそのように抽象化によってつくられた機能のうちの1つです。  



 人間が扱うことが比較的容易なプログラミング言語で書かれたプログラムをコンピュータに実行させるには、コンピュータが直接理解できる機械語へと変換する必要があります。


その変換の工程をコンパイルと呼びます。コンパイルの工程は緻密かつ複雑で、その作業工程はいくつかの抽象化された階層に分けることができるほどです。一般的にコンパイルはコンパイラバーチャルマシンアセンブラの3つの変換器によって実現されます。


コンパイルによって、0と1の機械語に変換されたプログラムは、いよいよソフトウェアからハードウェアの領域へと到達します。



 機械語は、ソフトウェアとハードウェアの境界におけるインターフェイスとなっています。

機械語において、プログラマーの抽象的思考はシリコン上で実行される物理的操作に変換されるのです。


しかし、機械語もまた抽象化されたものであり物理的には存在しません。機械語の中身は、言語規則に基づく記号の集合であり、この抽象的な形式を具現化するには、何らかのハードウェアによって実現する必要があります。




コンピュータアーキテクチャ



 コンピュータの階層構造におけるコンピュータアーキテクチャの階層は、ハードウェア領域の最上位の階層となっています。コンピュータアーキテクチャは、ハードウェア全体の基本設計だと言えます。


ビットに、つまりONとOFFの組み合わせによる命令セットの集まりへと変換されたプログラムは、コンピュータアーキテクチャの構成要素であるCPU(中央演算装置、Central Processing Unit)とレジスタ(CPU内にある演算用の小容量の記憶装置)を用いてメモリ(記憶領域)を操作します。


そして、機械語の命令セットはメモリに格納され、コンピュータが命令を実行するたびにCPUによって読み込まれ、解読、実行されます。メモリは2つの安定状態を持つフリップフロップ回路、クロック回路などから構成されており、入力された0と1のビット情報を回路の状態として記憶します。


プログラムのコードは、データと同様に、コンピュータのメモリに格納され操作されます。これが「プログラム内蔵方式」であり、まさしく「ソフトウェア」の正体です。プログラム内蔵方式というアイデアによって、同じハードウェアであっても別のプログラムを読み込むたびに、計算機、通信、グラフィックデザイン、ワードプロセッサ、ゲームなど様々な仕事を行うことができる万能性をコンピュータは獲得しました。




数学者ジョン・フォン・ノイマンは1945年、プログラム内蔵方式のコンピュータアーキテクチャを発表した。以降、プログラム内蔵方式のコンピュータを「ノイマン型コンピュータ」と呼ぶようになり、現在ではほとんどすべてのコンピュータがノイマン型コンピュータのアーキテクチャでつくられている。ノイマン型コンピュータの理論上の原型となっているのが、数学者アラン・チューリングが1936年に考案した仮想の計算機、「チューリングマシン(万能機械、Universal Machine)」である。



 上記のコンピュータアーキテクチャのモデルは「ノイマン型コンピュータ(von Neumann machine,1945)」と呼ばれ、今日のコンピュータのほとんどすべてがノイマン型コンピュータです。

ノイマン型コンピュータは、CPUを中心としてメモリを操作し、入力デバイスからデータを受け取り、出力デバイスへデータを送信します。


CPUは、コンピュータアーキテクチャの中心的存在で、その役割は、現在読み込まれているプログラムの命令を実行することにあります。CPUは、演算を行うALUと、命令コードを解読する制御ユニット、小型の記憶装置であるレジスタで構成されています。


そしてメモリは、命令コードとデータを記憶し、CPUからのアクセスを受け入れ、演算に応じて読み込み、書き換えられます。


 これらCPU・レジスタ・メモリなどのハードウェア、すなわちコンピュータアーキテクチャの各構成要素も、さらに下の階層の回路集合が抽象化されることによって実装されています。




論理回路とNANDゲート



 コンピュータアーキテクチャにおけるCPU、メモリなどの各モジュールの中身は多種多様な回路が集積して構成されています。

さらに、それらの回路はすべて、たったひとつの回路、「NANDゲート」の組み合わせから作り上げることが可能です。

NANDゲートとは、論理ゲートと呼ばれる基本回路のうちの一つで、いかなる組み合わせの論理回路もNANDゲートの組み合わせで実装することができます。


 論理回路とは、二進法の1と0を、電圧の正負や高低、位相の差異、パルスなどの時間の長短など通常電気的な信号によって表現して論理演算を実装した回路のことです。(しかし論理回路を実装するにあたっては、必ずしも電気信号を用いる必要はなく、水流であったり糸と棒やバネなどでつくることもできる。水路の開閉や、バネの伸縮で二進法を表現することによって、水流式コンピュータやバネ式コンピュータなども実現可能。)

論理回路は、与えられた(1または0の)入力に対応する(1または0の)信号を出力します。

つまり、プログラミング言語によってコンピュータに入力された“ 私たちの思考 ”は、論理回路上で物理的な力へと変換されるのです。





 ビットを情報量の単位として定義したクロード・シャノンは、いかに複雑な論理演算であってもONとOFFの2つの状態を切り換えられるスイッチング回路を組み合わせることによって実装できることを示し(Shannon, 1937)、コンピュータ設計技術を大きく前進させました。


シャノンは、19世紀の数学者ジョージ・ブールのブール代数をコンピュータサイエンスに応用することで、現在の形のデジタルコンピュータを実現するための基礎をつくったのです。


ジョージ・ブールによって提唱されたブール代数は、論理学における「真」と「偽」の命題論理を、論理式という数学の形式で表現することができます。シャノンらはブール代数における、ある論理集合の命題における「真(true)」と「偽(false)」の判定を、1と0のビットの演算に置き換えることによってコンピュータサイエンスに応用しました。



 ブール関数の演算においては、単項演算子であるNOT(論理否定、¬A、Aではない)と二項演算子であるOR(論理和、A∨B、AまたはB)AND(論理積、A∧B、AかつB)などの演算子を用いて様々な論理式の真偽を演算します。


NOT、OR、ANDの演算子は、現代コンピュータにおいては、トランジスタと呼ばれるスイッチ素子を特定の配線経路でつなぎ合わせた基本回路となっています。これらの基本回路は基本論理ゲートとも呼ばれ、組み合わせることによってより複雑な論理ゲート(論理回路)を実装する際の部品(ビルディング・ブロック)として使われます。


コンピュータのCPU、メモリなどすべての回路は、NOT、OR、ANDの基本回路を用いて実装することが可能です。

そしてNOT、OR、ANDの回路は、NAND(否定論理積、¬(A∧B)、「AかつB」ではない)だけを組み合わせてつくることができます。



NOT A = A NAND A


A OR B = ( NOT A ) NAND ( NOT B )

= ( A NAND A ) NAND ( B NAND B )


A AND B = NOT ( A NAND B ) = ( A NAND B ) NAND ( A NAND B )



コンピュータの階層構造の最深部は、このNANDゲートです。



 コンピュータの階層構造はNANDゲートの組み合わせによる回路から積み上げて、コンピュータアーキテクチャを構成し、その上にいくつかの変換器とOSとプログラミング言語からなるソフトウェアを実装することによって成り立っています。コンピュータをつくりあげているのはNANDゲートと抽象化です。


たった一種類の単純な回路から、コンピュータをつくりあげているのは、人間だけが持つ「組み合わせによって高次のコンセプトを創り出すことができる抽象化の力」に他ならないのです。


また、哲学者アリストテレスからの論理学の系譜が数学者ジョージ・ブールを経て、情報理論のクロード・シャノンによってコンピュータの一部として取り込まれていることは、コンピュータを考える上でとても興味深いことだと思います。




ループと再帰、そしてアルゴリズム


PINK FLOYDの4thアルバム『Ummagumma』(1969)のアルバムジャケット写真。 壁にかけられた絵の中で再帰的にイメージを繰り返す手法を用いて描かれている。あたかも無限に続くかのような連続したイメージが、視覚的にサイケデリックな効果を与える。日常の光景の中に、現代的なコンセプトが垣間見れる印象的なデザインとなっている。



 さて、コンピュータの階層構造の最深部まで到達したところで、表層部であるプログラミング言語の層まで戻ってきましょう。

ここまでにコンピュータの構造に少し触れることができました。それはNANDゲートという論理回路を最小の基本パーツとして、抽象化によって機能を積み上げた建築物のようなものでした。



では、果たしてコンピュータは何ができるのでしょうか?



汎用コンピュータは、プログラム内蔵式のアーキテクチャのおかげで、様々な用途に合わせて使える万能性を有しています。コンピュータは理論上、CPUの速度、メモリの容量という物理的な制限はあるものの、問題を解く手順を記述できればどのような計算も解くことができます。


 私たちはコンピュータをプログラムを実行させることによって動かします。プログラム次第でコンピュータは多様な仕事を行うことができます。しかし、どんなに複雑なプログラムであっても、プログラムを細かく分解してみれば、たった3つの基本制御構造の組み合わせで作られています。



<プログラムの基本制御構造>


順次: 処理を順番に実行する


分岐: 条件により処理を場合わけする


反復: 処理を繰り返し実行する


 特に、コンピュータは私たち人間と比べて「反復」が圧倒的に得意です。反復、繰り返しはループ(loop)とも呼ばれ、高水準言語の多くではfor文、while文という構文が用いられます。コンピュータは与えられた仕事をひたすら何度でも正確に繰り返すことができます。

 しかし、ループだけではコンピュータの特殊な能力を実現するには足りません。例えば、水車や風車などもループ処理を行っています。コンピュータがただひたすら繰り返すだけの他の機械装置と本質的に異なる能力を実現するには、繰り返し処理の方法の中でも、ハッカーたちが特別な愛着を持つプログラミング手法である「再帰(さいき、recursion)」という方法、そして考え方が必要になります。


 再帰プログラムは、関数の中に同じ関数を組み込んで、元の関数の演算の中に反復的にまるで“合わせ鏡”のように同じ関数を再び呼び出します。そして、またその関数の中に同じ関数を呼び出し、またその関数の中に…といった具合に、延々と繰り返します。そして、あらかじめ定めておいた折り返し地点まで演算を進めると、再び元の関数まで戻りながら演算処理を仕上げていきます。



数式にすると次のような式 f (x) を含むプログラムが、再帰プログラムです。


  x ≧ 1 のとき,

   f (x) = x・ f (x - 1) ・・・①

  x = 0 のとき,

   f (0) = 1 ・・・②


    (ただし、x ≧ 0 とする)



 このように、あるものを定義をするのに、その定義の中に自らを含んでいる形式を、再帰的であると言います。 

(この形式は、そのまま数学における無限の定義とも一致する。(Dedekind,1888))


例えば、xが5のとき、f(5)の解を求めるには①式からf(x - 1)、つまりf(4)を求める必要があります。しかし、f(4)の解はまだ不明なため、①式に再び4を代入すると、さらにf(3)を求める必要があります。同様にf(3)からf(2)、f(1)と降りていき、折り返し地点であるf(0)まで到達すると②式よりf(0)は1となり、そのまま一挙にf(1)、f(2)…f(4)、f(5)の解が明らかになります。


xに代入する数は、どんなに大きくても構いません。どんなに大きい数であったとしても試行を重ねf(0)にたどりついて、また再びもとのところまで戻っていきます。

つまり再帰式はあらゆる特殊なケースを、ひとつのやり方を繰り返し適用することによって、一般化していると言えます。帰納や数学的帰納法、連続や無限に対処するために数学者たちが用いた考え方とも本質的に同様の方法です。



 ループプログラムは一方向に直線的な繰り返しを、再帰プログラムは循環するサイクル運動を実行、出力します。 






 「ループと再帰」がコンピュータにもたらす特別な能力は、まず第1に、ループと再帰というプログラムを使うことによって、コンピュータは有限の記号の組み合わせから「無限」の演算を行うことが可能になります。

ループと再帰は、人間があらかじめ終わりを指定しない限り、延々と終わりなく演算処理を続けます。これは無限ループと呼ばれ、実際に無限ループを実行するとコンピュータの暴走を招く可能性があるためプログラムエラーとして扱われることもありますが、優れたプログラミングによって無限の連続性をコントロールすることによってコンピュータは私たちの意図や思考あるいは認知を拡張、増幅することができます。

(コンピュータはプログラムを書くことさえできれば、あの小さなモニター上に、無限遠の彼方まで、悠久の先までシミュレーションすることができる。制約があるとすれば、それは理論上の制約ではなく、あくまで物理的な制約、あるいは人間の想像力の限界という制約である。)

 そして、与えられたデータを反復的に演算処理することによって、つまり外部から与えられたデータをもとに出力を返し、その結果改めて入力されたデータから再び調整された出力を返すことによって(再帰的に処理することによって)、無限のバリエーションの配列を生成することもできます。

(バリエーションとは、つまり変化だ。再帰的方法で対処することによって、コンピュータは個々の状況にあわせて対応を変化させることができる。)


 有限個の記号の集合から無限の連続性とバリエーションを生み出すことを可能にする「ループと再帰」は、コンピュータを他の機械装置とは全く異なるものにしています。その違いは、処理を自律的に制御して自動化する能力の有無です。この能力は、外部からの入力を再帰的に処理して(入力にあわせて調整して)出力することを繰り返すことによって(つまりフィードバックによって)、もたらされる能力です。人によってはその能力や実行プロセスのことを「知能」とか「思考」と呼んでいます。


 第2に、ループと再帰は、同じ処理を何度も繰り返すので、そこで生成される構造や表現は対称性(シンメトリー)を有することになります。対称性は美術、音楽、建築などでも多用され、美しさを印象づけるのに効果的な要素だと言われています。また、雪の結晶や植物の葉脈の模様のような、全体から部分構造への再帰的な繰り返しは、自然の秩序の中にも多くみられます。対称性は、普遍的真理が兼ね備えている「簡潔さ」に到達する方法の、重要な要素のひとつなのです。


 プログラマたちはループや再帰などの制御構文、そのほか多種多様の関数を用いて、目的に応じて問題を解くための手順、算法をプログラミングしてコンピュータに内蔵します。

この問題を解くための手順、算法を「アルゴリズムalgorithm)」と言います。

アルゴリズムはコンピュータが情報を処理するための指針となります。アルゴリズムがコンピュータが特定の仕事を行うためのステップを指示しているのです。

 そして演算処理の対象となる情報、データをコンピュータで効率的に扱うために、どのように系統立てて格納するか、それぞれの「データ構造data structure)」を設計し、整理します。代表的なデータ構造には、リスト、木、スタック、キュー、グラフなどがあります。


 データ構造の中には再帰的な構造というものもあります。再帰的なデータ構造とは、あるデータの構造の中に、同様の構造を持つデータが含まれている構造のことです。再帰的データ構造の具体例には、ファイルシステムの木構造(tree structure,木が幹から枝葉に分かれていくような構造。データファイルの中にいくつかのファイルがあり、そのファイルの中にもまたさらにいくつかのファイルがあるというような、お馴染みの構造)などがあります。再帰的データ構造を持つデータの処理には、再帰的なアルゴリズムが有効なケースが多いでしょう。

 人間の使う自然言語も再帰的な木構造となっていて、自然言語を表現したり、解析するためには再帰的なプロセスが欠かせません。高水準プログラミング言語(CやJavaなど)を機械語にコンパイルする際の構文解析にも再帰的処理が欠かせません。

 再帰的構造は数学や自然科学上も深淵な意味を持っており、多くの科学的成果の土台になっています。

 プログラマは、まずどのように情報を扱うのかデータ構造を決め、そのデータ構造に応じてアルゴリズムを書き、データを目的に応じて有用な形に変換します。そして、データ構造とアルゴリズムの組み合わせのことを「プログラム(program)」と呼びます。 



迷路のデータを指定すると、アルゴリズムが入口から1マスずつ進みながら、再帰的に次に進める方向を条件判定し、出口までの道筋を探索するプログラムの実行プロセスを図示したもの。ソースコードは、迷路のデータ部分を含めてわずか32行のシンプルなプログラムだが、当然、迷路の形が変わっても、サイズが大きくなっても、アルゴリズムは同じように迷路を探索し、入口から出口までの道筋を出力する。ただし、出口に辿り着けない迷路であればエラー出力する。



 ハッカーたちは、美しくシンプルなアルゴリズムを書くことを尊び、素晴らしいプログラムによってコンピュータを効果的に動かすことが彼らの目的であり使命だと考えています。そして、ハッカーたちの書くアルゴリズム、そしてプログラムは核心的で無駄がなく、時に芸術性を帯びていることすらあるのです。



<よいアルゴリズムの要件>


1.信頼性が高いこと

  精度のよい、正しい結果が得られなければならない。


2.処理効率がよいこと

  計算回数が少なくて済み、処理スピードが速くなければならない。


3.一般性があること

  特定の状況だけに通用するのではなく、多くの状況においても通用しなければならない。


4.拡張性があること

  仕様変更に対し簡単に修正が行えなければならない。


5.わかりやすいこと

  誰が見てもわかりやすくなければならない。わかりにくいアルゴリズムはプログラムの保守(メンテナンス)性を阻害する。


6.移植性(Portability:ポータビリティ)が高いこと

  有用なプログラムは他機種でも使用される可能性が高い。このため、プログラムの移植性を高めておかなければならない。


(河西朝雄、『C言語によるはじめてのアルゴリズム入門』、技術評論社、1992、2017)



 ハッカーたちは今も、人間独自の「抽象化」という思考方法を用いて、アルゴリズムとデータ構造からつくった小さなプログラムを組み合わせることによって、現実世界の課題を解決するアプリケーションを、コンピュータの階層構造のプログラミング言語層のさらに上に積み重ねているのです。


そしていま、ハッカーたちが創り出す新たなアプリケーション、そしてシステムが《ニューエコノミー》と呼ばれる新しい産業構造を形成しつつあります。




>続きを読む