アプリケーション開発の世界観です。
テキスト処理を行うのであれば、内部のテキストデータをバッファに保持する必要があります。
巨大なテキストデータやストレージを扱う上で、考える必要があるのは断片化と永続化の問題だと思います。
ストレージやファイルシステムなどで、データの途中にデータを保管したい時に、単純に全てひとつの記憶領域やブロックに保管を行うと、挿入や変更に時間がかかります。かといって複雑に別々の場所に保存すると、ストレージが断片化する恐れもあります。
また、バッファやインスタンスのデータをメモリだけに保持していると、プロセスが終了した時に消えてしまいます。こういう時は永続化(プロセスが終了してもデータが存続できるようにデータを保存すること)を行わなければいけません。
コツとして、データを読み書きしたり表示したりする際に、テキストデータであれば、バッファのサイズは4096などと決め打ちにして、少しずつバッファに読み込んで表示するようにすると、メモリの使用量を少なく抑えられます。
プログラムを開発するコツは、「プログラムに必要な機能をよく分析すること」です。
たとえば、テキストエディタを作るのであれば、バッファに文字列を格納し、テキストエリアに整形して表示する機能がまず必要です。バッファが更新されたら、ビューも更新しなければいけません。
また、ファイルから読み込む機能、ファイルに書き込む機能も必要です。
また、検索や置換、あるいは比較のような機能があると、テキストエディタらしくなるでしょう。テキストエリアには、キーワードを色分けする機能(シンタックスハイライト)があると良いでしょう。
機能を分類できたら、今度はどのようなクラス設計でそれを実現するかを考えます。まず、バッファをメンバ変数としたエディタークラスを作ります。同時に、シンタックスハイライトとビューの常時更新機能をつけたテキストエリアコンポーネントを作ります。同時に、ファイルを管理する開く・保存機能を作ります。最後に、検索と置換の関数を作ります。これらをまとめて、エディタークラスに実装します。
常時更新機能を実装するには、バッファを編集するのに専用のインターフェースを設けて、テキストエディタにビューを更新する関数を作り、バッファのインターフェースが呼び出されたら、必ずその更新関数が呼び出されるようにします。この更新関数はどこからでも呼び出せるようにして、ファイルを開いたり保存したり、設定を変えた時にも呼び出します。また、シンタックスハイライトを作るには、テキストエディタコンポーネントが表示する処理を行う時に、バッファ読み込みとビューの表示の間に介入して、ひとつひとつのキーワードを解析し、その情報をテキストにタグのような形で付け足して、表示する処理の部分で、テキストに付属された情報の通り、テキストエリアで文字色を変えてフォントを表示するようにします。
そのように、どんな機能が必要かを考えることで、クラスの設計もしやすくなります。
2018-01-24より。
ワープロを作るために必要なのは、
・データの保管と読み書きをするデータオブジェクト
・文字や画像を表示する配置オブジェクト
・データオブジェクトと配置オブジェクトの変換をするメソッド
・配置オブジェクトを表示するメソッドとビュー
・ビューを操作した時に配置オブジェクトとビューを更新する描画モード
・配置オブジェクトの編集機能
ではないかと思う。
きっと、ブラウザなども同じ要領で作れる。MFCにはドキュメント・ビューという概念が存在するが、僕はそれには詳しくない。
基本的に、配置メソッドは四角形の領域を表示するようにして、表示メソッドによってビューに「全ての配置オブジェクトを表示する」機能をつけて、描画モードによって操作に応じて部分的に配置オブジェクトの表示を更新する機能をつける。そして、保存する時はデータオブジェクトに変換すれば良い。
オブジェクト指向は、クラスによってデータとメソッドを一体化させ、その上でメモリの管理をオブジェクト単位で行い、オブジェクトを簡単に作成・削除し、グローバル変数のようにクラス内部のメソッドからオブジェクトのメンバ関数を処理するものだ、と考えると良く分かる。
Webブラウザ開発を参照のこと。
プログラミングの基本は、「必要なたくさんの処理を、簡単にできるようにすること」です。たとえば、文字列の解析を行うのであれば、文字列の解析をする部分であるparse()関数を作って、解析を行いますが、この中で必要な処理の全てを書いて、parse(bytecode, in)と記述したら、簡単にinをbytecodeにパースできるようにします。これが、プログラミングの基本です。たくさんの処理を1つの関数にして、その関数を使うことで何度でも簡単に同じ処理を行えるようにする。あとは、ただそうした関数群を作ります。たとえば、bytecodeをアセンブリ言語に変換するconvert()関数を作り、convert(out, bytecode)などとします。ここで、parse()関数とconvert()関数の中で、変数定義をmvに変換するvar_convert()関数、if文やfor文や関数定義を機械語に変換するif_convert(), for_convert(), func_convert()などを作りましょう。実際のコンパイラの開発では、トークンの解析にはlexやyaccを使い、三番地コードと呼ばれる形式のコードに変換していきます。この中で、きちんと定義する必要があるのは、中間コードであるbytecodeオブジェクトをどのような形式のデータ構造にするか、といったことになるでしょう。
コンパイラ開発の世界観も参照のこと。
たとえば、カーナビのシステムを作る場合。まずは、地図データがあります。この地図データを、まず、変数に格納します。
そして、機能を作る前に、マッピングとして、地図データの基本的な操作メソッドと、ディスプレイやモニター画面に地図を表示する関数群(API)を作ります。
そして、基本的な地図の機能、たとえば拡大・縮小、回転、移動、のような機能を作ります。これは画像的なライブラリを使うと良いでしょう。
地図を解析して、道順を知るための機能は、まず、膨大な地図データをデータベースに登録します。そのために、画像から自動で地図データの「属性」を取得し、自動で登録する解析プログラムを作ります。
このデータには、道路の長さと、必要な移動時間、そして道路の右端と左端の位置情報や、道の分岐の情報を登録します。
そして、現在地と目的地の位置情報から、「どんな道のりのパターンがあるか」を、道路の右端と左端の位置情報や分岐の情報を上手く繋ぎ合わせることで、全パターン洗い出します。
そして、それぞれのパターンにかかる時間を計算し、それをソートして完成です。
その上で、さまざまなナビゲーションに必要な機能(道のりを別の色で表示したり、状況に応じてナビゲーションする機能)をつけて、カーナビのシステムを作ることができます。
このような場合にも、必要なのは、「データを保持する部分と、そのデータを操作する関数の部分を作ること」です。
さらに言えば、「どの道からどの道に繋がるか」というリンク情報をデータベースに登録しておくと、あとあと便利かもしれません。また、さまざまなボタンやメニューを作って、イベント駆動のメソッドを書く必要があるでしょう。そして、きちんと動くかを確認するために、テスト関数のようなものを用意して、さまざまな条件と結果をチェックするようにしましょう。現在位置を取得するGPS機能や、現在位置の変化とともに画面を移動させていく「リアルタイム解析機能」も必要になるでしょう。
2019-11-17より。
コンピュータが可能としたのは、「システム構築の簡便化」だけではない。彼らはインターネットという「世界中のつながった、誰でも参加できるオープンな仮想空間」を作った。インターネットは、コンピュータ技術を楽しみにする以上に、僕は将来においてとても重要なものになると思う。それは、「インターネットをいかに利用するか」はまだまだ未知数だからである。だが、僕はそうした「未来のインターネット」は、おそらく、そんなに良いものにはならないと思う。それは、タリバンやISのようなテロ組織がインターネットを「支配と戦争のために利用する」からである。彼らはインターネットを最後の戦場として、アメリカのインターネットとイスラムのインターネットが互いに争うようになる。だが、僕はこうした「戦争のインターネット」は一時的なもので、そのうち、「インターネット憲法」が定められると思う。だが、憲法が決まってしまえば、インターネットは自由が無くなり、つまらないものになるだろう。今のように、オープンに参加し、何をしても処罰されないインターネットではなくなる。義務と法律がインターネットに生まれた時点で、インターネットの価値は無くなり、ただのコモディティ的なものへと劣化することだろう。ただ、それでも、インターネットの「世界中を繋げる可能性」は未知数で、無くなるわけではない。だから、たとえば、現実世界とは本当に全く違ったコミュニティができる可能性もあれば、現実世界の中で何かをするためにインターネットをもっと利用するようになる。こうした発想は、今、まさにどんどん生まれている。だが、今までの「Webページ」を使ったインターネットには限界があるかもしれない。もう一度、誰かが「本当の分散ネットワーク」を作る可能性はある。だが、単純にWebページを見るだけ、というスタイルそのものが変わってしまうことは避けたい。インターネットの良さは、ページをブラウザが表示するという、「誰にでも分かる単純な社会の仕組み」に存在する。これを複雑なアプリケーションにしても、それは流行ることもなく、インターネットそのものの分かりやすさや自由度を劣化させるだろう。
僕が思うに、SNSのようなものはそのうち流行しなくなる。逆に、2ちゃんねるのようなシンプルな仕組みを持った掲示板サービスに対して、専用ブラウザのような「高度なことも必要に応じてできる」ようなソフトウェア技術は発達する。IRCで良いじゃないかという意見はあるかもしれない。だが、僕は「シンプルなSNS+専用ブラウザ」という発想が良いと思う。SNSは高度かつ複雑になりすぎている。シンプルに使える、一目で分かる新しいSNSに対して、たくさんの機能を提供する専用クライアントがあれば、僕はそれが正しいと思う。そして、サーバー側は、アカウントとデータの管理しか行わない。ビューは単純なものを表示し、データベースの中のデータはどこからでも、どんなクライアントからでもアクセスできる共通のものを更新・管理する。そして、クライアント(専用ブラウザ)の側から強力な機能を提供する。たとえば、全てのSNSを見て、その中でどんな書き込みがあっても最新の情報をスマホに通知するような、そういう仕組みをクライアントとして提供する。まさに、これが昔の2ちゃんねる専用ブラウザである。サーバー側は可能な限り単純化し、データの保持と提供しか行わない。クライアント側は可能な限り自由にし、何でもクライアント側のアプリケーションでできるようにする。サーバー側のシステムも、クライアント側のアプリケーションも、全てオープンソースにする。オープンソースにしない商用の業者がアプリケーションを作っても良いが、オープンソースのものも必ず用意する。
また、サーバー側のブレイクスルーとして、たとえばP2Pのように分散ネットワークにすることも考えられる。クライアントを専用アプリケーションにするのであれば、今のWorld Wide Webの仕組みを継承する必要はない。誰もが簡単にページ(ホームページと同じ)やグループ(掲示板と同じ)や、ニュース、ブログ、つぶやき、拡散・シェア・通知の機能などを、この「シンプルSNSサーバ」に実装し、クライアントがそれぞれの独自の「操作スタイル」から操作することができるようにする。つまり、データベースには、その投稿の内容と、その投稿がどんな意味を持っているかという情報を管理し、常に更新されるようにするための「P2Pサーバ」(そもそもP2Pはサーバー・クライアントシステムではないため、この名称は適切ではない)となり、クライアントは、P2Pサーバの適切なデータを操作するものとなる。それぞれのノードが常に情報を発信し、全てのプラットフォーム(Windows, Linux, Mac, スマホなど)に対してオープンに公開され、どんな風にその情報を整形して操作しても良い。インターネットと違う一番大きな点は、サーバーを構築する必要がない、ということ。レンタルサーバーを使って、有料でサーバーの費用を負担する必要がない。それぞれのノードは「共同体自治区」を形成する。自分の共同体自治区に含まれている人々の情報は、自分が共同でホストする。サーバーをレンタルせずとも、情報をP2Pで発信できる。動画サイトも漫画サイトもフリーソフトのダウンロードも可能にする。ただし、Winnyを目指しているわけではなく、匿名通信や第三者の仲介を基本にはしない。
ただ、本当のところを言うと、このネットワークでは自分たちの共同体自治区を共同でホストするだけを今までのWebサイトと同等に行うため、クライアントプログラムの実装を少し工夫すれば、匿名ネットワークや第三者が介入するアップロードやダウンロードの仕組みは実現できる。だが、これは全く逆のこともできることを意味する。すなわち、犯罪者のWebサイトや犯罪ファイルのようなものは、自分たちの共同体自治区から締め出してしまえば良い。たとえば、子供たちが見るページの共同体自治区は、その子供たちが使うアプリケーションが共同でホストするため、「自分たちの意に合わないサイトは全て消す」といったことができる。だが、これはある意味危険である。中国人が政府の批判を書くために、匿名ネットワーク機能をONにした上で、少しでも政府寄りのメンバーを全て排除することができる。おそらく、Winnyの開発者はそういうネットワークを開発したかったのだろう。
検索エンジンより。
検索エンジンを作るためには、並列処理を用いて全データベースを一度に一気に検索する必要がある。
たとえば、ひとつの単語を高速に検索するためには、その単語を一瞬で検索するために、全データベースで並列で検索を行う。
難しいのは検索を行う処理ではなく、データベースをどのように常に最新にするか、という「ロボットクルー技術」と、どのような順番で表示するか、という「ランキング処理」である。
GoogleはPageRankというアルゴリズムを用いて、「多くのページにリンクされているページを優先的に表示する」という方式でページを表示している。これは各サイトに含まれる別ホストへのアドレスへのリンクをロボットが収集し分析しながら、各ページをランキングにすることで実現できる。
また、常にロボットがWeb全体をクルーし、最新の内容をデータベースにキャッシュすることで、Web全体の検索を可能としている。
2019-12-27より。
僕は、最後に、この世界を僕を王とする王国に変える。
実際のところ、民主主義や社会主義の指導者には何もできない。支持層の意見を聞く必要があり、自分の好きな政策は何もできない。
自分の政策を行いたいのであれば、独裁者になる必要がある。
そして、世界全てを変えたいのであれば、EUの大統領であることがもっとも適切である。
僕は、ドイツの保守右翼と社会主義者とキリスト教徒とユダヤ人の支持を取り付け、ドイツの首相となり、そのまま、EUの大統領となる。
必要なのは、僕個人の権力を頂点とする、ひとりで決められる権力である。
僕は、自らコンピュータシステムを設計し、運用することで、ひとりで全てのことを決める。この世界の全てのことを、自分独りで決める。
また、コンピュータ・ネットワークが普通となった現代社会で、国を統一し各国のそれぞれの首脳が支配し外交する政治モデルは必要ない。
僕は、コンピュータを使った自動管理によって、分国行政を実現する。それぞれの国民の意見を聞いた上で、それぞれの国民に対して適切な行政サービスを、コンピュータが自動で管理し、どのような変化に対してもリアルタイムでその変化に対応する。そのため、きめ細かいサービスを行うこと、それぞれの国民に対して「本当に必要な支援」を適切に行うことができる。
また、法律からどのようにすれば適法かを判断する「法律AI」を作り、この法律AIが全ての会社に対して適切な契約と給与の支払いを行う。全ての人間の個人情報と労働状況をこのシステムはリアルタイムで監視し、全ての会社・全ての労働者に適切な給与の支払いを命じる。自由でも平等でもなく、必要な給与を必要な額だけ与える。
また、国家の政策は全てコンピュータシステムの設計の時点で決まっており、適切な場合に適切な政策を実行する。どんな時代の変化にも対応するために、万全のコンピュータシステムを設計・実装する。
僕は、このシステムをRed Hatとともに作る。僕がRed Hatのチーフマネージャーになる。
また、EUの大統領となった僕は、ロシアと友好する。そのため、「EU・ロシアの巨大な文明圏」を僕は作り上げる。そのうちそこに中国やインド・中東やアフリカも加わり、僕は世界政府の皇帝となる。
システムの最初のバージョンは、それくらいのシステムを作って役所を自動化する。難しく見えて簡単である。法律と現実の人々の置かれた状況を照らし合わせながら、適切に「与えるべき金」を計算すれば良い。また、システムの以後のバージョンでは、格差を徐々に再分配によって平等に近づけていく機能や、失業者がでないよう全員に適切に雇用を与える機能を作る。これも、ただ条件と状況が増えただけであり、すぐに実現できる。ソフトウェアの設計自体は簡単で、3か月から6か月ぐらいの時間で実現できる。だが、データを集めることが難しく、制度や仕組みを運用するために必要なことが多いため、どこかにあるデータを使うのであっても10年はかかるだろう。制度や実際の社会に導入するのは50年単位の時間がかかる。
また、プログラムとは何であるかを一言で言ってしまうと、「ルーチンを用意し、そこにデータを渡すこと」ではないかと思います。
たとえばウィンドウシステムであれば、ウィンドウの中にフォームやダイアログを表示する機能が必要ですが、これを作るためには、「どんなフォームの画面データが来ても、適切な大きさでそれを表示する」ことです。
この時、具体的にどんなフォームであるかなどは考えません。することは、どんなフォームであっても対応できるように、あらゆるフォームを表示することのできるルーチンを書くことです。
サイズやタイトルなどのフォームに属するデータも同様です。どんなサイズであっても、あらゆるサイズでウィンドウを表示できるようにルーチンを用意し、そのルーチンに対してサイズの情報を与えれば、どんな場合でも動くようにするのです。
メッセージなども同様で、どんなメッセージでもフォームとやりとりができるようなイベント通信機能を作ります。具体的なメッセージについては、このメッセージ通達ルーチンを「作る時」ではなく「呼び出す時」に、さまざまなメッセージを「具体的に送る」ことができるようにします。そして、今度はこのルーチンを使って、さまざまなメッセージを具体的にイベントの通達やフォームの返答に対して対応付けし、最終的にサイズを変えられるようにしたり、フォームを再描画したり、クリックやキーボード入力などのイベント機構を作ります。
要するに、「どんなフォームの画面でも、どんなサイズやタイトルでも、どんなイベントメッセージでも対応できるような、正しいルーチンを書く」ことができれば、それだけでプログラミングはできるのです。
プログラムの設計とは、このように、「どんな場合でも対応できるようなルーチンを書く」ことです。実際に具体的なデータを操作することはなく、ただ単にあらゆるデータを操作できるようなルーチンを書けば、それでプログラムは完成です。
後日注記:このように「汎用的などんな場合にも対応するルーチンを作る」のは、ウィンドウシステムに限ったことではありません。たとえば、GTKやQtのツールキットならば、イベントを回収する「イベントを回収するコアルーチン」や、ツールキット全てに適用する「グラフィックスの適切な配置と表示のコアルーチン」などは、特にオブジェクト指向であればクラスの継承階層を用いて、「ひとつの汎用ルーチン」を書くことで実装できます。ボタンであれ、ラベルであれ、配置に必要なルーチンやマウスクリックなどのイベントに対応するためのルーチンは同じ「コアルーチン」を作れば作れます。よって、フォームへの配置は「どんなウィジェットでも配置して表示できるルーチン」を作り、マウスなどのイベントは「フォーム上のマウスクリックやキーボード入力をそれぞれのウィジェットに適切に配送するルーチン」などを作れば作ることができます。その上で、これらのルーチンをオブジェクト指向のAPIで、「ウィジェットの具体的な作成とイベントに対するコールバック関数の登録をプログラマが行うことのできるフレームワーク」を作る必要があります。
後日注記:また、印刷のためのルーチンでも、どんなページでも印刷できるようなプリンターへグラフィックスを送るルーチンを作れば作れますし、インタープリタやコンパイラなら、一行の命令をどのように解釈するかを適切に判断する「文を解読するルーチン」を作れば作れるでしょう。実際には、ウィンドウシステムやツールキット、また印刷やインタープリタ・コンパイラには適切な「開発セオリー」があるため、「このように作ることが絶対に正しい」というものではありません。
後日注記:ウィンドウを表示する場合において、X座標とY座標によるひとつの点を示す構造体が2つあれば、そこから四角形を表示できます。また、3次元のコンピュータグラフィックスにおいて、「画家のアルゴリズム」と呼ばれるもっとも単純な陰面消去のアルゴリズムがあります。これは複数の画像を重ね合わせる時に、どこが見えていて、どこが隠れているかを処理するためのアルゴリズムです。