「短いプログラムは無条件で正しい」 125
ストーリー by Oliver
極論万歳 部門より
極論万歳 部門より
takusi 曰く,"@ITのopinionの「ソフト開発を成功させる1つの方法」によると、「短いプログラムは無条件で正しい。なぜなら、短いプログラムは短いというだけで実行速度も速く、理解も容易であるからだ」そうです。より短いプログラムの方が良いというの分かるけど、それなら、プログラムを書かないのが一番、正しいですよね。"
UNIXの精神論もシンプルに簡単にしようのKISS。言語をうまく選べば(たとえばRuby)、同じ事もより簡潔でなおかつ読みやすいコードで出来るので、一理はありそうだ。
オブジェクト指向を否定しているが (スコア:4, すばらしい洞察)
ソフトウェアが行うこと(所謂機能)が複雑化すれば、コードは複雑にならざるを得ないのは明らか。
これに対して、プロセス単位での短さ、単純さとコードレベルでの短さ、単純さを同列に語るのは愚かである。
複雑なソフトウェアをクラスという単位に分割してコードを作成するのがオブジェクト指向である。
単純で短く完結したクラスを、パイプの代わりに関数呼び出し(メソッドコール)で組み合わせて大規模複雑なソフトウェアを構成するのである。
例にあがっている、クラスのメンバーの価を取得する巻数にしても、メンバーの価を取るのではなく、概念として存在する価を取ると考えるべき。その裏には、そのクラスが完結したソフトウェアとして成立するためのコードが存在するはず。メソッド一つ取りだして効率を語るのは全く無意味。
筆者は隠蔽の意味を全くわかっていない。
古きよき時代? (スコア:3, すばらしい洞察)
ただ、最近は、Winに限らず、Linuxでも、GUIのプログラムはでか過ぎる。
1.0がまじかのMozillaだって、どう考えてもバカでかいプログラムの一つです。噂ではApacheも2.0では、汎用性のために、巨大で複雑になるようですし。
小さいプログラムというのは、過去の古きよき時代の歴史物になってしまうのでしょうか。
rm -rf /bin/laden
Re:なんだMicrosoftの宣伝か (スコア:3, 興味深い)
というより、むしろC#がJavaより優れているという理由を無理矢理 でっちあげているようにも見えるな。
川俣晶って前にも 「C言語の処理系を作るために実際にyaccを使っているユーザーは全世界で十人ぐらいしか居ないだろう」とか書いた前科があるし、 「結論先にありき(すべてXML)で、現実を意図的に曲解する」という指摘もあながち外れてはいないなという気がする。
というか、私の中では吉田弘一郎や岩谷宏あたりと大して変わらない存在だったりする。
Re:古きよき時代? (スコア:3, 参考になる)
いーえ、今はまず
1.1次キャッシュから取れるか?
2.2次キャッシュから取れるか?
3.メモリから取って来るか?
で実行速度が大幅に変わりますから、時代遅れな考えではありません。
昔の「メインメモリ」が「CPUキャッシュ」、「ディスク」が「メインメモリ」になっただけです。
#容量的にもそんなもんだし。
反面教師 (スコア:3, すばらしい洞察)
「最近頭と気力がよわってきて、長いコードを扱うことや、
ライブラリやオブジェクト指向の勉強ができなくなってきました。」
っていうことなのでわ。
だから速いアルゴリズムにして長くなることも…とかは考えもできず、
ライブラリ知らないので全部自分で作ることになって混乱するからOOPが嫌になり…。
てなかんじで、よいプログラマになりたい方にとっては
反面教師以外のなにものでもない気がします。
Unix一般については (スコア:3, 興味深い)
KISSという言葉を使っているかどうかはわかりませんが、"UNIX Internals: The New Frontiers"(Uresh Vahalia)によると、Allman E.が1987年冬のUSENIXにて「小さいことは美しい」というUnixのphilosophyについて述べています。
ただし、注目すべきは同じ1987年冬のUSENIXでの、Dennis Ritcheの論文です。Ritcheはこの論文で以下のように述べ、Unixの問題点を指摘しています。
そういう意味では、"Keep it simple"が理解できる人に対して"Stupid"と言うのは実は失礼なのかも知れません。また、川俣晶と言う人は7年ほど前個人的に知っていた(当時NIFTY SERVEの某所によく出入りしていた)のですが、今思えばあまりRitcheの言葉が理解できる人ではありませんでしたね(その某所にいた人のうち私以外はみんなそのような感じでした。なにせほぼ全員WindowsNTしか使わんと言うところでしたから。ちなみに当時の私はSunOS4)。
この基礎知識は基礎的なところに間違いが (スコア:3, 参考になる)
すずきひろのぶ
抽象化や汎用性は必ず必要? (スコア:3, すばらしい洞察)
C++の例が象徴的だと思うのですが、確かにメンバ変数を直接触らず、メソッドを経由するのは、「基本的には」、良い設計だと思います。なぜなら、将来、クラスの実装を変更したとしても、プログラムの変更がクラスの実装だけに留まって、そのクラスにアクセルしている部分を変更する必要がないからです。いわゆる、実装のブロック化にも通じると思います。
しかし、ここで重要なのは、クラスの実装が変更されなければ、アクセス手段を抽象化する必要がないという点です。しかも、アクセス手段をインターフェイスによって抽象化しても、インターフェイスの変更が必要になったら、結局、クラスの実装の変更、即ち、プログラムの一部の変更ではすまなくなります。
何が言いたいかというと、アクセスの抽象化による変化への対応能力にも限界があるし、プログラムが無用に複雑化することという欠点もあるということです。
"書き捨てや変更に弱いプログラムの意義"
ある状況においては、保守や拡張が非常に困難な、いわゆる、書き捨てのプログラムや、汎用性や移植性、将来の変更に対する耐性を犠牲にしたプログラムというのも、「あり」ではないでしょうか。WinのCOMや.NET、あるいは、GNOMEのBonobo[GNOMEのFAQ]のようなものを利用すれば、単体のプログラムが小さいままであることが可能で、保守性や仕様の変更に弱いプログラムでも十分、実用的であることができると思うのです。もちろん、この考えは言語の支援だけでは、まったく不十分です。OSやライブラリの支援が必須です。
rm -rf /bin/laden
こういう記事を書くのは (スコア:2)
コーディングを早く終らせて/.が見たいからかな(違
短いと速い (スコア:2, すばらしい洞察)
それだと、短いプログラムは短いというだけで速い、と言うことができないよ。いや、Ruby は遅いって言いたいんじゃなくて、速さを追求する目的でプログラムを短くするのなら、プログラムを短くするだけのために言語をとっかえると当初の目的に反することになる可能性があるよ、って。
それに、一般論としても、短いほうが速いとは言えないと思う。
Re:短いと速い (スコア:2)
たしかに実行速度自体がトロいのは問題かも知れませんが、現状でスピードのみを求めるのはあまり一般的ではない気がします。現在のPCは十分な速度を持っているので、ヘタに高速と名打って書き換えるとバグの温床になりかねません。
> 一般論としても、短いほうが速いとは言えないと思う。
具体的にはどういう感じのときにそういう一般論が出て来るのか興味があります。
Re:短いと速い (スコア:2)
いまどきは Quick Sort は built-in かも。
一理ある (スコア:2, 参考になる)
あとモジュール化とか構造化プログラミングっていうのは(オブジェクト指向もかな)長いプログラミングを短いプログラミングに分割していいプログラムを作る技法ってことじゃないかなぁ・・・とか思ったりして。私見ですが。
/.configure;oddmake;oddmake install
Re:ループ (スコア:2, おもしろおかしい)
だって、CLIだとMSの.NETのCommon Language Interfaceになったしまうから。(笑
[C#という提案]
rm -rf /bin/laden
Re:ループ (スコア:2)
貶めるべき対象として、CUI と呼んだのかな?
CUI と CLI は違うと思ってますし、罫線素片使った画面好きなんですけど、流行らないな。
Re:古きよき時代? (スコア:2)
これからは小さくて軽いクラスライブラリの時代でせう (^0^)/
ああ、そういうクラスライブラリが欲しい、って自分で書けって? (^_^;;;
Re:一理ある (スコア:2)
構造化や OOP は複雑なものを適切な粒度にするしくみなので、問題を適切に分割できていれば、コードを把握可能な大きさにとどめることができるでしょう。
無条件に短ければいいというのも疑問に思います。
短いコードをシステムとして動かすために組み合わせる過程で、組み合わせの複雑さの問題に直面してしまいます。
はじめの設計が肝心という当たり前の結論になるのですが。
「一般的に言って」なんだろうけど (スコア:2, すばらしい洞察)
要するにこのお話は「一般的に言って」ということであって、現場で長くならざるを得ないコードを書く必要のある人には「勝手なこと言ってるよなぁ」というお話ではないかと思います。
極端に言えば
「一般的に言えば」人間は長生きしたほうがいいけど、そう言ったところで、いま病気の人とか、今日交通事故に遭った人とか、そういう現実と格闘している最中の人には「なーんにも役に立たない」。
というのと同次元のお話のような気がしますねぇ。
筆者は悪い人とも経験のない人とも思わないけど、本文中でご自分でも認めている通り、「いま、現場にいる人」ではない、というだけのことだと思う。
正直なところ、私も現場にはいない管理者だけど、こういったことは思っていても現場にあまり良い影響を与えないから、まず言わない。一般論なんていう役に立たないものを吐くくらいだったら、黙っていたほうが絶対に良い結果が出ると思う。
もっと、現場を信頼しなきゃ。管理者なら。
でも、普通は現場出身の管理者に限って、これ、できないことなんだよね。
「短いプログラムは無条件に正しい」という仮定をうけ (スコア:2, おもしろおかしい)
#だれか、Win95の方がDOSより短いと主張されたい方は?
短いプログラムは正しいなんて (スコア:2)
public void youAreWrong() {
System.out.println("嘘だろ?");
youAreWrong();
}
There is no spoon.
Re:オブジェクト指向を否定しているが (スコア:2)
というか、件の記事を読んだ限りでは、どうもこの人の理解は「オブジェクト指向 == 継承」なのではないかと疑わざるを得ませんね。
どうせなら (スコア:2)
クラスのメンバー (スコア:2, 参考になる)
メソッド一つが全体を形作る物じゃないし。
確かにコードは少なければ少ないほどデバッグ量も少なくなる。
ただ、そのコードを書くのにはどこまで気にしなくてはならないかという表面に現れるコード以外の部分も多いと思う。
局所局所がシンプルに全体をまとめ上げると言う手法はオブジェクト云々よりも構造化のほうだと思うんだけれども(笑)
kusanagi shin
Re:なんだMicrosoftの宣伝か (スコア:2)
言語仕様だけ見れば、C#は改良Javaなんで、的外れとは言えないと思います。
一々setter, getterを書かなきゃならないJavaより、宣言だけで済んでしまうC#の方が簡略なコードになるのは事実。
でも言語としては、実行系の実装やライブラリの充実の方が重要でしょうな。特に短いコードを書くなら、ライブラリが充実してるのが一番だし。
おっと、この記事だとライブラリも一々自分で書けってあるんだっけ (^-^;;;;;;;;;;;;;
Re:短い方が遅い例 (スコア:2, 参考になる)
確かにそうなんですけどね. 現実問題として性能を要求される場合にはコンパイラに任せることは不可能です. なぜかって言えばコンパイラからは見えない条件(例えば配列上のデータの並びの特性とか)が最適化に大きな影響を与えるからです.
これを解決する手段としては
ついでにもう一つ長さが性能に直結しない例を挙げると, データベースの操作に使うSQL. こいつはデータベースの構造に合わせた書き方になっているかどうかで性能が数100倍以上変わりますから, 長さなんて殆ど意味を持ちません.
Re:古きよき時代? (スコア:2)
だからこそ、bonoboなどのcomponent modelが注目を集めているのだと思いますけど。まだ理想には程遠いような気はしますが。
Re:反面教師 (スコア:2)
「思いどおりにプログラムを書こうと思ったら、趣味でプログラムを書きながら技術解説屋をやるしかない、ということである。」
Re:どれが正しい? (スコア:2, すばらしい洞察)
rm -rf /bin/laden
やりたい事を簡潔に表現できるのなら、長くても構わな (スコア:2, 参考になる)
昔書いた組込み用画像圧縮のコードなんか、そのコードを最適化するために書きなぐったコード群がなければ、何やっているのか数日悩むことになると思います。何もかも定数テーブルとビットシフトに化けてるし。
仕様を整理してみると、そんなプログラムは必要無い、と結論できる事がままあります。クライアントのやりたい事が理解できると、仕様もシンプルにできます。
やりたい事を簡潔に表現できるような、操作対象、概念を過不足無く自然に表したクラスライブラリを使い、作り、メンテナンスするのが、簡潔で品質の高いプログラムを書く王道だと思います。
ただ、自分は組み込み屋なんで、普段は最適化至上っス。速度のためなら、汚いコードも平気で書きます。ただ、仕様はシンプルに保つように努力しています。幸い、ハードも自作なんで……
これも極論? (スコア:2, 興味深い)
「コードを書くからバグが入る」
というのは絶対的真理では?
…これも極論?
現実世界は (スコア:2, 興味深い)
Larry Wall氏の言だったかと思うのですが(ソースを示せなくて申しわけない),
というような話があったと思います.だから, プログラムが短くなるということはそのバックグラウンド(Perl スクリプトに対する Perl Core) が複雑になります.要は誰かがプログラムで楽をする・出来るということは他の誰かが複雑なことをやっていることになるのでは?# エントロピーは変わらないってか?
Koichi
ネタになっている本は? (スコア:2)
川俣氏が20年前に読んだという本(この話題のソース)って何でしょうね。
当時、1980年頃といえば構造化プログラミング全盛でしょう。そんな時代にあって「短いプログラムは無条件に正しい」と断言すればちょっとは注目されたかもしれません。しかし、その私はそのような本を知らないのです。単に私の浅学(否定しませんが)のためだけなのか、その本の著者が読者を引き付けるために敢えて大げさな主張をしただけなのか知りたいところです。
条件が一切無い場合に限り正しく (スコア:2, すばらしい洞察)
Re:古きよき時代? (スコア:2, 興味深い)
そういやUNIXついては、「UNIXという考え方」という本が出てます。
が、俺としては、この本が言うUNIXのシンプルさってのが、どうにも釈然としませんでした。
というわけで
俺の文句を書き連ねたのがこちら(笑)
また、参考にしたのがGnomeの人の
Unixをもう少しましなものにしよう
http://tiki.is.os-omicron.org/?c=v&p=Unix%A4%F2%A4%E2%A4%A6%BE%AF%A4%B7%A4%DE%A4%B7%A4%CA%A4%E2%A4%CE%A4%CB%A4%B7%A4%E8%A4%A6
色々書いてあるけど一言でいえば、unixが言う「部品化」は、
処理の共有はともかくとして、状態の共有に無頓着な、
つまりエディタも作れやしない部品化方式、を
採用してしまってる、といえると思います。
これが天下のUNIXかと思うと、ちょっとがっくり。
天に唾を吐く行為 (スコア:2, すばらしい洞察)
●gotoの弊害を「数が少なければ大丈夫じゃん」と言ってる辺りが駄目。
●「UNIXという考え方」に通じるが、Pipe方式は部品化のうちの一部の側面しか解決しない。
それだけで諸手を上げて喜ぶとは、その程度で満足している人だ、ということだ。
半ば偶然の結果だが、GUIソフトのほうが往々にして状態の扱いが旨い、ので
大勢のユーザーがそっちに流れてる、という面は無視しちゃいかんでしょう?
●OOPを使えてない度にいたっては目を覆うばかり。(悪い意味での)爺ほどこういうことをほざいて逃げるんだよな。
●OOPが駄目だといってるくせにC#を持ち上げるとは謎すぎ。自分がナニを主張してるか?も理解してないのかな。
まぁ一般的に「改良されたコード」は正しいのだろう(とーとろじーだな)。
だが、あるコードを改良してみて、それが以前より長くなるか短くなるかは、神のみぞ知るんでわないのか?
Re:ネタになっている本は? (スコア:2)
言語の言及すらないので、まずそこから列挙してみるしかないでしょう。当時使われていそうなものというと、
ぐらいでしょうか。
この中で、Cについてはこんな話を聞いたことがあります。
これだけなら事実でしょうが、その受け売りでこんなことを言っているとしたらそれこそ帯域の無駄。
ちなみに、先の話を聞いた時の結びは、
でした。ですから、本質の上にガワをかぶせてしまえば、Pascalなら1行で書けることがCでは1行で書けないかも知れません。
Re:「短いプログラムは無条件に正しい」という仮定を (スコア:2)
Re:古きよき時代? (スコア:2)
GNOMEやBonoboが目指しているものについては別のコメントにあったリンクで読んでみましたが、どうもわからない点があります。
まず「状態」が何なのか。ちょっとcomputer scienceをかじっている人なら、Turing machineのヘッダの状態と考えるんでしょうか。もしそうだとすると、Bonoboはcomputer scienceにおける無謀ともいえる挑戦をしています。Bonoboの(機械的な)力で状態を正しく遷移させる、すなわちプログラムを正しく動かそうとしていることになります。プログラムを使ってプログラムが停止するかどうかもわからんのに、どうやってそんなことができるんでしょうか?
それから、プログラムの実行に関わるあらゆる状態をプログラムの各部分で共有したいのであれば、小さなオブジェクトを結合するようなモデルが本当にふさわしいとは考えられません(状態があちこちのインスタンスに散在するため、状態の一貫性を保つのが難しい。オブジェクトの外側はそんなことを気にしないが、内側では大きなコストを払うことになる)。それはむしろデータベースが解くべき問題と同じであり、巨大なデータモデルに対して各部分が必要なビューを定義するというモデルの方が、より問題の見通しがつきやすいし、実績もあるので納得できるのですが。
Re:ネタになっている本は? (スコア:2)
個人的に
という記法が好きじゃないというか、ん?、これって、qの大きさがpより大きかったらバッファオーバーフローぢゃん。バグだバグ~(勝手に騒ぐ)ちゅうかCならstring.hとか使うのが普通だよねえ。ライブラリ無いのかこの処理系は。
Re:ネタになっている本は? (スコア:2)
現代ならそういわれてもしょうがないですが、これを聞いたのは80年代後半なんです。当時はまだISO Cがなく、規格といえばせいぜいANSIぐらい、それも準拠できていたのは比較的新しい処理系だけという時代でした。Unix上の処理系はかなり苦しんでいました。
もっとも、DOSで規格への準拠が全くないmaster.libが流行ったことを考えると、ライブラリがあればよいというのも危険ではありますが。
訂正+補足 (スコア:2)
Turing machineの状態は、厳密には制御部の内部状態でした。ヘッダは状態を持つのではなくてテープ上で左右に移動できます。
また、Turing machineの変形として、テープを複数本用いるものはあります(テープを1本にまとめることは可能らしい)。が、制御部が複数ある変形Turing machineというのは聞いたことがありません。
Re:この基礎知識は基礎的なところに間違いが (スコア:2)
とりあえず日曜のうちに執筆スタッフMLには指摘してありますので、いずれ直ると思います。
"Quidquid latine dictum sit, altum videtur."
Re:オブジェクト指向を否定しているが (スコア:2, 参考になる)
従って、表現は難しいかも知れないけど、ふつーのCやアセンブラでもOOPは実現できるので(って言うか自分が設計からやれる時は、ドライバの類とかでもそうするように心がけている)。
所詮、C++だJavaだクラスだ継承だと言っても表現する道具。
必要な道具を必要な方法で使いやすく使うことが、プログラム書く上での基本だと思うし、ポータビリティやMPU資源消費の類とのバランスは設計段階で考慮すべき(言語の選定も含めて)。
# Javaは非常に優れたOOP言語ですが、JVMがかむので通常の組み込みでは
# 主言語にはならないのが、優れているが故に残念です。
逆に言うと、私がかつてJavaに心酔していて、某OSが乗っている関係でCを使う必要に迫られてJavaの手法を使ったから言うわけではないけど、道具に振り回されてあーだこーだと言うのは意味があるようで、実は無意味な議論なのではないかと思うのですが。
Re:反面教師 (スコア:2)
こういう考えの人がいるからいつまでたってもプログラムステップ数なんぞで課金されちゃうんだよ。と思った。
bonobo and COM (Re:古きよき時代?) (スコア:2)
COMについては OLE2のコンセプトが参考になりますかね。
Re:この基礎知識は基礎的なところに間違いが (スコア:2)
「書いた奴誰だ」と書いてたハズなのに……どうして消えてるのだ~
"Quidquid latine dictum sit, altum videtur."
Re:短い != 簡潔 (スコア:2)
変数のチェックを一々受け手がしなきゃならんと、トータルとしてステップ数は増えますから、あの指摘は逆にプログラムを複雑にする元ですな。
Re:古きよき時代? (スコア:2, すばらしい洞察)
例によって挑発的なボールを投げてくれるんで...
はい。Turing machineに対する無謀さと、システムプログラムの方法論に対する無謀さの2つがあります。前者はすでに述べたので、後者について。
システムプログラム、例えばOSやDBMSなどのミドルウェアの開発では、システムの全体像を把握すること、それに基づいてシステムを決定論的に動作させることが伝統的に行われてきています。これは開発者がシステムの各要素の挙動をすべて管理できるという前提の上に成り立っています。
これに対し、要素を分散させるモデルを取り入れると、その瞬間に管理者は分散した要素の挙動を把握できなくなります。これは管理者をfatal pointにしないという分散化のセールスポイントにはなるものの、システム全体を決定論的に動かすことが不可能になります。どこかにある要素が何か予測がつかないことをやらかす危険性が付きまとうわけです。分散DBはまだいい方です。スキーマがgivenであるため、状態のcoherencyを保証することはまだ可能です。しかし、Bonoboのようにプログラミングモデルにこの問題を持ち込むと、スキーマで縛ることはまず不可能です。だれかがシステム全体を乱すような変なオブジェクトを作らないという保証はありません。
管理者の見えないところでも要素が自分で動いているとなると、むしろ人間の活動に似せてモデル化する方がまだうまくいきそうです。例えば、人工言語がものを一目見ただけで決定論で力押しできるのと違い、自然言語は統計的処理など、多くのデータの素性を幅広く眺めるやり方をして初めて使いものになったように。少なくとも、伝統的なシステムプログラムの方法論をどこかで捨てる必要はあります。
Re:短いと速い (スコア:1)
同意します。一般的に、単純な処理の性能を改善するには、アルゴリズムを複雑にする必要があります。
でも、ここで言う速いというのは、起動が速いとか、メモリの消費量が少なくてはやいとか、そういう類いのものだと思います。
rm -rf /bin/laden
Re:短いと速い (スコア:1)
たとえば、1次元のlist構造を実装するのに、後にaddするのと、先頭にaddするのでは、先頭の方が圧倒的に単純化され、コードが短くなります。
一方、ふつ~(何がふつ~かはおいといて)にリスト構造を考えると、前から順番に並んでいる(topポインタは先頭アイテムを指す)という発想になりがち。
こういう発想の転換で頭を使うのと、真っ向から複雑なアルゴリズムのコードをデバッグするのではどっちが生産性が高いかは明らか。
一方で、プログラマの能力はこういう処に現れるという見方をできるかも。