分からないことが分からない
いつもニコニコしながら「そうだね~」なんて同調できるほどには大人になったけれども、「〜が分からない」という「分からない」意味が「分からない」ことがよくある。何を言っているか、分からないかもしれないけれども、特定の何かの現象や症状、定義を「理解できない」という人に対して、なぜそれを理解できないのかが「理解できない」。
C言語のポインタが難しい?
例えば。C言語のポインタは誰もがつまづく壁である(とよく言われている)。個人的には、構造体とか共用体とかのが、存在意義が分からなかった。それは、初めて存在意義を見出したときに「やるじゃん構造体」みたいには、理解はできているけど使いどこがわからないということはあった。みんなが言っているので「そうだねー」と言うけれども、ポインタがわからないという意味がぜんぜん理解できない。
わいのプログラミングの段階で行けば、小学校の頃にBASICに触れ、中学校の頃にその処理性能の悪さにマシン語・アセンブラへ流れた経歴です。コンパイラやアセンブラは、中学生には高すぎるか、とんでもない分量のマシン語を入力しないと、その恩恵に預かることはできませんでした。今みたいに、ボタンくりっとするとコンパイラが入ってしまうなんて、そんなものは夢の世界でした。1980年代ですね。ネットワーク自体はもちろん存在していたし、カセットやROMカートリッジでソフトウェアも提供されていたけれども、それは中学生には高嶺の花でした。
マシン語に限っては、そのような高級なアセンブラやコンパイラがなくとも、当時のMSXでは、BASICから実行する方法が備わっていたので、気合さえあればどうにかなりました。気合というのは、「ハンドアセンブル」すれば良いということ。今でも中学生の頃に書いたZ80向けのハンドアセンブルしたノートが出てきますが、相当しんどかったはずです。
1980年代は、まだ技術書がほとんどなく、MSX(Z80)のマシン語本なんて、近くの本屋さんに1冊おいてあったからそれを読んでいた、というレベルです。新宿の紀伊国屋へ行けばいいじゃないかとか、そういうお金もないので、近くの本屋でなんとかしていたレベルです。それでも、数千円するので、中学生には厳しかったですよ。それも、完全に大人向け。文章がまず難しい。単語がわからないところから始まるのに、Googleもないから調べようがない。BASICマガジンやBeep!!は買っていた頃なので、そういったものでなんとか補完しながら、マシン語を試していったわけです。
そりゃもう、難しいなんてもんじゃないし、他人のプログラムはほとんど公開されていないから、写経だってできない。でも、ここでマシン語の良さを理解します。どんなプログラムでも、バイナリさえダンプできれば「ディスアセンブルできる(推奨しません)」んです。そのうち、バイナリ見ててもアルゴリズムくらいは理解できるくらいになりますが、まぁ言ってもマシン語です。ほんとに単純な命令系統にしかならないので、たいていは優しいフローです。自己書き換えとか、ループ展開とか、CPUキャッシュのない古き良き時代に書かれたその時代特有のものでない限りは、命令の少なさはありがたかったのです。
8bit時代のマシン語は制約がほとんどなく、割り当てられたメモリにすべて直書きの時代でした。今みたいに、CPU自体にドメイン(レイヤー)が割り当てられたりしていないので、特権命令使いたい放題です。仮想メモリアドレスなんてものもないので、常に実メモリアドレスを指し示します。マシン語のプログラムを、どの番地から開始するように割り当てるかによって、絶対アドレス指定のプログラムは影響を受けてしまうわけです。ほら、当時はアセンブラとか気の利いたものがないので、自分でアドレスを指定するわけです。そこで、ほとんどのJUMP(JP)ケースでは、相対アドレス指定をするわけです。そのほうが処理も速かったし(確か相対のが1byteコード少なかった気がする)。この相対アドレス指定が、まぁやっかいです。プラスに進む場合は良いんだけれども、マイナスに進む場合は計算良くまちがえてました。もう二度とやりたくない。
ただ、データに関しては配置場所のアドレスを指定してデータを配置しておきます。LOAD(LD)するときに、その番地を指定してデータを読み出すわけですが、これこそがまさに「ポインタ」なわけです。そりゃそうだよねと。0から割り振られた8KBのRAM内において、そのデータはどこにあるの?と聞かれたら、その8KBの中の何処かをポイントするだけです。8bit CPUなので、メモリは8bitを1アドレスとして、0番地から順番にふられています。16bit データなら 2番地分使ってるわけですよ。だから、そのデータのサイズによって、次の番地がいくつになるかどうかってのはあるにせよ、少なくともデータが入っている領域をポイントするってのは、ごくごく自然で当たり前のことなんです。それしかできないから。
このようなきな臭い経歴をたどってしまうと、「ポインタが分からない」と言う意味がわからなくなってしまうんです。「何がわからないのか分からない」というアレです。自然なんです。ごくごく自然にポインタって名前なんだという定義だけで理解していたのに、世の中にはポインタだけで本が出てたりします。理解できない。
基礎が理解できていればすべてが分かる?
いわゆる基礎中の基礎を理解してしまうと、その上で動く森羅万象は、理解できないことってものは少ないはずなのです。ただ、レイヤーが上がりすぎてくると「概念が理解できない」という、思念としての課題も出てきます。これは、コンピュータを理解できていないんじゃなくて、宗派が異なるだけです。LISPはごめんなさい。viとemacsは使い分けできる大人です。edも使えます。
当時、マシン語難しすぎてツライ。みたいな状態にいましたが、BASICを知っていたり、その後、C言語を学んでくると「アセンブラチョット分かる」というときがやってきます。抽象度が上がると、具体化されていたものの存在意義や、価値、ユースケースなどを理解しやすくなります。物事を理解していくためには、こうやって基礎から応用へ上がっていき、抽象度を上げていくことはとても重要なことです。これに気がついたのは、自分がITコンサルタント(ただしインフラ専門)というロールになったときです。
次元が上がると下位の次元を理解できる
当時は、ITアーキテクトの職位でしたが、部門的にコンサルもやらなければならず、コンサルタントと一緒に動くケースが多かったのです。最初はコンサルタントたちが何を言っているか、まるでさっぱり理解できてませんでした。そりゃそうです。これらの職位、次元が異なるんです。2次元と3次元の違いのようなものです。2次元からは3次元の状態は見えません。いま我々の住んでいる3次元世界では、4次元空間は認知できませんね。でも、次元を展開すると、ひとつ下の次元に落ちてきます。3次元でモデリングされた立方体を展開すると、2次元化されますよね。抽象度が上がるということは、こういった次元が上がっていくイメージです。ITエンジニアのロールで行くと、スペシャリスト→アーキテクト→コンサルタントと抽象度は上がっていきます。上の次元にあがるとどうなっていくかと言うと、下位の次元を理解できるんですね。抽象度が上がって、全体を俯瞰する形になるので、今まで自分がやってきたこと、やったことを客観的に観察することができるようになります。すると、それを「正しく」認知・理解できるようになります。
同じロールを続けるのではなく、必ず上のロールへ上がっていくことを、若い人たちにはちょいちょい話しています。通じてないかもしれませんけど。それは、物事を正しく理解するためには必要なアプローチだと考えています。実際にそのロールを職とすることがなくとも、抽象度の一つ上から、今の自分を客観的に理解することで、その時の職位では何をすべきなのかを、正しく認識できるようになるわけです。
理解には、二段階あると考えてます。まず最初に、定義と動作・振る舞いを理解します。その後、抽象度を上げて俯瞰したときに、その存在意義やユースケースを理解することで、何故それらを利用するべきか・利用すべきではないかを判断できます。
物事を理解するときに「3つの目」で見ると良いなんていいますね。「虫の目」、「鳥の目」、「魚の目」。それぞれの立ち位置によって、使い方は変わってきます。この「虫の目」が最初の理解でミクロの視点です。「鳥の目」は次の理解で、マクロな視点です。「あれ、魚の目は」となりますが、これはテクノロジーを離れた、もっと上の潮流です。市場の流れや、流行り廃りなど社会そのものだったりします。これは、今まで理解してきたものを、どうやって組み合わせて当てはめていくかということであって、多くのことを理解した上で、現実社会に適用するとしたらを考える部分。もうすでに、理解したことが前提になっているレイヤーだと考えています。
物事を理解するということ
物事を理解するときに、同じ次元にとどまっていると、理解できぬまま育つことになりかねません。それを実現するための基礎を知らないのかもしれません。それをどのように使うかという、応用を知らないから理解できていないのかもしれません。いずれにせよ、立ち止まったままでは理解できないので、立ち位置や味方を視点を変えてみると、新しいことに気がつくのではないでしょうか。