schedule2021-09-05

【技術書】UNIXという考え方-その設計思想と哲学を読んだ

picture 1

仕事で普段使っているLinuxの元となったUNIXってどうやって作られたんだろう?って知りたくなったので、「UNIXという考え方―その設計思想と哲学」を読みました。

後述するけどLinuxはUNIXを元に作った血のつながっていない親戚のようなもの。 Linuxを理解するうえでUNIXについて知っておくことはとても大事だ。 本書を読んだことで初めて触れたLinuxが苦手に感じたことも、学んで理解して行くうちに仕事のパートナーとも呼べるくらい愛する(もっと理解したいから愛しているといって差し支えない)ことになった理由も分かった。 また、UNIXのことを知るだけでなく自身の設計の考え方にも影響を受けた。

Linuxを利用されている方にはぜひ読んでUNIXのことを知ってもらいたくお勧めする書籍です。

Contents

UNIXという考え方―その設計思想と哲学

UNIXという考え方―その設計思想と哲学 Mike Gancarz (著), 芳尾 桂 (翻訳)

この本はUNIXのツールの使い方を紹介する本ではなく、「UNIXの考え方」について解説している本です。 数あるOSの中でなぜUNIXが広く受け入れられてきたかのヒントがたくさん書かれている。

原著は1996年に書かれ日本語訳の初版が2001年とちょっと古い。 例えば比較するOSの対象がAtariホームコンピュータ1やMS-DOS2と31才の僕では使ったことも直接見たこともないコンピュータと比較している。 出版は古いが、本書にか書かれているUNIXの思想は今日では当たり前として受け入れられていたりアジャイルやドメイン駆動設計などの思想にも関連している部分がある。現在でも学ぶべきだし今後の技術者としての支えになると思う。

UNIXとLinuxの関係

ここでUNIXとLinuxの関係について触れておく。

UNIXの誕生と普及

まずアメリカのベル研究所でUNIXが生まれた。 他のユーザーフレンドリーなOSと違い、UNIXは「ユーザーは、自分が何をしているか分かっている」との前提に立っているため何をしているかわからないユーザーには不親切極まりない。しかしその柔軟性と移植性から一部のコンピュータに詳しい人々がいじり倒した。

結果、柔軟性と移植性と性能の高いオペレーティングシステムだと評判になった。 ベル研究所が所属するAT&T社は当時独占禁止法によりUNIXを作りながらもUNIXを販売することができなかった。そのため、利益が出る程度の少額で配られるようになり、急速に普及した。

ソースコードも公開されていたため、ここから様々な派生版のUNIXが誕生することになる。 UNIXが大きなビジネスになることに気づいたAT&T社がUNIXを商標登録したためライセンス縛りが普及の足かせとなってしまった。

Linuxの登場

Linuxは1991年にリーナス・トーバルズがUNIXの機能が不足していると感じて改造したのが始まりです。 せっかくだからとゼロから作り直し、AT&TのUNIXは著作権が面倒だったのもあり独立したOSとなった。LinuxはUNIXが参考としているがソースは別物です。

リーナスが勉強用に作ったOSでしたが、多くの人に見てもらいアドバイスを求めようとオープンライセンスで一般公開した。 UNIXライセンスに苦慮していた有志たちが集まり、わずか2年で実用に耐えられるだけのLinux ver1.0がリリースされる。

ちなみにリーナスが作ったUNIXだからLinuxらしい。

以降の快進撃によりLinuxは世界標準のOSとなった。 それは、本書の著者Mike Gancarzが言い続けてきたUNIXが世界標準となる未来をある意味で当てたことになる。

参考: 【初心者向け】Linuxの歴史解説! OS誕生からLINUXへ - エンジニアの入り口

というわけで、UNIXの思想を知ることはLinuxにもつながる。

UNIXの思想と哲学

ここから本書で書かれているUNIXの思想と哲学について紹介する。 UNIX開発者の教義ともいえる9つの定理と重要度は低いがUNIXの文化を担う小定理を10個をまとめられている。

重要な9つの定理について簡単な紹介と面白かったところ自分用にまとめつつ紹介する。

  1. 小さいものは美しい
  2. 一つのプログラムには一つのことをうまくやらせる
  3. できるだけ早く試作する
  4. 効率性よりも移植性を優先する
  5. 数値データはASCIIフラットファイルに保存する
  6. ソフトウェアを梃子(てこ)として使う
  7. シェルスクリプトによって梃子の効果と移植性を高める
  8. 過度の対話亭インターフェースを避ける
  9. すべてのプログラムをフィルタとして設計する

各定理の簡単な紹介は「本書1.1 UNIXの考え方かた:簡単なまとめ」より引用してます。

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

小さいものは、大きいものにはない利点がいくつもある。 小さいもの同士なら、簡単に独特の便利な方法で組み合わせることができるというのもその一つだ。

例えば、ファイルをコピーするプログラムならファイルをコピーするだけにする。他の引数のチェックや、ファイルが存在するかチェックしたり、ファイルを開いたり、閉じたりするプログラムと組み合わせることでユーザがしたいことを実現する。 UNIXでは小さなプログラムを集めて複雑で大きな処理を行う。

また、小さなプログラムは分かりやすく保守がしやすくシステムリソースにやさしい。

なにより小さなプログラムは他のツールと組み合わせやすい。あらゆる不測の事態に備えるには機能をたくさんつけて大きなプログラムになる。 それよりも、未来の予測は諦めておく。予期しないことへの対処も小さく使いやすいプログラムなら直ちに対処できるから。

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

一つのことに集中することで、プログラムに不要な部分をなくせる。 不要な部分があると、実行速度が遅くなり、不必要に複雑になり、融通が効かなくなる。

オブジェクト指向設計の単一責任の原則(Single responsibility principle)に通じる考え。 本質ではない処理は他のプログラムと組み合わせて実現する。

道を誤ったUNIXコマンドとしてlsが紹介されていた。 20以上あるオプションが今も増え続け、ファイル名順のソートやターミナル幅に合わせて数列に表示する。 純粋なlsはディレクトリ名を1行に1つずつただ出力良くすればよい。

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

あらゆるプロジェクトにおいて、試作は重要だ。一般的に施策は設計全体のうちのほんの一部として扱われているが、UNIXにおいての試作は、効率的な設計には欠かせない重要な一部だ。

試作によって学び、早い試作がリスクを減らす。 時間をかけて正しくやるよりも、時間に追われて重要な箇所だけに集中して作り上げてしまうことを良しとしている。

UNIXの開発者は短い機能仕様書のみ書いて、あとはソフトウェアを書きとテストを繰り返す。 満足できたら(必要なら)詳細なドキュメントを書く。

Design Sprint3というできるだけ早い試作をしてリスクとコストを抑える仕組みに似ている。

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

UNIXが移植可能なオペレーティングシステムという新境地を開拓したとき、これはすごいニュースにだった。 現代のソフトウェア設計では、プログラムに移植性があることは当たり前のこととして捉えられている。 これは、UNIXの考え方のうち、ほかのシステムにも広く受け入れられている一つの例だ。

この定理は良いプログラムは死なず、ただ新しいハードウェアに移植されるのみ(p53)に尽きる。

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

移植性のあるプログラムは重要だ。しかし、移植性のあるデータも移植性のあるプログラムに勝るとも劣らず重要だ。 従来の移植性に関する議論では、データの移植性という視点がいつも無視されてきた。

時間も手間もかけずデータの移植をするためにASCIIテキストで統一している。

日本語文字コードの歴史を見ているとASCIIテキストで統一できる英語圏は羨ましくなる。 Unicodeの登場によって良くなったが今でも変換に悩む移行作業に出会ったりする。

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

再利用可能なモジュールの重要性について、たいていのプログラマは表面的にしかわかっていない。 プログラムの再利用は、ソフトウェアの梃子を最大限に活用した強力な考えだ。UNIXの開発者たちは、この考えに従って、非常に多くのアプリケーションを比較的短期間に開発してきた。

この章の中で独自技術症候群を避けるように明言している。

既存のアプリケーションをゼロから設計し直すことは模倣であっても創造といわない。 むしろ、これを避けることで、新しい、わくわくするような設計世界への扉が開かれる。(p71)

時間をかけても自分で書くのが好きだから耳が痛い。 普段使う言語だと特に慣れて書けてしまうから、有名なライブラリしか知らない。 もっとライブラリを知って任せられるとことは時短して、新しい機能を開発するようにしたい。

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

シェルスクリプトは、ソフトウェアの梃子を活かすと同時に移植性も高めるという二つの効果がある。 可能なときには常に、C言語ではなくシェルスクリプトを使うべきだ。

シェルスクリプトが難しくて、Python2.7でサーバのバッチを書いていた時期もあった。 シェルスクリプトに慣れてくると確かに短いコードで同じ処理が書けるようになる。

シェルスクリプトなら古いOSにも未来のOSでも利用できる。

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

いくつかのコマンドは、「ユーザーを拘束する」インターフェースを持つ。そのコマンドを実行してしまうと、実行中には他のコマンドを実行することはできない。 つまり。そのコマンドの実行中は、ユーザーはそこを離れなくなってしまう。 そのため、この類のものを「拘束的」ユーザーインターフェースと呼ぶ。

拘束的プログラムはユーザの入力を待つためいくら計算処理が早くなっても待ち時間が出てしまう。 他のプログラムと結合するのも難しくなる。

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

ソフトウェアの本質は、データを処理することで、生成することではない。 その能力を最大限に発揮するためには、プログラムをフィルタとして動作するように設計すべきだ。

データを作るのは人間だ。 そのデータを上手く格納したり表示するのコンピュータで、データはプログラムのフィルターを通っている。

読んで感想

これからの設計やプログラミングに影響を受けそう。 特に「小さいものは美しい。」「各プログラムが一つのことをうまくやるようにせよ。」は保守性とテストを容易にしてプログラムの見通しもよくなる。 WEBシステムで言えば、APIにステータスによって処理を切り替えることはさせずエンドポイントを分けたりすることが良いかな。 最近、ドメイン駆動設計をどうにか取り入れようと試行錯誤しているので続けていきたい。

「全てのプログラムはフィルタとして振る舞うようにせよ。」を発展させたのが関数型言語な気がする。まだ、関数型言語は触ったことがないので入門したくなった。

リーダブルコードを読んでこれから書くプログラムが変わるように、本書のUNIXの思想に触れてこれからのシステム設計や自身の哲学にいい影響を与えてくれた。

UNIXという考え方―その設計思想と哲学 Mike Gancarz (著), 芳尾 桂 (翻訳)

Footnotes

  1. Atariは現代のコンシューマゲーム機の先駆け。OSとしては選択肢をできるだけ減らしユーザにはただ1つの方法しか与えず誰でも扱えるようにすることを目指した設計。 Wikipedia

  2. Microsoftが開発したOSで個人で扱かえるPCとして登場し、当時覇権をとったIBMのPCからの互換性を持つことで驚異的な普及をした。 Wikipedia

  3. Googleの仕事術で重大なリスクを早期の試作で洗い出して結果コストを抑えられる仕組み。SPRINT 最速仕事術は読んで面白かった。