CLOSE

プログラミングのことわざ〜Rubyの父が語る教訓と知恵〜(全4記事)

巨大なタスクに圧倒されそうな時は“分割統治”で征服せよ ゴールまで走り続けるために有効な考え方

技育祭は「技術者を育てる」ことを目的としたエンジニアを目指す学生のための日本最大のオンラインカンファレンスです。「技育祭2023【春】」に登壇したのは、Ruby開発者のまつもとゆきひろ氏。プログラミングの体験の中で実感した、ことわざや格言について話しました。全4回。3回目は、「分割統治」について。前回はこちら。

大きな問題も分割すればなんとかなる

まつもとゆきひろ氏:次のことわざにいきましょうね。4番目は、これもことわざじゃないと言われちゃうんですが、「分割統治」という言葉です。英語だと「Divide and Conquer」。「分割して征服せよ」という感じです。大きな問題もね、分割すればなんとかなるというやつですね。

(スライドを示して)これは最近見た漫画です。巨大なタスクが存在して、圧倒されそうな気持ちになった時には、タスクを取り上げて細かく分解すると、細かく分解されたタスクは無視しやすいので、タスクは片づかなくても気分は楽になるという漫画なんですけども(笑)、実際、そういうところもあるんですよね。

非常に巨大なことをしろと言われると大変なんだけど、手に負える範囲に分割して1つ1つ話をしていくと問題を解決できるというのは、どこにおいても応用可能な原則だと思います。

クイックソートは一応現時点で知られている最速のアルゴリズムと言われていますが、最速のソートアルゴリズムは、この分割統治法を使っているわけです。

エレメントの中からピボットという1つの要素を選んで、その要素より大きいか小さいかで2つに分割して、それをまた分割していって、ある程度小さくなったら適当な方法でソートして、またそれをマージしていくという感じのやり方をするのがクイックソートですね。

例えば仕事で「ソフトウェアを開発しろ」と言われて、「『ファイナルファンタジー』や『モンスターハンター』と同じぐらいの規模のゲームを作りなさい」というタスクが降ってきたとしたら、みなさんだいぶ圧倒されるわけです。

私が子どもの時は、雑誌に100行とかでゲームのソースコードが載っていて、パソコンのBASICでポチポチ打ってそれで満足みたいな感じで、非常に原始的で良かったんですが、現代におけるゲームは、「作るのに100億円かかります」みたいな感じになっていて(笑)、映画を作るのと変わらん感じになっているわけです。

そういうタスクをもらった時はだいぶ圧倒されるわけですよね。もちろん1人でもできない。

私の場合も、例えば「世界的に使われるようなプログラミング言語を作る」というタスクをやろうと思ったらですね、だいぶ圧倒されて、それはとても無理だと思うわけです。

実際に私は最初から世界的なプログラミング言語を作って、プログラミング言語だけで食べていけるようになろうという現在の状態を夢に見ながら活動していたかというと、あまりそんな感じではないんですよね。

例えば、「Yacc」という文法を定義する言語があります。Rubyという言語はどんな文法になるでしょうか? というのをYacc記述だけを作って考える。

Yaccで記述をコンパイルすると、文法チェックができるんですね。シンタックスエラーだけが検出できます。僕はRubyでは、こういうプログラムが書けるといいなと思っていたんですよ。

ファイルをこの文法チェッカーにかけるとシンタックスエラーが出なかったので、この文法は合っているに違いないとか、あるいは、「これは間違ったRubyのプログラムだと思うんだけど」といって、その文法チェッカーにかけるとシンタックスエラーと言われて、あぁ、そうそう、文法ってこういうもんだよねとわかる。そこから始めて何年もかけて、少しずつ作ってきたんですね。

例えば、今日はこの関数を完成させようとか、あるいは、このバグを見つけちゃったから、今日はこのバグを直そうとか、そういうことを一つひとつやってきたというところがあるわけですよ。

相互に依存する関係を最小にする「分割統治」でゴールまでたどり着く

すごく前に読んだ、マラソンランナーのインタビューですが、42.195キロという距離……私はそんな距離を走ったこともないので想像もつかないんですけど、最初から42.195キロを2時間何十分で走ろうみたいなことを考えると、だいたいの人は圧倒されるんですよね。

だけど、そのマラソンランナーが言ったのは、もう走ってすごくしんどいんだけど、そのしんどい中でも、向こうの角にある100メートル先の電柱までは諦めずに走ろうとか、そこの電柱を過ぎたら、その次の200メートル先の電柱まで走ろうとか、そういうふうにして進んでいったと。

そうしたらゴールまで走り続けることができた。もう100メートル走ろう、もう200メートル走ろうということを繰り返していくことによって、42.195キロ、人によってはとてもとても限界を超えないといけないような距離でも走れるということをインタビューで読んだことがあります。

分割統治というのは基本的に、相互に依存しない小さな部分に分割して、1つずつ片づけるというのが基本的な戦略なんですね。

相互に依存しない小さな部品にバラバラにした後であれば、その個別の部分を、ほかの人に「ここ、やっておいてくれない? インプットはこれでアウトプットはこれだから」と出すことができるんですね。

そのためには、繰り返しになりますが、相互に依存する関係を最小にすることが必要です。

ものすごく複雑なネットワークが存在している時に適当な状態でバラバラにすると、それぞれのモジュールからよそに対する関係が非常に複雑になってしまいます。この機能に手を入れるためには、あのチームとこのチームとそのチームとの間でミーティングをしないといけないという話になると、結局分割した意味がないですよね(笑)。

そうじゃなくて、相互の依存を……できるだけそのチームだけで完結して仕事ができるような状態にするのが、分割統治の基本的な戦略になると思います。

これはもちろんアルゴリズム的な話が元になっていて、分割統治でやる数学の解法などけっこうありますが、それだけではなくて、例えばプロジェクトの進行であるとか、仕事のやり方であるとか、結局仕事だけじゃなくて、あるいはタスクの管理など、あらゆることに使えるんですよね。

例えば今日、「なんとかということに対して小論文を書いてください」という話になった時も、テーマを集めるとか、あらすじを考えるとか、そういうタスクに分解していって、一つひとつやる。

「ええっと、こんなに文章を書かないといけないの?」と言って圧倒されているところを、一つひとつ解決していくことによって、ゴールまでたどり着くことができるので、自分の生き方に応用できることわざなんじゃないかなと思います。「分割統治」ですね、ぜひ覚えて帰っていただければと思います。

人間は忘れやすく、複雑さを把握する能力もあまり強くない

今4つ(笑)? 次、いきましょうね。「簡潔さは力なり」。「Succinctness is Power」ですね。

これも言った人ははっきりわかっていて、ポール・グレアムさんという人が言いました。この人は、昔「Viaweb」という名前のショッピングサイトのバックエンドを作った人です。今でいうと「Shopify」みたいなやつですね。

それをアメリカのYahoo!Storeに売却して大金持ちになったので、Y Combinatorという超アーリーステージのベンチャーキャピタリストになったんですね。

ここ(Y Combinator)がお金を出したところは、たくさんあります。たくさんの企業が軌道に乗っていて、例えば「Dropbox」はY Combinatorの卒業生ですし、若い人にアイデアを持ってこさせて、「こんなアイデアを思いついたあなたに投資しよう」みたいな感じで応援する。あるいはメンタリングといって、指導をしているところです。

ポール・グレアム自身は、Y Combinatorをすでに引退しているらしいですが、Y Combinatorという組織は、いろいろな人を助けることになっています。

この人は、もともとLispハッカーでViawebもLispで書いたという、ちょっと変わった人なんですけれども(笑)。その人が言っているのが、この「簡潔さは力なり」です。彼は、エッセイを書いていて……(コメントを見て)そうそう、誰かがチャットで書いてくれましたが、『ハッカーと画家』という本を書いている人ですね。

何を書いているかというと、まず、人間の能力にはそもそも限界がある。人間の能力には限界があって、あまり難しいことを把握できないんですよね。例えば記憶力には限界があって、よく人間は忘れるんですよね(笑)。

私もだいぶ忘れっぽいのでしょっちゅう怒られます。約束しているのを忘れてダブルブッキングしちゃったみたいな(笑)。一応気をつけてはいるんですけど、たまにやっちゃうんですよね。記憶力には限界があるということですね。あと、子どもに「お父さん、その話はもう10度目ぐらいだよ」と言われたりもするんですけれども、そんな感じですね。

それに関係して、複雑さを把握する能力もあまり強くないんですよね。システムや、関わっているものが多くなってすごく複雑になると、一度に考慮しなくちゃいけない要素がすごく増えてしまう。そうすると、正しい選択をすることができない、正しい判断をすることができない。それは人間の能力の限界なので、ある程度はしょうがない。生物学的限界なので、しょうがないっちゃしょうがないんです。

さっき言った分割統治も、複雑さを扱う限界に対して細かくすることによって、一度に考えなくてはいけないことを減らすという部分で、少なくとも人間に対して適用する場合にうまくいくという側面があるんですよね。

結局、我々が人間として仕事をする時には、複雑さを制御することが必要なんですね。

残念ながらプログラミングと世界は、ものすごく複雑になりがちです。例えば物理的実体がある存在、建築物とかでもいいんですけど、制約があるんですよね。あまり鉛筆みたいに細いビルを建てると地震で崩れるとかですね、物理的な限界は超えられない制約があるんですよね。

物理法則というのは変えられないので、ある程度以上複雑だったり、脆弱だったりする構造を作ってしまうと、成立できないんですよね。

「プログラムは、人間が表現すべき内容が簡潔になるように進化してきた」

厳密に言うと、プログラミングの領域にもそういう物理法則の限界はあります。ハードディスクの容量の限界や、人間がその処理時間に耐えられないというパフォーマンスと人間の忍耐力の限界など、そういう限界はあるのはあるんだけど、ただ、構造の複雑さに対する限界は、非常に緩いんですよ。

現代の我々のコンピューターには、例えばTB単位の記憶容量があるんですが、「GPT-3」のモデルのデータって850GBぐらいなんですよね。

これは、人類がかつて書いた文章の構造を認識して、コンピューターが人間と同じようにしゃべれるぐらいの知能が持てるだけの複雑なデータが、みなさんのお手元のハードディスクに収まるサイズなんです。

それを考えると、チームで寄ってたかって作っていると、人間の理解を超える複雑さになりがちなんですよね。そういう複雑さになってしまうと、どうにもならないわけです(笑)。

それも、上手に作らないとジェンガみたいになるわけですよ。物理的限界のないジェンガって、もうなんかやってられない感じがします。1本抜くと全部崩れるかもしれないので、手がつけられないということが起きるわけですね。やっていられないわけですよ。

どうにもこうにも、この複雑さを制御しないといけないんですよね。逆に言うと、その複雑さを制御すると、人間の生産性は上がります。

最初のプログラミング言語であるFORTRANができたのは、1954年と言われていますから、2024年で70年になるんですね。最初の頃はFORTRAN1個しかプログラミング言語がなかったんですが、今は……今いくつプログラミング言語があるかは誰も数えたことがないのでわからないんですがど、一説には数万とか数十万とか言われているんですね。

その間、プログラミング言語は少しずつ進化してきているわけです。その進化の系統の中で、ポール・グレアムは「プログラムは、人間が表現すべき内容が簡潔になるように進化してきた」と言っているんですね。

その結果、新しいプログラミング言語を使うことで、ソフトウェアのコード、プログラムはどんどん簡潔になっているし、これからますます簡潔になるべきだというのが、ポール・グレアムの主張なんですね。それは、本当にそうだなと思います。

例えば同じことをするにも、アセンブラ、C言語、Ruby、Pythonでは、だいぶ行数が違うわけです。

一説によると、人間が1日に生成することができるコード量は、言語によらず一定であるという仮説があります。人によって違うかもしれませんが、すごくがんばって、だいたい数千行から1万行ぐらいと言われています。そうすると、例えばアセンブラで1万行書くのと、Rubyで1万行書くのとでは、Rubyのほうが抽象度が高いので、だいぶできることが違う気がするんですよね。

そういうことを考えると、プログラミング言語の進化というのは、より簡潔になることによって人間に対する負荷を減らすというところにあるんじゃないかなと思います。

ソフトウェアを開発している時は、本質的に問題が複雑なので複雑になりがちですが、そのソフトウェアが必要以上に複雑になっていないか、もっと簡潔に書けるんじゃないか、ともし感じたとすれば、その複雑さは間違った方向性ではないか、それを減らす方法はないか、減らすことによって正しい未来をもたらすのではないかについて、考えるタイミングではないかなと思います。

実際、RubyとかRuby on Railsとかが登場してくる前のソフトウェアに比べて、後のソフトウェアのほうが、RubyやRuby on Railsの影響もあって、例えばWebアプリケーションの開発がだいぶ簡潔になっている、簡単になっていると思うんですね。

それは、プログラミング言語やフレームワークの進化によってもたらされた簡潔さであり、望むべき進化だと思うんです。

ただし、どこでもそうなんですが、「正しい」というのは厳密には定義されていないので、誰にとって正しいのか、どういうふうな見方から、視点から正しいのかというのは、いろいろ考えないといけないという感じですね。

型の表現ということに関しては、もう一波乱あるんじゃないか

プログラミング言語の領域だと、動的型・静的型というのは非常にホットなトピックで、ずっと言われています。正直に言うと、現代ではGoとかRustとかHaskellとか、静的型のプログラミング言語のほうが人気が高いんですよね。

ただ、さっきまで言ってきた簡潔さという観点からいうと、型宣言がそもそもない時点で動的型のほうが簡潔なんです。型は便利ですよ。静的型が要らないと言っているつもりはないんだけど、静的型の記述は、必要以上に複雑になりがちなんですよね。

最近、TypeScriptの静的型についての論文を読んだら、TypeScriptの型の部分はチューリング完全であると書いてあったんですよ。

どういうことかというと、型宣言の部分だけで任意のアルゴリズムが記述できるということなんですね。TypeScriptの型だけで三目並べ、Tic-tac-toeのアルゴリズムが書けるという例があって、「VSCode」の型補完で、型の部分だけ書き換えると三目並べが解けちゃう(笑)。

タブを押すたびにポップアップで三目並べの答えが出るというプログラムを書いていました。いや、念のために言っておくけど、静的型は便利ですよ。だけど、「それは必要な複雑性なんだろうか?」と悩む時があるんですよね。人間に見せていい複雑性なんだろうか? という感じなんですね。

それを考えると、将来、型の表現ということに関してですね、もう一波乱あるんじゃないかなという気がしています。

(次回へつづく)

続きを読むには会員登録
(無料)が必要です。

会員登録していただくと、すべての記事が制限なく閲覧でき、
著者フォローや記事の保存機能など、便利な機能がご利用いただけます。

無料会員登録

会員の方はこちら

この記事のスピーカー

同じログの記事

コミュニティ情報

Brand Topics

Brand Topics

  • 1年足らずでエンジニアの生産性が10%改善した、AIツールの全社導入 27年間右肩上がりのサイバーエージェントが成長し続ける秘訣

人気の記事

新着イベント

ログミーBusinessに
記事掲載しませんか?

イベント・インタビュー・対談 etc.

“編集しない編集”で、
スピーカーの「意図をそのまま」お届け!