Unixという考え方を読んで

昔読んだ読書感想文が残っていたので、また読み返せるようにコピーしておいた。

  • 1、小さいものほど美しい
  • 2、早めの試作
  • 3、移植性優先、ハードウェアに依存するものを造らない
  • 4、ソフトウェアの梃子の原理
  • 5、対話型プログラムの危険

1、小さいものほど美しい

大きいものは組み合わせるのが難しいが、小さいもの同士であれば組み合わせることが簡単である。という原則に立ち、UNIXコマンドを構成するモジュール一つ一つは非常に限られたことだけを 行うように設計されている。実際にファイルをコピーするという動作のために、ファイルが存在するか確認するモジュール、ファイルが読み込めるかどうかを確認するだけの モジュールなど、限られた目的しか達成することの出来ないプログラムを組み合わせている。これらのプログラムは一つ一つは何の仕事も達成できないが、組み合わせることで様々な機能を構成するモジュールとして再利用することができる。

また小さいものはシンプルで仕組みを理解しやすい。これはプログラムのメンテナンスにおいても効果を発揮する。経営者は自力で複雑な機能を持ったプログラムをかけるプログラマよりも、小さくてシンプルなものを書くプログラマのほうが優れているということを知っている。前者はプログラマが職を離れたときに困るのは経営者自身だからだ。

2、早めの試作、完璧な仕様書を作らない

良いシステムを作り上げるためには、主に3つの段階を踏む必要がある。1つは不完全だがアイデアを実証するためのプロトタイプ、次に必要と思しきあらゆる機能を詰め込んだ 大規模なシステム、最後に不要な機能を削ぎ落とし本当に必要なものだけに絞った完成されたシステム。どんなプログラムであれ、この3つの段階から逃れることはできない。

最初のプロトタイプを作るの前に、完璧な仕様書を作ろうとしても実際のところ細部は開発中に変えざるを得なくなってしまう場合が多く、そうなると何重個ものバージョンの仕様書 が発行されることになる。そうではなく、最初のプロトタイプが出来たら、まずそれをユーザーに見せ、その反応をみて開発を進める。最初のプロトタイプを見せたとき、開発者側も ユーザー側も「こんなことができるかもしれない」という新たなインスピレーションを得ることができ、それが開発に新しい方向性を示すことがある。

本当に仕様書が必要になった場合でも、今開発しているものをそのまま文書化するだけ、というのが望ましい姿だ。

3、移植性優先、ハードウェアに依存するものを造らない

ハードウェアに依存するコードを書けば、新しいハードウェアの登場とともに、その資産は使えなくなる。 少なくとも対応の為のコードの書き直しの間に、他の製品がそのハードウェア上で動くようになりマーケットでのシェアを失う。 また、ハードウェアの変化によってコードが使えなくなる悪影響は未来の資産として使えなくなることにも関連している。 ハードウェアの進化は目覚ましく、今かろうじて動いているシステムがあれば、一年後のハードウェアではすいすい動いている。 Unix上で動くコードを書くことで、Unixが動くハードではすべてその資産を使えるようになる。

移植性の問題はこの本が書かれた時代とは大きく変化していると思う。 まず、ハードウェアに依存したプログラムというものが今ではほとんど思いつかない。当時はアセンブラ言語でかかれていたプログラムも多かったということなのだろうか。 基本的に、OSは3つしか存在せず、どんなハードウェアでもそれらは動く。

Google DocumentがWordやExcelに取って代わったように、ブラウザというインターフェースを通して、あらゆるものをバックエンド の処理を達成でしようとするのが今の潮流だろう。 サーバー側のバックエンドはハードの激しい技術進歩にさらされるかもしれないが、フロントエンドはJavaScript以外の新たな言語が登場するには相当な時間がかかるだろう。 そうなるとJavaScriptUNIXでいうシェルスクリプトのような、もっとも望ましいかたちの言語ということができる気がする。

4、ソフトウェアの梃子の原理

ソフトウェア開発において過去の資産を極力使い、それを拡張することで付加価値を付けることに徹するべきだという考え方だ。 車輪の再開発をしたり、より高速なスペックを求めて効率的なコードを書こうとするのはただの模倣であり、付加価値は付けられない。 シェルスクリプトはその代表例ともいえる過去の資産である。小文字のアルファベット数文字で入力できる命令を組み合わせることで、 C言語900行分くらいの命令を実行できる。逆に、C言語で書かれたプログラムはハードウェアに依存する場合も多く、書き直しが必要になって そのコードを使いまわせないことが多々ある。

今まで自分は他のライブラリを組み合わせて一つの作品を作ることが多かった。LINEをインターフェースとしたリマインダーはLINE APIと データベース制御用ライブラリの組み合わせに過ぎないし、Sinatraのブログも、Markdownレンダリング用のライブラリと、データベースのやり取りにhttmlを加えたものに過ぎない。 そうした作品は所詮、ライブラリ同士のやり取りを仲介するコードを書いただけに過ぎないという思いや、既製品を1から自分で作り上げること こそ勉強になる、という思いもあった。確かに、コーディング能力を上げるという意味ではこれもあながち間違っていないのかもしれないが、 プロフェッショナルとして仕事をするなら、付加価値をつけることに徹すること、既存の資産を使うことを覚えなければ意味がないということも理解した。

もちろん、これは「これから作る作品を将来資産として使えるようにしておく」ということの裏返しでもある。ハードウェアに依存したコードは 新しいハードウェアの登場でもう使えなくなる。いろんな機能を満載にしたプログラムは大きすぎて、必要な機能だけを取り出すことができないから 過去の資産として使えなくなる可能性がある。小さく、シンプルなものを可能な限り、移植性に留意して作り出さなければならない。

5、対話型プログラムの危険

ユーザーフレンドリーな対話型プログラムはユーザーがキーボードの前にているという前提があり、ネットワーク上から命令を流し込んだり、他の プログラムとの組み合わせには向かない。またいちいちユーザーに入力を期待するようなプログラムはどんなに早いハードウェアの上で動いても ユーザの速度に依存してしまう。その為UNIX環境では、プログラムの起動時に複数のオプションを含めたすべてのコマンドを入力しておき、実行を開始したら ユーザーに入力を求めないという方針を貫いている。 UNIXのユーザーとのインターフェースはstderr,stdin,stdoutの3つのファイルのみで構成されることが推奨されている。こうすることで、この3つのファイルへの 書き込み権限さえあればネットワーク上だろうと、他のプログラムからだろうと実行することができる。

Amazon LinuxUnicornを導入したとき、エラーメッセージは短いものだけが表示され、あとはstderr.logを見よというメッセージが出ていた。 あの時はいちいち、vimでそのファイルにアクセスしなければならなかったので面倒だったが、この度はような哲学の下に成り立っているシステムだとは知らなかった。