UNIX哲学

ソフトウェア設計方針

UNIX哲学とは、ソフトウェア開発に関する文化的な規範と哲学的アプローチのまとまりであり、UNIX OSの開発者たちの経験に基づくものとされている。 その内容は、発言者によって異なるが、以下の点に留意が必要である。

  • いずれもUNIXが開発された1971年から10年以上が経過してからなされた発言が大半である
  • 発言者には、UNIX開発との関わり合いが希薄な人物も含まれている
  • UNIXを生み出したケン・トンプソンデニス・リッチーは"simplicity"や"easy to use"といった標準的な用語しか用いておらず、"哲学"(philosophy)という表現をしていない
  • 商用UNIXには大規模で多機能なアプリケーションソフトウエアーが含まれている場合がある

すなわち、"UNIX哲学"が、一貫したものとして当初から存在し続けているわけではなく、UNIXに関わる全ての人に共通認識として受け入れられているわけでもなく、UNIXの置かれている現在や過去の状況を必ずしも的確に表現し得ているわけでもない。また、そこで表現されている手法の妥当性や有効性が、普遍的に立証されているわけでもない。

ある意味では、"UNIX哲学"とは、UNIXに関心を示す人々のうちの一部が抱く、希望や願望あるいは理想を表明したものにすぎない。

起源編集

Unixの哲学は、1978年のBell System Technical Journal[1]ダグラス・マキルロイ[2]他によって記載されている。

  1. それぞれのプログラムが1つのことをうまくこなすように。新しい仕事をするために、新しい「機能」を追加して古いプログラムを複雑にするのではなく、新しいプログラムを構築する。
  2. すべてのプログラムの出力が、まだ見ぬ別のプログラムの入力になることを期待する。出力に余計な情報を入れないように。厳密に列挙された入力形式やバイナリ形式は避ける。インタラクティブな入力にこだわらない。
  3. ソフトウェアはもちろん、OSであっても、早期に、理想としては数週間以内に試せるよう設計・構築する。不器用な部分は躊躇なく捨てて、作り直すように。
  4. 回り道をしても、使い終わった後に捨てることになっても、プログラミングの作業を軽減するためには、お手伝いさんではなくツールを使う。

その後、en:Peter H. Salusが『A Quarter-Century of Unix』(1994年)[2]にまとめている。

  • 一つのことをうまくやるプログラムを書く。
  • 連携するプログラムを書く
  • 普遍的なインターフェースであるテキストストリームを扱うプログラムを書く。

1974年のUnix論文[3]で、ケン・トンプソンデニス・リッチーは以下のような設計上の考慮事項を述べている。

  • プログラムを書いたり、テストしたり、実行したりするのが簡単に行えるようシステムを設計しました。
  • 当初のバージョンでは1人のユーザーしかサポートしていませんでしたが、システムをインタラクティブに使用できるようにしました。
  • 適切に設計された対話型システムは、「バッチ処理」システムよりもはるかに生産的で満足のいくものであると信じています。
  • サイズの制約は、経済性だけでなく、デザインのある種の優雅さを促してきました。これは、もしかしたら「苦難による救済」という哲学の薄っぺらなバージョンかもしれませんが、私たちの場合はうまくいきました。
  • すべてのUnixソフトウェアはUnixの下で保守されています。

マキルロイ: UNIXの四半世紀編集

パイプの発明者でありUNIX創始者の一人でもあるマキルロイは、この哲学を以下のように要約した。

これがUNIXの哲学である。
一つのことを行い、またそれをうまくやるプログラムを書け。
協調して動くプログラムを書け。
標準入出力テキスト・ストリーム)を扱うプログラムを書け。標準入出力は普遍的インターフェースなのだ。 — ダグラス・マキルロイ、UNIXの四半世紀

この哲学はしばしば、「一つのことを、うまくやれ」とさらに厳格に要約される。

3つの教義のうち第3のものだけがUNIX特有であるが、UNIXの開発者はしばしば3つの教義すべてを他の開発者よりも重要視する。

パイク: Cプログラミングに関する覚え書き編集

(注意: これは直接にはUNIX哲学ではない。強い結びつきのあるC言語についての記述ではあるが。現在英語版のこの記事には、この節に対応する節はない)

ロブ・パイクNotes on Programming in C [4]の中で、以下のようなルールをプログラミングの格言として提案している。これはまたUNIX哲学のポイントとも共通点がある。

  • ルール1: プログラムがどこで時間を消費することになるか知ることはできない。ボトルネックは驚くべき箇所で起こるものである。したがって、どこがボトルネックなのかをはっきりさせるまでは、推測を行ったり、スピードハックをしてはならない。
  • ルール2: 計測すべし。計測するまでは速度のための調整をしてはならない。コードの一部が残りを圧倒しないのであれば、なおさらである。
  • ルール3: 凝った(Fancy)アルゴリズム が小さいときには遅く、 はしばしば小さい。凝ったアルゴリズムは大きな定数を持っている[5] が頻繁に大きくなることがわかっていないなら、凝ってはいけない( が大きくなるときでさえ、ルール2が最初に適用される)。
  • ルール4: 凝ったアルゴリズムはシンプルなそれよりバグを含みやすく、実装するのも難しい。シンプルなアルゴリズムとシンプルなデータ構造を使うべし。
  • ルール5: データはすべてを決定づける。もし、正しいデータ構造を選び、ものごとをうまく構成すれば、アルゴリズムはほとんどいつも自明のものになるだろう。プログラミングの中心は、アルゴリズムではなくデータ構造にある。
  • ルール6: ルール6は存在しない。

パイクのルール1と2は、ドナルド・クヌースが述べた格言「早すぎる最適化は諸悪の根源である」を言い換えたものである(最適化 (情報工学)#最適化する時期も参照)。ケン・トンプソンはパイクのルール3と4を「疑いがあるときは総当たり(brute force)を使え」と言い換えている。ルール3と4はデザイン哲学KISSの例である。ルール5はフレッド・ブルックスが以前に「人月の神話」の中で述べている。ジョン・ベントレーの Programming Pearls は同じデザイン原則について述べた章を含んでいる。ルール5はしばしば「スマートなデータを使うつまらないコードを書け」と短縮され、また「データ構造が十分に良いものなら、それを扱うアルゴリズムは平凡であるべきだ」というガイドラインの実例でもある。ルール6はモンティ・パイソンの「ブルース・スケッチ」を愉快に参照しているだけのものだ。Cの文字列では最後の1バイトがヌル文字であり、したがってその文字列の長さを示すことになる[要出典]

ガンカーズ: UNIXの哲学編集

1994年、マイク・ガンカーズ(X Window System開発チームの一員)は、UNIXで得た経験と、同僚プログラマーやUNIXに依存する他分野の人々との議論を活かし、以下の9つの至上命令に集約される「UNIX哲学」を創出した。

  1. スモール・イズ・ビューティフル(小さいものは美しい)
  2. 各プログラムが一つのことをうまくやるようにせよ
  3. できる限り早く試作せよ
  4. 効率よりも移植しやすさを優先せよ
  5. 単純なテキストファイルにデータを格納せよ
  6. ソフトウェアを梃子(てこ)として利用せよ
  7. 梃子の効果と移植性を高めるためにシェルスクリプトを利用せよ
  8. 過度の対話的インターフェースを避けよ
  9. すべてのプログラムをフィルタとして設計せよ

以下の重要性が相対的に低い教義は、UNIX哲学の一部として普遍的に合意されるものではなく、場合によっては現在も激しく議論されているものである(例えばモノリシックカーネルマイクロカーネルのように)。

  1. 好みに応じて自分で環境を調整できるようにせよ
  2. OSのカーネルは小さく軽量にせよ
  3. 小文字の短い名前を使え
  4. 森林を守れ
  5. 沈黙は金なり
  6. 並行性を考えよ
  7. 部分の総和は全体よりも大きい
  8. 90パーセントの解決を模索せよ
  9. 劣るほうが優れている(より悪いことは、より良いことだ)
  10. 階層的に考えよ

より悪いことは、より良いことだ(Worse is better)編集

リチャード・P・ガブリエルは、UNIXの重要な優位性のひとつは彼が「より悪いことは、より良いことだ」("Worse is better")という用語に込めるデザイン哲学を体現しているところにあると述べている。「より悪いことは、より良いことだ」式のデザイン・スタイルでは、インターフェースと実装の両面がシンプルであることが、システムにおける他のいかなる特性よりも重視される――正確さ、堅牢さ、完全さよりも、である。ガブリエルは、このデザイン・スタイルが発展のための重要な利点を持っていると論じているが、一方でいくつかの結果の質について疑問を抱いてもいる。

例えば、黎明期のUNIXにおいて、プロセスはカーネル・システムコールをすべてユーザスタック上で実行した。もしカーネル内で長期間のI/Oやsleepによってプロセスがブロックしているときに(例えばsleep(10*60)のように)、そのプロセスにシグナルが通知されたら、何が行われるのだろうか? シグナルはI/Oが完了するまでの間(どれくらいかわからないが、おそらく長い間)遅延されるのか? プロセスがカーネルモードで動いている場合、シグナル・ハンドラは実行され得ず、スタックには繊細なカーネル・データが残ったままである。カーネルはシステムコールを棄却(バックアウト)し、応答と再始動に備えて保管し、成功裏にシグナルハンドラを完了することを引き受けるべきなのか?

このようなケースでは、ケン・トンプソンデニス・リッチーは完全性よりもシンプルさを好む。UNIXシステムは機会ごとにシステムコールから素早く復帰し、何もしなかったことを知らせるエラー通知(「Interrupted System Call システムコールに割り込みが発生」)を行う。すなわちエラー番号4(EINTR)である。もちろん、このような呼び出しはシグナルハンドラを呼び出すために中断されている。こうしたことは、長期間実行されうる一群のシステムコール(つまりread()write()open()select()等)において起こり得る。利点としては、この仕組みはI/Oシステムを何倍もデザインしやすく、理解しやすいものにしている。圧倒的多数のプログラムは影響を受けない。なぜならこうしたプログラムはSIGINT/^C以外のシグナルを扱わず、経験もしないし、SIGINTが発せられたときには正確に終了(die)するからである。それ以外の少数のプログラム(ジョブ制御のキー入力を受け付けるシェルやテキストエディタのようなもの)のためには、システムコールの小さなラッパー(wrapper)を追加することができ、EINTRエラーが起こったらすぐにシステムコールを再試行できるのである。問題はシンプルな方法で解決される。

(現在のUnixクローンでは、カーネルコードがユーザスタックで実行されたりしないし、I/O中のシグナルについて、このようなふるまいであったのは、初期のUNIXやSystemV(あるいは初期のLinux)においてのことである。4.3以降のBSDや現在のLinuxでは、全くI/Oが進行していない状態でシグナルが入った場合、シグナルの処理が終わった後、中断されたI/Oが再開される)

レイモンド: UNIXプログラミングの技法編集

エリック・S・レイモンドは著書『The Art of UNIX Programming』[6]の中で、UNIX哲学を "Keep it Simple, Stupid" (KISS原則、「シンプルでつまらないものに保て」)という、広く使われている工学哲学として要約した。そしてレイモンドは、彼がいかにこの総体的な哲学がUNIXの文化的規範として適用されていると信じているか述べている。だが以下のルールに深刻に違反した例が実際のUNIXの実践において簡単に発見できるのも驚くべきことではない。

モジュール化のルール
クリーンなインターフェースで接続されるシンプルなパーツを書け。
プログラムは、単純な部品同士を、しっかり目の定義を持つインターフェースでつなぎ合わせたものとして書かれるべきです。そうすれば、問題は局所的なものとなり、プログラムの一部は将来のバージョンで新機能をサポートするために交換することができます。このルールの狙いは、複雑で長くて読めないコードをデバッグする時間を節約することにあります。
明瞭さのルール
明瞭さは独創性よりも良い。
開発者が最も意志疎通を図るべき相手はコンピュータではなく、プログラムを読み、保守を行う自分を含めた開発者であるかのようにプログラムを書くべきです。このルールは、将来そのコードを扱う人にとって、コードが読みやすく、理解しやすいものにすることを目的としています。
合成のルール
他のプログラムと接続できるようプログラムをデザインせよ。
開発者は、他のプログラムと簡単に通信できるプログラムを書くべきです。このルールは、開発者がプロジェクトを、過度に複雑な一枚岩のプログラムではなく、小さくてシンプルなプログラムに分解することを目的としています。
分割のルール
ポリシーをメカニズムから分離せよ。インターフェースをエンジンから分離せよ。
開発者は、プログラムのメカニズムとプログラムのポリシーを分離する必要があります。一つの方法として、プログラムをフロントエンドのインターフェースと、そのインターフェースが通信するバックエンドのエンジンに分ける等があります。このルールは、メカニズムを崩さずにポリシーを変更できるようにし、結果的にバグの数を減らすことを目的としています。
シンプルさのルール
シンプルさを求めてデザインせよ。複雑にしなければならない場合に限り、複雑さを加えよ。
開発者はシンプルなデザインを心掛けるべきです。プログラムを小さく分かりやすい協調性を持ったピースに分割する方法を模索してください。このルールは、開発者が「緻密ちみつで美しく複雑な」実際にはバグだらけのプログラムを書いてしまうことを防ぐためのものです。
倹約のルール
大きなプログラムを書くのは、他に何もできないことが実証された場合のみ。
開発者は大きなプログラムを書くことを避けるべきです。失敗もしくは妥協的アプローチへの開発時間の過剰投資を防ぐことが、このルールの目的です。これらは膨大な作業の数々を破棄したくないというプログラム所有者の気持ちが原因でおこります。小さなプログラムは、最適化やメンテナンスが容易であるだけでなく、廃棄する際も削除が容易です。
透明性のルール
透明性を求めてデザインせよ。調査とデバッグが簡単になる。
開発者は、将来そのプロジェクトに参加する開発者が、自分の思考プロセスを明瞭に見ることができるように書き、有効な入力と正しい出力を容易に識別できる入出力形式を使用することによって、可視性と発見性を設計する必要があります。このルールにより、デバッグにかかる時間を短縮し、プログラムの寿命を延ばすことを目的としています。
頑丈さのルール
頑丈さは透明性とシンプルさから生まれる。
開発者は、透明性と発見力を高める設計をすることで、堅牢なプログラムを設計する必要があります。なぜなら、理解しやすいコードは、複雑なプログラムでは予見できないような予期せぬ状況に対してストレステストを行いやすいからです。このルールは、開発者が堅牢で信頼性の高い製品を構築できるようにすることを目的としています。
代表のルール
知識をデータに織り込め。するとプログラムのロジックをつまらなくて頑丈なものにできる。
開発者は、選択に迫られたとき、プログラムの手続き的なロジックよりも、データをより複雑にすることを選択すべきです。なぜなら、人間にとって複雑なデータは、複雑なロジックに比べて理解しやすいからです。このルールは、プロジェクトに携わるどの開発者にとってもプログラムを読みやすくすることで、プログラムの保守を可能にすることを目的としています。
最小限の驚きのルール
インターフェースデザインにおいては、常に驚きが最小限であるようにせよ。
開発者は、ユーザーが期待する潜在的な知識の上に構築されるプログラムを設計する必要があります。例えば、電卓のプログラムでは、'+'は常に足し算を意味するはずです。このルールは、開発者が直感的に使いやすい製品を作ることを奨励することを目的としています。
沈黙のルール
余計な出力をすべきではない。他の開発者にとってただ邪魔なだけである。
開発者は、不要な出力をしないようにプログラムを設計する必要があります。このルールは、他のプログラムや開発者が、冗長な出力を解析することなく、プログラムの出力から必要な情報を選び出せるようにすることを目的としています。
修復のルール
失敗しなければならないときは、騒がしく、かつできるだけ早く失敗せよ。
開発者は、故障の原因が特定しやすく、診断しやすい、つまり「音を立てて故障する」プログラムを設計する必要があります。このルールは、プログラムからの不正な出力が入力となり、他のコードの出力が検出されずに破損することを防ぐことを目的としています。
経済のルール
プログラマの時間は貴重である。プログラマの時間をコンピュータの時間より優先して節約せよ。
現在のマシンサイクルは1970年代の価格と比較して相対的に安価であるため、開発者はマシンタイムよりも開発者タイムを重視すべきです。このルールは、プロジェクトの開発コストを削減することを目的としています。
生成のルール
hand-hacking[7]は避けよ。プログラムを書けるときに、プログラムを書くためにプログラムを書け。
開発者は手書きでコードを書くことを避け、代わりに抽象的な高水準プログラムを書いて、コードを生成する必要があります。このルールは、ヒューマンエラーを減らし、時間を節約することを目的としています。
最適化のルール
洗練させる前に原型(プロトタイプ)を作れ。最適化する前に原型が動くようにせよ。
開発者は、ソフトウェアを磨く前にプロトタイプを作るべきです。このルールは、開発者がわずかな利益のために過剰な時間を費やすことを防ぐことを目的としています。
多様性のルール
あらゆる「ただ一つの本当の方法」という主張は信じるな。
開発者は、プログラムが柔軟でオープンであるように設計する必要があります。このルールは、プログラムを柔軟にすることで、開発者が意図した以外の使い方を可能にすることを目的としています。
拡張性のルール
未来に向けてデザインせよ。未来は思ったよりもすぐにやってくる。
開発者は、プロトコルを拡張可能にし、他の開発者がプログラムのアーキテクチャを変更することなく簡単にプラグインできるようにし、プログラムのバージョンを表記するなどして、将来を見据えた設計をする必要があります。このルールは、開発者が書いたコードの寿命を延ばし、実用性を高めることを目的としています。

これら規範の多くはUNIXコミュニティの外で受け入れられている――最初にUNIXが採用したときはそうでなかったとしても、後にそうなった。また、多くはUNIXコミュニティ独特のものではなく、UNIXコミュニティから生じたわけでもない。にもかかわらず、熟練のUNIXプログラマーはこれらの考え方を組み合わせたものをUNIXスタイルの基礎として受け入れる傾向がある。

論争編集

GNUプロジェクトによる標準的なUNIXプログラムの代替(diffやfind等)が「Unix哲学」に従うものであるのか、あるいはそれを誤解しているのかは議論の分かれるところである。おそらく、UNIXに古くから関わる人々のうちの少なくともいくらかは後者を主張するであろう。なぜならGNUプロジェクトのツール群はしばしばUNIXと同等のものよりも十分に大きく、また機能も豊富だからである(GNUはコーディング標準において、いくつかの点でUNIXと同じにしないことを薦めている)。

GNU以前に1983年にはすでにロブ・パイクによる、Unixの基本的なツールにおいてBSDによって拡張された機能のうちのいくつか(代表例として挙げられたのは、cat に制御コードを文字に変換して可視化させる -v )の仕様が、Unix的でないとした批判がある[8]。確かにUnix哲学に従えば、cat -v の機能は独立したフィルタで果たされるべきであり、本来は「連結」コマンドである cat が単にストリームを読んで書くだけの目的に流用されることが多いとはいえ、それに加えてあれこれと機能を持つべきではない[要校閲]

しかし、同様にして批判された別の例である、ls コマンドが出力を表示される幅に合わせて整形する機能などは十分に便利ではあり、Unix哲学に従って column コマンドをパイプで繋げるのはどう考えても煩わしい 。そういったわけで、現代では議論されることはあまり見られなくなったものの、普段Linux等を使っている際に当然とされていることが本当に当然なのか、考えさせられる論点がある[要出典]

引用編集

  • 「UNIXはシンプルである。必要なのはそのシンプルさを理解する素質だけである。」 - デニス・リッチー
  • 「UNIXはユーザが愚かなことをするのを止めるために作られたのではない。小器用なことをするのも防いでくれるのだ。」 - ダグ・グウィン
  • 「UNIXはユーザフレンドリーだ。誰彼構わずフレンドリーになるわけではないだけだ。」- スティーブン・キング
  • 「UNIXを理解しない人々は、それを不十分に再発明することになるだろう」 - ヘンリー・スペンサー

関連項目編集

参照編集

脚註編集

  1. ^ Doug McIlroy, E. N. Pinson, B. A. Tague (8 July 1978). “Unix Time-Sharing System: Foreword”. The Bell System Technical Journal (Bell Laboratories): 1902–1903. https://archive.org/details/bstj57-6-1899/mode/2up. 
  2. ^ a b Raymond, Eric S. (2004). “Basics of the Unix Philosophy”. The Art of Unix Programming. Addison-Wesley Professional (2003-09-23発行). ISBN 0-13-142901-9. http://www.catb.org/~esr/writings/taoup/html/ 2016年11月1日閲覧。 
  3. ^ Dennis Ritchie; Ken Thompson (1974), “The UNIX time-sharing system”, Communications of the ACM 17 (7): 365–375, doi:10.1145/361011.361061, https://people.eecs.berkeley.edu/~brewer/cs262/unix.pdf 
  4. ^ Pike, Rob (1989年2月21日). “Notes on Programming in C”. 2008年11月21日閲覧。
  5. ^ 訳註:凝ったアルゴリズムは、それ自身がすでに大きなコストであるということ。
  6. ^ Addison-Wesley刊 ISBN 978-0-13-142901-7、アスキー刊日本語版 ISBN 978-4-7561-4948-0
  7. ^ http://www.catb.org/jargon/html/H/hand-hacking.html
  8. ^ http://harmful.cat-v.org/cat-v/

外部リンク編集