Create a gist now

Instantly share code, notes, and snippets.

UNIXという考え方 The UNIX philosophy

UNIXという考え方 The UNIX philosophy

定理

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

小さいものは、大きい物にない利点がいくつもある。小さいもの同士なら簡単に独特の便利な方法で組み合わせることができる
小さなプログラムという発想
  • 小さなプログラムはわかりやすい
  • 小さなプログラムは保守しやすい
  • 小さなプログラムはシステムリソースに優しい
  • 小さなプログラムは他のツールと組み合わせやすい
一般にソフトウェアの開発者は、巨大なプログラムを書いてしまう。
これは「あらゆる不測の事態に対応できるように」という誤った考えに基づくものだ。
巨大で複雑なプログラムの開発者は、「将来が予測可能で、そして現在とそう大きくは変わらない」
という勝手な思い込みを前提としている。
一方、小さなプログラムの開発者は、未来の予測など最初からあきらめている。
彼らの予測することは、明日作られるものは今日作っているものとは違うということでしかない。
作った時には予測できなかったことに対しても、小さなプログラムなら直ちにそれに対処できる。
未来に目を向けよう。未来は、思っているより早く来る。

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

一つのことに集中することでプログラムに不要な部分をなくせる。
不要な部分があると、実行速度が遅くなり、不必要に複雑になり、融通が効かない。
  • creeping featurism(しのびよる多機能主義)
プログラマはシンプルなApplicationを書くかもしれない。
しかし、彼のCreativeさが新機能や新しいオプションを付けさせてしまうのだ。
そのコードが本当に必要なのかどうかを常に意識しておくべきだ。
・プログラムはユーザーとの対話を必要とするのか?パラメータはファイル読み込みや引数で出来ないのか?
・プログラムの入力データが特殊フォーマットである必要があるのか?他のプログラムに回せないのか?
・プログラムの出力データが特殊フォーマットである必要があるのか?他のプログラムに回せないのか?
・新しくプログラムを書く必要があるのか?他のプログラムを組み合わせれないのか?
  • 小さなプログラムは単一機能になる傾向があり、単一機能のプログラムは小さくなる傾向がある。

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

あらゆるプロジェクトにおいて、プロトタイプは重要である。
一般的にプロトタイプは設計全体のうちの一部として扱われているが、
UNIXにおいてのプロトタイプは、効率的な設計には欠かせない重要な一部である。
  • ソフトウェアに完成はない
ソフトウェアには常に改善の余地はあるのはもちろんだし、時間的な制約などでそのソースコードは必ずしも最高の状態が保たれているわけではない。
ほとんどのソフトウェアは妥協の産物だ。完成することはなく、ただリリースがあるだけだ。
ソフトウェアや計算機が常に進化していることを意識しなければならない。
UNIXの考え方はソフトウェアの進化にも強い。
ソフトウェアを小さくてシンプルな部品に分割すれば、
将来の変更に容易に対応できるし、ソフトウェアを容易に移植可能にしておけば、来年には利用できるようになる、
よりはやい計算機でも簡単に動かすことができる。
  • なぜソフトウェアは「ソフト」ウェアなのか
ユーザーが自分たちの望むもの正格に表す事ができ、ソフトウェア技術者たちが、ユーザーが現在必要としている機能と
将来必要になるであろう機能とをすべて把握していたとすれば、ソフトウェアはいらないだろう。
すべてのプログラムが最初からROMに書かれていればいい。残念ながら、そのような完璧な世界は存在しない。
リリース後に進行状況の報告を絶えず受け、対応した進路に修正していくことこそがゆういつの拠り所となる。
誰もが常に学び続けている。たとえ我々がすべてを知り尽くしたと勝手に思い込んでいても、誰かが我々への要求仕様を
変えてしまうのだ。
  • 第一のシステム、第二のシステム、第三のシステム
人間にはこの三種類のシステムしか作れない。
人間の作るSystemは人間に似るということなのかもしれない。
人間が、若さからはじまり、成熟し、やがて老いていくように、
システム設計にも若い設計、成熟した設計、枯れた設計がある。
  • 追い詰められた人間が第一のシステムを作る
第一のシステムは、一人もしくは少人数が、時間に追われる中で創造性を発揮し、勢い良く作ったシステムだ。
時間追われたために、足りない機能もあるが無駄はなく効率的に動く。
さまざまな批判を浴びせかけられるだろう。
しかし、当の本人は「ああ、そりゃちょっと汚いのは分かってる。でもちゃんと役に立ってるだろ!」と、こういうだろう。
「正しく」やっている時間など無い。
「正しく」やる時間がない人間は、重要な箇所だけに集中して枝葉を無視する。
その結果、いくつかの細かい点は次のバージョンに回そうと計画する
第一のシステムのコンセプトは、人間の想像力を刺激する。
この段階で大規模になることはない。
チームが大きくなることで意思疎通・個性の衝突がおきる。
このタイミングで人を投入してもあちこちに縄張りが出来るだけであり、第一システムの実現すら危ぶまれる。
人月の神話である。
  • 人間による第二のシステム
しかし、第一のシステムが成功しはじめると、多くの人が集まってくる。
そして、「専門家」が第一のシステムにより有用性が証明されたアイディアを用いて第二のシステムを作る。
第二のシステムは第一のシステムに目をつけた多くの参加者からなる委員会が機能を決定する。
その結果として、多くの人の意見(独自技術症候群を持った意見も含む)を取り込みすぎるため、機能は多いが、無駄のある遅いシステムができあがる。
多くの人に期待された第二のシステムは時には商業的にも成功するが、実はあまり役に立たない。
  • 人間による第三のシステム
第二のシステムで「火傷」した人々が、第三のシステムを構築する。
第三のシステムだけが、第一のシステムが発見したアイディアと第二のシステムの中で見つかった必要な機能をバランスよく取り入れて、やっと役に立つシステムを構築することができる。
Systemの目的はしっかり把握され、使用するギジュ湯もすでに証明済みであるため、リスクは小さい。意思決定の段階で、正格な予算を組み、正格なスケジュールを建てることができる。
第三のシステムの設計者には、ようやく「正しく」やることが出来る時間が与えられる。
  • 効率的に第三のシステムを構築するために
UNIXの考え方では、なるべくはやく第三のシステムを構築するために、すばやく試作することをおすすめしている。
直接、第三のシステムをつくることはできないのだ。
1 短い機能仕様書を書く(3〜4枚程度)
2 ソフトウェアを書く
3 テストして書き直す。満足できるまで、これを繰り返す。
4 詳細なドキュメントを(必要なら)書く

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

現在のハードウェアに制限されないソフトウェアこそ、未来でも利用される
  • 最も効率のよい方法は、ほとんどの場合移植性に欠ける
ハードウェアと切り離すことができないソフトウェアは、そのハードウェアが競争力を持ち続ける間しか価値を維持できない
より高速なハードウェアによって既存のハードウェアが置き換えられる度に書き直さなければならない。

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

移植性を保つ上で、各OSのバイナリーファイルに依存しないASCIIフラットファイルに保存し、参照可能にする。
データをわざわざバイナリーにする必要がない。

6. Use software leverage to your advantage. ソフトウェアを梃子(てこ)として使う

プログラムの再利用は、ソフトウェアの梃子を最大限に活用した強力な考えだ。
UNIXの開発者たちは、この考え方に従って、非常に多くのApplicationを比較的に短期間に開発してきた。
  • 独自技術症候群
一般に信じられているところとは反対に、独自技術症候群は創造性を伸ばさない。他人の仕事を見て、自分のほうがうまくできると主張してみても
それだけで創造性が増えるわけではない。
既存のApplicationをゼロから設計し直すことは模倣であっても創造とは言わない。
むしろこれを避ける事で、新しい、わくわくするような設計世界への扉が開かれる。
「自尊心」の誘惑に負けてはいけない。
  • すべてを自動化する
ソフトウェアの梃子をクカ的に利用する方法の一つは、マシンをより激しく働かせることだ。
コンピュータにできることを人間が手作業で行うのは時間の無駄だ。
おどろくべきことに現代的なエンジニアの研究所でさえ、中に入ってみると、驚くほど多くの熟練技術者が日常の業務を手作業で行っている。
よい方法を知ってはいても、昔からの習慣はなかなかなくせない。人間が必要以上に働き過ぎ、コンピューターが眠っているということは無いだろうか?

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

shell scripts はソフトウェアの梃子を活かすと同時に移植性も高めるという2つの効果がある。

8. Avoid captive user interfaces. 過渡の対話的インターフェースを避ける

いくつかのコマンドは、「ユーザーを拘束する」インターフェースを持つ。
そのコマンドを実行してしまうと、実行中に他のコマンドを実行することはできない。
そのコマンドの実行中は、ユーザーはそこをはなれられなくなってしまう。
この類のものを「拘束的」ユーザーインターフェースと呼ぶ。
先端技術の胸囲を使いこなすにあたっては、ユーザー側にもある程度の知識が必要となる。
モノが小さくなって高度になればなるほど、使うために必要な知識も増してくるように見える。
以下の様な特徴がある
・小さなものは人間にあまり良く馴染まないということ。
・小さなものは、人間とはよく馴染まなくても、互いにはよく馴染むということだ。
コンピューターソフトウェアの世界においても、
小さなプログラムやモジュールを数多く持つことで環境への適応能力は最大となる。
しかし、残念ながら、モジュールが小さくなればなるほど、ユーザーとのインターフェースという問題が大きくなってくる。
モジュールの数が増えれば増えるほど、取り扱いも煩雑になる。
そこにソフトウェア設計者にとってのジレンマがある。アプリケーションに最大の柔軟性を求めて、数多くの小モジュールから構築する。
しかし、一方では、ソフトウェアを使いやすいものにするという要件も無視できない。モジュールの数が多すぎると扱いが困難になる。
UNIXは、この矛盾を解決するためにユニークな方法を用いる。
ほとんどのシステムは、ユーザーとモジュールとの間に広がりつつ有る溝を、「拘束的」ユーザーインターフェースと呼ばれるソフトウェアで埋めようとする。
UNIX開発者も溝が広がる一方であることは認めている。
しかし、ユーザーとモジュールとを大量の「スパゲッティ」コードで結びつけるのではなく、その溝を少しずつ小さな塊または層にして減らしていこうとする。
UNIXユーザーの多くは、ユーザーが誤ったパラメータを入れると、必要なパラメータとその使い方を示す簡単なMessageを表示する。
UNIXユーザーが拘束的なユーザーインターフェースを避けるのには、もう少し深い理由がある。
UNIXユーザーにとっては、コメンど同士を対話させる方法が必要なのだ。
  • 拘束的プログラムはユーザーを人間と想定している
拘束的プログラムの開発者は、キーボードの前に人間がいるという前提で設計している。
コンピューターが人間の限界に制約され、システムがユーザー入力を待つ必要があると、
キーボードの前に座る人間と同じ早さでしか動作できない。つまり、全く早くないということだ。
姑息的プログラムは「大きい物は美しい」的アプローチをとる
拘束的プログラムは、他のプログラムと結合するのが難しい。
拘束的ユーザーインタフェースはスケーラビリティに欠ける
最も重要な事に、拘束的ユーザーインタフェースはソフトウェアの梃子を効果を利用できない。
「Yes/No」やユーザー入力、その他の応答をユーザーから引き出したりする。

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

ソフトウェアの本質は、データを処理することで、生成することではない。
その能力を最大限に発揮するためには、プログラムをフィルタとして動作するように設計すべきだ。
すべてのプログラムは、何らかの形式のデータを入力として受け入れ、何らかの形式のデータを出力として生成する。
プログラムはデータを作らない。人間がつくる
一般にはアプリケーションがデータを作ると信じられているが、実際のところ、アプリケーションにはデータを作る能力など無い。
データを作るには、想像力が必要だ。そして、オリジナルの情報源が必要だ。コンッピュータは情報源を持たない。
コンピュータは、データを一つの係止から別の形式に変換する。

重要度の低い定理

1. Allow the user to tailor the environment. 好みに応じて自分で環境を調整できるようにする

UNIXのユーザーは、自分の思い通りに環境を手直しすることを好む。

2. Make operating system kernels small and lightweight. OSのカーネルを小さく軽くする。

新機能の追加要求が次から次へと出てくる中でも、UNIXの開発者たちはOSの中心部分を小さく軽く保つことを好んできた。
アプリケーションのパフォーマンスを高めたいと思う人がまず考えるのは、ランタイムルーチンをカーネルに組み込むことだ。
実行中のアプリケーション間のコンテキストスイッチが減るが、代わりにカーネルが大きくなり、他のUNIXカーネルとの整合性も
失われてしまう。
Xウィンドウシステムの開発の初期段階で、Xサーバーの一部をUNIXカーネルに埋め込むことが提案され、
それでパフォーマンスが高くなるかどうかをめぐって激しい意見の対立があった。
結論、Xサーバーにバグがあると、ウィンドウシステムがクラッシュするだけではなく、OS全体がクラッシュすることがわかり、Xサーバーはユーザー空間に置かれている。
カーネルが小さくて軽ければ、タスク開始時にコピーもしくは変更するデータ構造体の数が少なくすみ、ユーザー空間でタスクがすみやかに実行できる。
「一つのことだけをうまく」実行する小さなプログラムの集まりが効率よく動作するためには、カーネルが小さいことがぜひとも必要となる。小さな単一機能
プログラムが迅速に実行されることは、UNIXのパフォーマンスに取って極めて重要だ。

3. Use lower case and keep it short. 小文字を使い、短く

アルファベットの小文字を使うのがUNIXの伝統。もともとはそうする理由があったが、進化とともに理由が無くなった現在でも
UNIXユーザーの好みは変わっていない。

4. Save trees. 森林を守る

UNIXユーザーは紙のドキュメントを嫌う。
すべてのテキストファイルをコンピュータに保存して、強力なツールでそれらを操作するのだが、このことに十分な理由がある。
「データを紙に印刷してしまったら、もうそれ以上操作出来ないんだぞ」と、上司は言った。
紙に印刷されたデータは、並び替えも、移動も、フィルタ処理も、変形も、修正も出来ない。
少なくとも、コンピュータ上でやるように簡単には出来ない。
瞬時に取り出せるように、巨大なディスクファームにアーカイブ保存することも出来ない。キー一つで検索することも出来ない。
保護したい機密情報なのに暗号化もできない。
動かせないデータは死んだも同然だと前に言ったことを覚えているだろうか?紙に印刷されたデータも同じことだ。

5. Silence is golden. 沈黙は金

UNIXのコマンドは、詳細なエラーメッセージを出すべき時にも、悪名高いほど沈黙を守る。
UNIXに慣れたユーザーはそれが一番いいと考える。
UNIXは一般に「ドライ」で、ただ「事実」だけを伝える。それ以上でも以下でもない。
 ls -l | awk '{ print $4 }' | sort
 ここでlsが"DIRECTORY: NO FILES FOUND"という出力をパイプラインに送ったらどうなるのだろうか。
 このメッセージの4番目のフィールドが”FOUND”であるから、sortコメンからの最終出力として、
 意味不明の"FOUND"というメッセージが表示されることになる。

6. Think parallel. 同時に考える

たいていの仕事は、いくつかの小さい部分に分けられる。
これらの小さい部分を同時に実行すると、大きな一つの仕事にかかるのと同じ時間でより多くの仕事ができる。

7. The sum of the parts is greater than the whole. 部分の総和は全体よりも大きい

小さい部品を集めて大きなApplicationを作る方が、大規模プログラムを単体で構成するよりも柔軟性に富み、従ってより役に立つ。
どちらのアプローチでも同じ機能は達成できるかもしれない。しかし、先のことを考えると、小さい部品の集に夜アプローチの方が有利だ。

8. Look for the 90 percent solution. 90%の解を目指す

どんなことであれ、100%上手くやることは大変だ。90%のことだけを上手くやれるようにするほうが、はるかに能率的であり費用対効果も最も高い。
UNIX開発者は、対象ユーザーの90%が満足する解を目指す。

9. Worse is better. 劣るほうが優れている

生き残るのは最大公約数的なSystemだと、UNIXファンは信じている。
高級品ではないが効率的なモノのほうが、高品質で効果なものよりも断然受け入れられやすいだろう。
PC互換機の世界が、UNIX界のこのアイデアに従って大きな成功を収めつつある。

10. Think hierarchically. 階層的に考える

UNIXユーザーと開発者とは、物事を階層構造で整理するのが好きだ。
例えば、UNIXでのディレクトリ構造は、ファイルシステムに適用された最初の階層構造アーキテクチャだ。
UNIXはこの階層的な考え方をさらに発展させ、ネットワークサービスでの命名法やウィンドウ管理、オブジェクト指向開発など、他の分野にも影響を及ぼした。

一つのことをうまくやろう

CSP(小プログラム集合”Collection of Small Programs”)層は、一組のUNIXコマンド、またはシェルスクリプトからなっており、その一つ一つがアプリケーションの一機能を実行する。
新しい機能が必要になった時は、その機能を実行する小さなプログラムを作成するだけなので簡単だ。
一方、もっと限定的なアプリケーションが欲しいという時は、あなにもしては行けない。
この場合は、アプリケーション層が不要なプログラムを実行しないだけのことだ。
  • アプリケーション層と小プログラム集合層(CSP)
ユーザーにとって、どの機能が必要あの判断はアプリケーション層で行われ、機能自体は小プログラム集合層で実行される。
アプリケーション層は、主として小プログラム集合層とユーザーインタフェース層の「つなぎ役」として働くほか、アプリケーションの機能を決定する。
小プログラム集合層のさまざまな要素を一つの環境にまとめ挙げることで、小さなプログラム同士の相互関係を規定し、そsの動作の枠組みを規定する。
  • ユーザーインタフェース層
ユーザーインタフェース層とは、ユーザーがアプリケーションを実行したとき、画面上で目にする部分を言う。
外見の好みに応じて、様々なユーザーインタフェースから好きなものが選べ、非常に柔軟性に富んでいる。
UNIX環境では、一般に3通りのゆーざーインターフェーススタイルがある。
まず、一つ目はシェルスクリプト型またはスクロールメニュー型で、すべての端末またはテレタイプで使用できる。
次は、cursesベースのインタフェースだ。これは、文字度端末で使用される全画面ユーザーインタフェースだ。
最後にXウィンドウシステムの端末やワークせテーションで見られるグラフィカルユーザーインタフェースだ。
巧みに構成されたアプリケーション層であれば、様々なユーザーインタフェースのスタイルからユーザーが好きなものを選択することが出来る。
このことは、ユーザーインタフェース層が「ハードワイア」されていてはならないということを意味している。
状況に応じて、どのようなユーザーインタフェースでも選ぶことが出来なければならない。
小さなプログラムには、明らかな利点がある。
まず、わかりやすいことだ。
大きな「何か」より小さな「何か」のほうが、人間にはわかりやすい。理解しやすければ、当然、保守も用意となるので、最終的には費用体効果が大きくなる。
また、システムリソースを余り使わないので、読み込み、実行、開放のいずれもすばやく行うことができ、効率が高まる。
移植性を高くしようとすると効率は犠牲になってしまうものだが、プログラムを小さくすることで、多少なりとも取り戻せるだろう。
最後に、小さなプログラムは、他のツールと簡単に結合できる。
単独ではたいしたことができなくても、他の小さなプログラムと組み合わせて使うことで、
プログラマは--最も銃なことに--ユーザーが自分で短時間のうちに、新しいアプリケーションを作ることが出来る。
小さなプログラムは、目的を絞らなければならない。言い換えると、一つのことを上手くこなすことに専念すべきだ。
一つのプログラムでひとつの問題を解決することをモットーにしてほしい。
大きく複雑な問題でも、小さく分割すれば、一度に少しずつ克服していくことが出来る。
一つのことを上手くやるプログラムは、他のアプリケーションの中でも比較的簡単に再利用できる。できることと出来ないことをが明確で、
大きなプログラムにありがちな曖昧さがない。
一つのことだけに専念すれば、小さなプログラムのまま、大きくて複雑な単体型プログラムになる危険を避けれられる。
単体型プログラムは「スパゲッティコード」を含んでいることが多く、他のアプリケーションとの共同作業が苦手だ。
小さなプログラムは、今日とは違う明日があることを認識している。
今日完璧に見える機能でも、明日は不完全になり、場合によっては時代遅れになるかもしれない。
単体型プログラムは目前のすべての状況に対処しようとするが、小さなプログラムはソフトウェアが進化することを率直に受け入れている。
ソフトウェアに完成はない。ただリリースが有るだけだ。
世界のソフトウェアは絶えず進化し続けており、誰も学習曲線からは逃れられない。
ソフトウェアの世界がどの方向に向かおうとしていのか、絶対の確信を持って予言できる人は誰もいない。
人間にできることは、せいぜい明日のニーズは変化しうるという前提に立って、今日のニーズを満たすソフトウェアを作ることくらいだろう。
開発者は設計仕様書の作成に何週間も何ヶ月も費やす無駄をやめ、計画の目指すおおよその方向を文書にまとめたら、さっさと開発に取り掛かったほうが良い
試作をできるだけ早いうちに作ることが重要だ。
設計者の頭の中にあったアプリケーションが、早期に形となって他人の手に渡り、それだけ第三のシステムへの歩みも早まる。
試作は、将来へ向かっての歩みを加速させる。
変更が必要なものなら、すべてが意思に固まるまで待ってから変更するより、まだ万事が流動的な初期段階で変更するほうがいいに決まっている。
試作を作ってみれば、何がうまくいくか、そしてより重要なことに、何がうまくいかないかがわかる。
試作は、一つのことだけを行う小さなプログラムを使い、徐々に進めて行くといい。
何かの機能が必要になるたびにそれを小さなプログラムとして追加していけば、費やす労力は最小限ですむ。
覚えておいてほしい。ソフトウェアは、実は作るものではなく、成長して行くものなのだ。
成長したソフトウェアを新しいハードウェアにも移植できれば、そのソフトウェアの価値は上がる。
新しいアーキテクチャは頻繁に現れる。
移植性の高いソフトウェアは、すぐにその新しいアーキテクチャの長所を利用できる。
そこで、試作では効率より移植性を優先させる。
この結果、移植できるものは生き残る。それ以外のものは、やがて時代に取り残されてしまうだろう。
UNIXの考え方とは、常に将来を見据えながらオペレーティングシステムとソフトウェアの開発にアプローチすることだ。
そこでは、常に変化し続ける正解が想定されている。
将来は予測できない。現在についてあらゆることを知っていても、その知識はまだまだ不完全なことは認めざるをえない。
ソフトウェアを開発するにせよ、子どもたちのためにより良い世界を築くにせよ、将来はガラス越しにしか見えない。
いつか、すべての答えがわかる日がくるかもしれないが、それまでは前進し続けれなければならない。いつか、すべての答えを知る時がやってくるのかもしれないが、それまでは、一日ごとに「今日」が「昨日」担っていく日々を過ごしながら、将来に適応し、前進し続けなければならない。
UNIXの理念は、そういう将来に向かうアプローチの一つだ。
その本質は柔軟でありつづけることだ。
嵐が何度やってみても、風に揺れる気は折れることがない。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment