COBOLに対する根強い誤解とプログラミング言語の本質に関して

(COBOLに関しての話が盛り上がっていたので、今回は予定を変更し怒りのへっぽこプログラマ、デスパレート井上先生の寄稿を掲載します)

いい加減、神話は捨てよう

「COBOLは10進数が扱えるので数値計算が正確に行える」
この神話はまったくと言っていいほど正しくないのだが、恐ろしいことにIT系の中でも間違って覚えている人が非常に多い。

結論から言えば、Javaでも10進数を扱えるクラスは存在するし、他の言語でも、そのようなクラスを書けば全く同じ精度で計算することができる。

またこの件に関して「COBOLは言語の仕様として10進数を使っているから速い」という説明をする人も見受けられるが、これもおかしな話だ。プログラムは実行環境に合わせてコンパイルされて動く。最適化されるかどうかは、コンパイラの設計に起因するもので、言語の仕様ではない。

なぜ、IT系の中でもこんな間違いをする人が多いのか。話してみると、彼らはどうも「計算機」と「プログラミング言語」を混同しているらしい。

いらすとやの絵柄で描かれた二頭身のキャラクターを想像してほしい。顔の部分は白抜きで「C」とか「Python」とかそういう名前が書いてある。その擬人化されたプログラム言語がねじりはちまきなんかをしめて、汗をかきながら必死に鉛筆で計算をしている。

どうもそういう認識でいるようなのだ。はっきり言って大間違いだ。計算をするのは、計算機でありCPUだ。プログラミング言語はそれに対する命令にすぎない。

この誤解は根が深い。計算機の仕組みを理解していればまず間違えないのだが、そこを理解するのはハードルが高い。お恥ずかしい話だが、私もこれを理解したのはつい最近のことだ。知識としては知ってはいた。学校に行って、一番最初の学期の講義で触れるような基礎的な内容である。だがしかし、それが脳内でピンとつながって理解できるようになるまでには、長い長い時間が必要だった。

だから、ITエンジニアの中にも誤解が広まっているのは正直な所理解できるのだが、だからといってあまりにも無理解な内容が反乱していると、不安になってしまう。例えば、「プログラミング言語の速度を調べてみました!」なんて記事はちょっと調べるだけで大量に見つかるのだけれど、これも正確に言えば、かなりおかしな話だ。プログラミング言語自体に速いも遅いも無い。速度差は実行環境によるものだ。(この話が理解できなかった人は、このテキストを最後まで読むことをおすすめする)

そこで、今日はこのような誤解を生み出さないために、新人のために書いた計算機についてのテキストを寄稿する。

あらかじめ断っておくが、私も計算機のことを完全に理解したかというと、全くそうではない。だから、不正確だったり、間違っている部分も多く存在しているだろう。その時は容赦なくマサカリを投げてほしい。そうやって、少しずつブラッシュアップしていくことが、何よりも大切だ。

計算機とはなにか

さて、計算機とは計算する機械だ。何かを考えているわけではない。物理法則に従って動くだけの存在だ。
ソロバンを想像してほしい。一定のルールに従って珠を弾くと、計算結果が珠のパターンとして盤面に現れる。計算をしたのは、人間か?ソロバンか?いや、ルールだ。

大切なのはルールだ。ルールさえ適切に作ることができれば、電気によって動作しようが、人力だろうが、計算機は動作する。

現代の計算機の実現には、数学的な理論が大きな役割を果たしている。一つが二進数。もう一つがブール代数(論理演算)である。

二進数とは、我々が通常使っている10進数とは異なり、0と1だけで数字を表す表記方法のことだ。私達が10で桁あがりするように、二進数は2で桁が上がる。

10進数の「5」は二進数では「101」となる。

現代の計算機はほぼ二進数で動いている。なぜ二進数なのかというと、それが最も楽だからだ。二進数同士の一桁の足し算は、わずか4パターンだ。4パターンの状態を再現する機械をつくることができれば、それは加算機として動作する。

さらにブール代数(論理演算)も重要だ。これは数学の一分野であり、「AND」「OR」「NOT」の3種類の演算ができれば、すべての論理式を実現させることができることを証明している。(※1)

すべての数は二進数に変換できる(※2)。そして、すべての演算は、「AND」「OR」「NOT」の三種類に置き換えることができる

我々にとって幸運なことに、これらはすべて電気回路で実現できた。二進数は、電気のONOFFとして表現できたし、AND、OR、NOTの三種類の論理ゲートはスイッチング回路で実現できた。(※3)

つまり、どんな計算でも。そう、この世の中にあるどのような計算でも、それを実現する電子回路を作ることができる(※4)のだ。言ってしまえば、これが計算機だ。

※1 正確にはNANDというNOTとANDがくっついたものがあれば、一つで済む(組み合わせることによって、ANDにもORにもNOTにもなる)
※2 変換しても小数の形で表せない数もある。例えば、いくつかの小数は循環小数となってしまう。ただ、表せないだけで変換できないわけではなく、さらにこれは二進数の問題でもない。我々の使っている十進数でも1/3は循環小数となってしまい表すことが出来ない。
※3 これを修士論文で示したのが、かのクロード・シャノンである。人呼んで「今世紀でもっとも重要な修士論文」
※4 どのような計算でも。と書いた。しかし式にできないもの。計算できないものは当然不可能である。何が計算可能で計算可能でないのかに関しては、また長い話になるので各自調べてほしい。

注釈

「計算」する回路

簡単な足し算ができる計算機を回路で作ってみよう。4桁の二進数を扱うことにしたい。つまり、4ビット加算器というわけだ。

茨のように複雑に絡み合った回路を想像してほしい。そこから、四本のコードが二組、8本出ている。これが入力だ。反対側には、やはり、四本のコードが出ている。これが出力だ。とりあえず、出力には豆電球でもつけておこう。電気が流れると光る。

さて、入力から出ているコードに電圧を加える。計算したい数字を二進数に変換して与えるのだ。入力は2つあるので、2つの数字をいれることができる。例えば片方に「5」を二進数に変換した「0101」を、「3」を二進数に変換した「0011」を入力する。電気を流したいコードにだけ電線をつなぎ、電気を流す。

すると、出力側の豆電球が点灯する。回路の中を電気が駆け巡り、巡り巡って、四本のコードに集合する。その結果、コードに電気が流れ、豆電球を点灯させる。回路が正しければ、左から2つ目の豆電球だけが光るはずだ。つまり「0100」である。

おめでとう。計算が完了した。君は今4ビットを加算できる計算機回路を作ったのだ。

あまりも単純すぎて拍子抜けしてしまう。ただ電線に電気を流すだけで計算ができるというのはにわかには信じられない。だが、計算というものはそういうものだ。法則に従った結果、そうなるだけなのだ。

さて、この回路は、二進数進数に変換する手間は必要だが、計算に必要な時間は電気が回路を流れる時間であり、つまり一瞬である。4ビットなので、整数で15までの数しか扱えないが、もっとビットを増やせば大きな値に対応できる。

前にも書いたように、すべての演算にはそれに該当する電子回路が存在する。大砲の弾道計算でも、視野角から相手までの距離を見積もることも、地球の表面上の位置を星の高さから求める計算も、月を目指すロケットの軌道計算でも、全てそれに対応できる回路を作ることができるし、入力さえうまくいけば、一瞬で答えを導き出すことができる。なんと素晴らしいことか!

いでよ!汎用計算機!

さて、これで電気で動く計算機(というか回路)を手に入れたわけだが、欠点が一つある。

違う計算を行いたいときには新しく回路を組み直す必要があるのだ。文字通りのコーディングである。先週までは人口統計の計算をやっていたのに、今週からは急にロケットの計算をしろと言われても、急には変えられない。その計算も、今回一回しか使わないとなると、割に合わない。

この問題をどう解決すればよいのか。エンジニアたちはクールな解決方法を生み出した。基本的な計算だけを実装し、あとはそれを命令で呼び出せば良い。複雑な計算は、単純な計算の繰り返しに置き換えれば良い。つまり「汎用計算機」の概念であり、CPUの実装であり、プログラムの誕生だ。

これらの解決方法はなにも突飛なアイディアではない。エイダ・ラブレスの時代から、パンチカードで織機の織り方を変えるアイディアはあったし、ディスク状の譜面を読み込んで音を奏でるオルゴールなんてものも存在した。

オルゴールが単純な音の組み合わせから無限の音楽を奏でるように、単純な計算を繰り返せば、どんな計算だって実現できる。

具体的には以下のようにする。先程、頭の中に描いてもらった回路を改造しよう。

まず、入力部分の改良だ。ここには4本のコードが2組あるが、これは1組に集約することができる。時間方向にずらすのだ。つまり、最初に入力された値と次に入力された値を加算するようにすればよい

ちょうど電卓のような使用感になるはずだ。さらに、足し算だけではなく、メモリへの書き込みや読み出しと行った操作も行えるように改造しよう。それらの操作を実行する命令は、例えば「1000」を加算などと、定義し、入力できるようにする。

この回路に「0001」「1000」「0010」を入力する。それぞれ、「1」「+」「2」を表している。そうすると、3ステップ後に「0011」、つまり「3」が出力される。

入力も簡単にしよう。いちいちコードを繋ぎ変えて電気を流していては大変だ。これも、ある種のオルゴールのように、穴の空いた紙を読み込ませるのが良い。紙は1行1行読み込まれ、回路に入力を与える。

ガチャンガチャンと音を立てながら紙は機械に飲み込まれ、全ての紙が飲み込まれると、出力からは違う紙がでてくる。そこには答えがパンチされているというわけだ。

現代の計算機も基本的にはこれと同じ動きをしている。流石に今は紙の代わりに、シリコンで作られた超高速のメモリを利用している。そこに、電気として情報が蓄えられ、CPUに送られる。

CPUは計算機の本体だ。与えられた数値に対して命令を実行する。紙を1行1行読み込むことに相当する行為を今のCPUはとてつもない速度で実行する。これは俗にクロック数と呼ばれものであり、今のCPUには5GHz、つまり一秒間に50億回も実行できるものが存在している。

これほどの速度で動けば、魔法のようなことができる。こうして、画面に文字をタイプするための処理も、単純な計算を想像を絶する回数繰り返して実現しているのだ。

機械語からアセンブリへ

汎用計算機は計算という操作をハードウェアとソフトウェアに分離した。これはちょうど、楽器と譜面の関係に近い。現代の中国語では、プログラムのことを「算譜」と呼ぶそうだが、これは本質をついている。

様々な譜面によって、楽器は無限の音楽を奏でる。では音楽の本質は、譜面なのか楽器なのか?それともその2つが合わさり初めて音楽が生まれるのか?

禅問答的な話はともかく、計算機も似たような哲学を抱えている。まあ、祖の話はおいといて、計算の度に計算機を作り直す必要はなくなった。重要になってくるのは「どんな計算をどの順序で実行するのか」つまり、プログラムだ。

プログラムの本体は、ビット列である。先程は、単純な加算のプログラムを提示したが、プログラムの中にはあのように、命令とデータが含まれたビット列が膨大な量存在する。それをCPUに流し込めば動作してくれる。先ほどの例では「000110000010」となる。

これを機械語と呼ぶ。つよつよエンジニアと呼ばれる人の中には、その機械語を読める人も存在するそうだが、正直な所、常人には極めて難しい。

そこで、機械語を扱いやすくするために、素朴なアイディアが生まれた。その一つがアセンブリ。という概念だ。

アイディアはとても単純だ。0と1の組み合わせを対応する単語に置き換えてしまうのだ。

「000110000010」
は「0001」「1000」「0010」であり、
書き換えれば「1」「+」「2」になる。

この書き換えた後の「1+2」が俗にアセンブリ言語と呼ばれるものになる。ただの数字の羅列に比べると、遥かに見やすい。書き換えは機械的にやってしまうので手間はそれほどかからない。ちょっとした工夫で仕事を楽にするようなものだ。

さあ、高級言語へ!

「書き換え」というアイディアで状況は良くなった。もう、数値の羅列と格闘する必要はない。ここまでくれば、高級言語、つまり我々が想像しているプログラミング言語までもう少しだ。

ここで、技術者たちはアイディアを更に拡張しはじめる。「書き換え」をさらに進めて、もっと分かりやすい形式にしてみよう。

例えば、メモリ上の場所に名前をつけるのはどうだろう。メモリ上の場所は「01000010」等の番号で表され、そのアドレスを指定して書き込みや読み出しを行うのだが、これに名前をつける。

「01000010」に情報を書き込み。ではなく、「name」領域に情報を書き込み。と置き換えればさらに分かりやすくなるし、間違いにくい。変数領域の誕生だ。

ループや分岐などの命令も変換可能だ。人間に分かりやすい方法で書いて、それを後で機械語に変換すれば、さらに仕事は楽になる。

この変換器をコンパイラという。コンパイラはあるコードを別のコードに変換してくれる変換器だ。この概念が登場することで、仕事が楽になる上に、とてつもないメリットが生まれた。

それが、違うCPUでも動かすことができる。ということだ。

今まで登場してきた、CPUに与える数字の羅列、機械語は、実はCPUによってかなり違いがある。

現代だと、PC用のCPUで使われているx86_64命令セットと、携帯電話などに使われているARMアーキテクチャが分かりやすい。この2つのCPUは設計思想が全く違う。高性能で動くことを目的とするものと、モバイル機器向けに省エネルギーで長時間動くことを目的としているものであり、双方に互換性はない。

コンピュータの黎明期となると、さらに状況は深刻だった。独自設計でCPUを作っていたとしよう。これを改良して命令セットを変えたい。となっても、気軽に変えるわけにはいかない。命令セットを変えれば、せっかく過去に作ったプログラムが動かなくなってしまう。かといって古い命令は使いにくい。なんとも頭の痛い問題だ。

コンパイラはこの問題を解決する。つまり、動かしたいCPUに向けて、プログラムをコンパイルすればよいのだ。

一度、高級言語、例えばC言語などで、ソースコードを書いてしまえば、あとはそれを環境に合わせて適切に書き換えてくれるコンパイラさえ見つけてくればどんな環境でも動く。IntelのCPUでも、Nintendo Switchでも、Appleシリコンでも、メインフレームでもだ。

これは非常に大きなメリットだ。かくして、プログラマたちは、機械語と一対一に対応しているようなアセンブリ言語から、高級言語を手に入れ、さらに生産性を増していくことになった。

コンパイラという大黒柱

コンパイラの重要性はいくら強調しても強調しすぎることはない。マイナーなシステムになると、コンパイラが数種類しか存在しないことが普通に存在する。これは厄介な問題だ。

例えば、メインフレームという銀行などで使われている専用の計算機があるのだが、これは各社が独自に設計している。(※1)当然コンパイラも各社が提供している。HITACHIのメインフレーム上でプログラムを実行できる状態にコンパイルするためには、コンパイラ(有料)を使う必要があったりする。

そういった環境の場合は、コンパイラはCOBOLやPL/Iといった古い言語でしか提供されていない場合が多く、例えばswiftやrubyと言った新しい言語を使うことはほぼできない。(※2)必然的に選択肢は多くない。

「コンパイラさえあればどんな環境でも動く」のは正しいが、そのコンパイラ自体があるとは限らないのが現実だ。実際の開発では、コンパイラが存在しているかどうかによって、大きく状況が変わってくる。

また、コンパイラにも言ってしまえば良し悪しがある。良いコンパイラは、翻訳するときにCPUに合わせて最適な機械語を書いてくれる。いわゆる最適化だ。この最適化がうまくいくと、実行速度が早くなったりする。(※3)

悪いコンパイラにはそもそもバグがあったりする。もっとも、現代ではそんなことはそうそうないだろうが、例えば新しいプログラミング言語を作ったとして、最初に作ったコンパイラにバグがあったりすると大変である。(※4)

だれもそんな言語は使いたがらないだろうし、人気が落ちて開発中止になってしまえば、せっかく書いたコードが無駄になってしまう。そんなことはだれだって嫌だ。だから人はよりつかないしプロジェクトはポシャる。ちゃんと動作するコンパイラを作ることは第一優先事項だ。

プログラミング言語は、規約の集合にすぎない。実際に動くものを作るためには、コンパイラを作らなければならない。「プログラミング言語を開発する」というのは、ある意味コンパイラの作成とほぼ同じだ。

※1 実際のアーキテクチャには詳しくないのでどこまでが独自規格かはよくわかっていない。ただ、F系(富士通)とH系(HITACHI)には互換性はなかったと記憶している。(2024/6/11 富士通もHITACHIもIBMのOSに準拠しているため、互換性はあると言えばある。という指摘を頂いた。もっともHW依存の部分は書き直さないといけないそうだ。Windowsのようにはいけないものか……)
※2 もしかしたら、私が知らないだけで存在しているのかもしれない。祖の場合は、ぜひ使わせて欲しい。

(2024/6/11)なんと!!!IBMメインフレームではrubyもswiftも利用できるとの情報を頂いた。https://x.com/rabitgti/status/1800540099656208572
す、すげぇ!!使わせてくれ!!
※3 メインフレームには独自の回路が乗っていて、それを利用するとさらに速度を上げることができる場合もある。例えばIBMのメインフレームには、AI推論用のアクセラレータがついているそうだ。IBMのメインフレーム向けのコンパイラを使えば、こういった回路を適切に使ってくれるはずだ。
※4 コンパイラのバグを疑い始めたら、作業を一時中断して寝るのが良いとされている。実際に私がコンパイラのバグに遭遇したことは一度もない。実際に遭遇した人がいたら、かなりのレアケースのはずだ。あなたは凄い!

注釈

チューリング完全

ここで、少しむずかしい話をしたい。チューリング完全という概念だ。理論的な話であり、実際の業務にはほとんど関わってこないが、この概念を知っているかどうかで、エンジニアとしてはかなり差が出ると思っているので、記載する。

さて、機械としてのコンピュータができる以前の話をしよう。イギリスのアラン・チューリングという科学者が「チューリングマシン」というアイディアを提唱した。

これは「無限に長いテープ」と「ヘッダ」を持つという空想上の機械であり、実在はしていない。機械の動作は単純で、ヘッダを動かし、命令表に従ってテープに書かれている内容を書き換える。というただそれだけのものであるのだが、なんと面白いことにこのシンプルな機械は、理論上全ての計算を実行することができるのだ。(※1)

一体どうやって?という疑問はあるし、正直いって私も理解できているというとまったくそうではないのだが、チューリングは数学的な研究から、「全ての計算はいくつかのシンプルな操作に置き換えることができる」ということを知っていた。そして、それを突き詰めていった結果、このような機構を持つ機械であれば実現できることを発表したのだ。

チューリングマシンと同程度の計算能力を持っている機械やシステムのことを「チューリング完全」と呼ぶ。

面白いことに、意外なものが計算能力を持つことがある。例えば、マインクラフトというゲームは、ゲーム内のブロックをうまく組み合わせれば、論理回路を設計できることが知られている。

そして、その論理回路によって作られた計算機は、チューリング完全なのだ。

つまり、マインクラフト内部に作られた計算機は、チューリングマシンでできる計算を全て実行可能なのだ。これは、どんなスーパーコンピュータで行う計算も、マインクラフト内部で実行可能ということになる。(※2)

もっと興味深い例としては、カードゲームであるMTGがチューリング完全を満たすというものが挙げられる。この場合、うまく状況を組み合わせると、対戦するプレイヤー同士が常に選択肢が一つしかない状態におかれ、それを実行し続けると、最終的にフィールド上に計算結果が現れるそうだ。

詳しくは上記を読んで欲しいのだが、ゲームで遊んでいたら、いつのまにか計算機として振る舞っているというのは、驚愕の事実だ。おまけにチューリング完全である。二人の人間が向かい合って紙のカードで遊んでいるだけで、コンピュータでする計算が全て実行可能とはにわかには信じがたい。

だが、システムの内部に組み込まれた人間がどう考えようと、システム全体で計算を行うことが可能であればそれは計算機として振る舞うのだ。

チューリング完全なシステム同士は、お互いの動きをそっくりそのまま真似することができる。考えてみれば当たり前だ。チューリング完全ということは、どんな計算でもできるということだ。前述したが、スーパーコンピュータでやる計算をマインクラフト内部の回路で実現することも可能なのだ。つまり、どんな計算機でおこなう仕事も、代わりに行うことができる。

これを「万能チューリングマシン」と呼ぶ。

さて、世の中にあるプログラム言語は、ほぼ全てがチューリング完全である。つまり、あるプログラム言語にできて他のプログラム言語にできない。ということはありえないのだ。回り道することになっても必ず実現できる方法がある。

ここの認識を持っているかどうかは大きな違いとなる。「そのプログラム言語では、〇〇ができません」みたいな認識は間違っている。(※3)大前提として、可能ということは知っておき、その上で、どの程度の労力がかかるのかを見積もるのが大切になってくる。

※1 チューリングマシンにもできないことがある。それが停止性問題だ。「自分がいつ終了するのかが判別することができない」という問題である。他の計算機にもこれはできない。そういう意味で「全ての」ではないかもしれない。より正確に言うならば「計算可能なものは全て計算できる」かもしれないが、これはトートロジーなので書くべきか悩んでしまう。
※2 当然その速度は極めて遅い。
※3 しかし、IT系でも平気でそういう発言をする人がいる。正確には「できるけど、めっちゃ疲れるのでやりたくない」または「労力が非現実的」の方が良いと思っている。いつもそういうことなのだろうなと好意的に解釈しては苦虫を噛み潰している。

注釈

そもそも動くときは機械語

さて、ここまで来れば、なぜ冒頭言及した「COBOLは10進数が扱えるので正確」が間違っているのか解ると思う。

まず、COBOLでもその他の言語でも、コンパイル型なら、ほぼ全てが二進数のコンピュータ上で実行されるようにコンパイルされて動くはずだ。その時点で全て機械語に変換されてしまう。だから、どんな言語でもその時点で同じフィールドに立っていることになる。

COBOLだから特別な回路で計算しているわけではまったくない。さすがにこの認識は改めて欲しい。COBOLで書こうが、Cで書こうが、同じCPUで動作するのだから、全く回路を使っている。(※1)

プログラミングの速度に関しても同様に正確に言うならば間違いだ。すべてのプログラム言語は、コンパイルされてCPUで実行される以上、同じ環境で速度差が出るのは、ほぼコンパイラの性能による。

コンパイルした結果が、たまたまそのハードウェアで効率よく計算できるものになっていた場合は速いし、そうでなかった場合は遅くなる。それだけの話だ。

しかし、「コンパイラの性能とはそのまま言語の性能と言ってもよいのではないか?」という意見もあるだろう。実際その通りで、人気が高かったり、古くから使われている言語は、コンパイラの最適化もかなり進んでおり、かなり効率的に変換してくれるそうだ。

そういう意味では、「このCPUで最も速いプログラム言語はこれだ」という言い方は確かに意味は通る部分もある(私としてはあまり認めたくないが)

話をややこしくするのが、Javaなどの仮想環境で動く言語だ。Javaは機械に合わせていちいちコンパイルしなおす手間を省くために、JVM(Java Virtual Machine)という仮想的なコンピュータを動かして、その上で計算する。マインクラフトの上に作ったコンピュータのようなものだ。CPUで直接動かすわけではないために、速度は少々劣る……といわれているが、ぶっちゃけた話、そこまで気にする必要はない。

気にする必要があるのは、Pythonなどのスクリプト言語と呼ばれるものだ。これらの言語は、まとめてコンパイルせず(※2)、一行一行解釈して実行していく。そのため速度の面では難がある。しかしこれも、実用的な部分では気になるほどの遅さではない。(※3)

※1 と書いたが、IBMや日立、富士通のメインフレームは、10進数用の回路を持っており、提供されるCOBOLコンパイラはその回路を使うように書いてくれるため、厳密にいうと違うのではないか。という指摘を頂いた。その通りであるので、ここの書き方はすこし怪しい。ただ、それはコンパイラが実行環境に合わせて最適化してくれた結果であって、COBOLの仕様の話ではないことに注意。実際、Javaでも10進数のアクセラレータが動いてくれるようだ。だったら、Javaで良くないだろうか?
※2 ある程度まとめてコンパイルしてくれるやり方もあったはずだが、よく覚えていない。
※3 何を持って実用的とするかは人によって違うが、ちょっとしたプログラムを書きたい。という要望には十分答えられると思う。大量のデータ処理となると、あまりよろしく無い……と思うが、最近のPythonは機械学習でよく使われるようになり、分散処理などが大変得意になっているそうだ。ここまでくると、もう速いんだか遅いんだかさっぱりわからない。有識者に相談して判断して欲しい。

注釈

ではなぜCOBOLが選ばれるのか?

ここまで書いた内容を読んで「ではなぜCOBOLが選ばれるのか?」と考えた人もいると思う。いくつかそこには理由がある。

そもそもの実行環境でサポートしている言語がCOBOLしかない

COBOLが必要な現場はほぼすべてがMF(メインフレーム)という計算機を使っている現場と思われる。(※1)MFというのは、日立や富士通、IBMと言った会社が出していた大型計算機であって、専用のOSを積んでいる。当然その上で実行するプログラムを書くためには、それ専用のコンパイラを(ときには有料で)使わなければならない。そのコンパイラがCOBOLしか対応していなければ、それを使うしかない。

こればかりは実行環境の問題なので仕方がない。とはいえ、今メインフレームの市場は驚くほどの勢いで縮小している。富士通も撤退を決めたし、日立もハードウェアの製造から撤退することを決めた。

今は脱メインフレームが全国的に進んでいると認識している。よってオープン系に移行しなければならず、そのためコンパイラがそれしかない。という状況は変わっていくものだと思われる。

ベテランがCOBOLしかできない

これは結構問題の根が深い。勉強すればいいだけ。とも言えるのかもしれないけれども、勉強する気がない社員がいて、しかも法律的に解雇が難しい。となるとかなり対応は難しい。(※2)

それに、もともとのシステムを設計している人がCOBOLしかわからない。という状況でなおかつその人物が出世して管理職何かになっていたりすると、どうしても、自分の経験上安牌を切ろうとする。よって、COBOLが選定される……という流れもある程度はあると思っている。

正直な話、危険な流れだと思っている。なにしろベテランはあと10年もしないうちに去ってしまうのだから……。

過去の資産があるから

個人的にはこれが一番大きな影響だと思っている。すでにCOBOLで書いたシステムがMFで稼働している状態を想定しよう。

システムをそっくりそのまま作り直せば、〇〇億かかる。しかし、今のシステムをだましだまし使っていけば、使えないこともない。となると、極限まで刷新を引き伸ばすのは選択肢としては間違っていない。引き伸ばしている間にブレイクスルーが起こって、もっと安価に刷新できるようになるかもしれない。(※3)

また、旧システムと全く同じ動作を保証することは、非常に難しい。COBOLで書いたものをJavaで書き直して、コンパイルしてまったく同じコードになるかというと、おそらくはならない。(というか、JavaはJVM用の中間コードになるため、そういう意味でもコンパイルという言葉は正確ではないかもしれない)

例えば新しいメインフレームを立ち上げて、その上でCOBOLで書いたものを再コンパイルすれば、ある程度は現行保証ができる。もっともコンパイラ依存で変わる部分が入っていれば話は別だが、言語としての仕様を守っているなら、動作は保証される。

であるなら、MFを刷新して、その上で過去の資産をそのまま動かしたほうがコストが掛からない。

実際、コストの面では理のある選択肢だと思う。リスクと引き換えではあると思うが……

さらに言えば、今動いているシステムがあるのであれば、それはそのままにして、他のことに労力を割くというのも考えとしては成り立つ。余計なことをして障害を起こすぐらいだったら、触らないでほうっておくのが良い。触らぬ神に祟りなしだ。

そもそも選ばれていない

そもそもCOBOLが選ばれていると言う事自体が幻想ではないのかという気もしている。実際の所、メインフレームからは各社が撤退しているので、正直な所、先行きは全くよくない。COBOLエンジニアが求められているのだって、「古いシステムがCOBOLで書かれているので、刷新」みたいな案件が多いのではないだろうか。

障害で有名になったみずほ銀行も、COBOLからJavaに変えた案件だった。

ということで「COBOLは今でも選ばれている」という考え方自体が非常に局所的なもので、全体を見れば凄い勢いで縮小していくというのが正確な見方なのではないかとも思う。

※1 その他の分野で使っている人はいるのだろうか? 気になるが、守秘義務などもあるので、あまり聞くわけにもいかない。
※2 COBOLすらできない。というパターンもある。労働者としては、安定な雇用環境があるというのは歓迎すべきことではあるが、それにしても技術的な素養のない人間をアサインすると苦労する。とはいえ、これは各企業の問題ではある。
※3 とはいえ、さすがにこれは楽観的すぎるかもしれない。最終的にどうにもならなくなってしまうリスクはある。十分に予算を取って式年遷宮していったほうが良いのではと思っているが、これはいろいろな意見がある。

注釈

どんな言語を選ぶべきか?

さて、ここまで読んできてプログラム言語に対する理解が深まった所で、一つの疑問が湧いたと思う。

どのプログラム言語でも結局できることが変わらないのであれば、COBOLを使ってもよいのではないか?

そう、その通り。まさにその通りなのだ。逆説的だが、ここまでの結果を総合すると、環境に対する適切なコンパイラさえあれば、別にCOBOLで開発しても構わないのだ。(※1)

COBOLのデメリットはたくさんある。COBOLの記法は長ったらしくて生産性は著しく低い。他にも配列が1から始まっていたり、配列の添字によってはメモリの変なところを見てしまったり(これは言語の仕様なのか、コンパイラの仕様なのかわからない)、可変長配列が扱えなかったり(環境によっては扱えるらしい)と、モダンな言語に比べると非常に使いにくい。

ただ、他のプログラム言語でできることは全てCOBOLで実現できる。のも事実だ。とんでもない回り道になるし、そのコストに見合うかは別途議論が必要だが……。(※2)

個人的に、システム開発で使う言語を選ぶ立場になったら、ある程度人気があって、言語仕様が殆ど変わらない(※3)言語を選びたい。

人気のある言語は技術者の数が多く、メンバーの急な長期離脱などのトラブルに対応しやすい。人気があるのでコンパイラの開発が進むし、いろんな環境で使えるコンパイラが揃っている。最適化も進みやすい。数が多いというのはそれだけでメリットだ。

しかし、それと同時に自社がCOBOLで古い資産を大量にもっているのであれば、それを利用できることはメリットだ。とくに古いシステムのコードが数万行ある場合は、書き直すだけでもとてつもない時間がかかる。

様々な状況を踏まえてメリット・デメリットを比較し、最も適切な言語を選ぶ。それがプロのやることだし、これができていれば、最終的にCOBOLを選択したとしても私は納得できる。

ただ、間違った知識で選定するのだけはやめていただきたい。

COBOLでしか10進数の計算ができないから、COBOLを選定した」「最適化されていて、より計算が正確だからCOBOLを選択した

この考えは両方とも全く正しくない。そんな間違った認識で計画を立てても、ひどいことになるのが目に見えている。腐った基礎から生まれるのは瓦礫だけだ。

※1 それがあれば苦労しないというか。それがないから苦労しているというか……。
※2 マインクラフトのレッドストーン回路で業務システムを書くことも原理上は可能だが、要求される速度は絶対に出せないだろう。もっともそんなことを言われた時点で辞表を出すべきだが。
※3 Pythonはそういう意味で大変だったと聞く。何しろ2.0系と3.0系に互換性がないのだ。プログラムを引き継ぐためにはかなりの書き直しが必要になったという。

注釈

最後に

以上、プログラミング言語についてつらつらと書かせてもらった。詳しい人から見れば「そんなことは常識だよ。当たり前だ」なんて思う内容かもしれない。しかし、この文章を書こうと思ったのも、私自身これを理解しておらず「〇〇という言語は遅くて~」など、知ったフウな口を叩いていた時期があったからである。

なんともお恥ずかしい話だし、仕事を始めてから「もっと前にコンパイラについて理解できていれば……」と後悔することがとても多い。

そこで、少しでも助けになればと思いこの文章を書かせてもらった。理解の促進になれば、幸いである。

(2014/6/10 デスパレート井上)

この記事が気に入ったらサポートをしてみませんか?