プログラム言語探訪 COBOL(後編)
さて、COBOLについて、ずいぶん前に上司――既に定年退職しました――がこう言ってました。
「COBOLってさ、誰が書いてもだいたい同じなんだよね」
どういうことか。
COBOLのかなり代表的な命令をざっとあげるとこんな感じ。
IF
PERFORM
GO TO
CALL
OPEN
CLOSE
READ
WRITE
REWRITE
DELETE
START
MOVE
COMPUTE
ACCEPT
DISPLAY
ADD
DIVIDE
SUBTRACT
MULTIPLY
使用頻度の多そうな順に並べてみましたが、このくらい。
IFの条件分岐、PERFORMのループ処理に、ある意味必須のGOTOと別プログラム呼び出しのCALLが制御系の主な命令。OPENからSTARTまでがファイル処理系、MOVE以降は代入とか演算とかそういう系。ただし、ADD以降はかろうじてDIVIDEで剰余を求めるときに使う程度、かな。
もうちょっとだけ命令文がありますけど、ざっくりこのくらいの命令で九割以上のプログラムが書けてる、そんなイメージです。そしてこれ、最近の言語に比べると明らかに少ないんですよね。
なので、とある仕様書を用意して百人にプログラムを作らせると、だいたい同じプログラムができあがってくる。違いとしては変数の命名とか、順番が前後しても問題ないような処理の順序くらいで、誰が書いてもだいたい同じプログラムが出来てくる。
そして、最近の言語だと普通にできたりする、代入と比較を同時にする、とか関数の引数に関数を与える、なんてこともできません。
これ、とても重要なんです。要するに、
「プログラムを見ると、だいたい何をやってるかわかる」
「機能改修とかで修正するときにどこをどう変えればいいか、だいたいわかる」
保守性という意味ではバッチリなんです。恐らく、最近の言語に慣れた人がCOBOLを見ると、なんか単純なことやってんな、と見えるくらい。
ほかの言語だと、百人のプログラマがいたら下手すると百通りのプログラムができあがってしまい、それぞれの個性――こだわりともいう――が強烈に出てしまうのですが、COBOLにはそういう要素を入れ込む余地がないということ。
実際、作者も仕様書を見ずに
「ああ、このプログラムはこんな感じか。なら今回の修正はこれじゃ無くてこっちのプログラムの方がいいか」
というのが、割とすぐに判断できちゃったりします。もちろん、それまでそのシステムに触れてきた経験もありますけどね。
そして、そんな特徴もあってか、面倒なことも起きてます。
「COBOLのプログラムは仕様書が無いから困る。だからCOBOLはダメ、やめるべき」
仕様書をキチンと作成して維持するのはプログラム言語の機能じゃ無いだろう……
あと、全く新しい言語でシステムを構築するときだって、今までのシステムの仕様書って必要だからね?
コの業界にいない人にはなかなか理解されませんが、仕様書とプログラムって完全にイコールじゃ無いんですよ。仕様書には「このプログラムが想定している入力データ」とか、「このプログラムが使われる業務局面」というような、プログラムには記述しない情報も含んでるのです。
わかりやすい例でいうと、「このプログラムは仕入れ先○○からの出荷データを受け取るプログラムである」というのが仕様書に書かれていて、実際にプログラムに読み込ませるのもそういうデータだけ。だけど、プログラムには「仕入れ先○○」という記述が書かれるかというと……微妙。かろうじて「仕入れ先○○の仕入れ先コード」が書かれているくらいで、コメントに「仕入れ先○○」が書かれているかどうか……しかも、書かれていてもそれを信じていいかどうか。そんな感じです。コの業界、コメントに嘘が書いてあるのは良くあることなので。
ということで、プログラムと仕様書はイコールではないし、仕様書をキチンと維持していくのはシステム会社の責任であって、プログラム言語にそれを求められても、というのが作者の所感です。
そんなわけで、COBOLを忌避する理由ってのがイマイチ納得できるものが見当たらないんですよね。何かの陰謀を感じる……といってもいいかも?
とはいえ、COBOLは前科持ちなので、今後のことを考えると見直しを進めるのもやむなしなのかも知れません。
前科とは?
もはや当時のエンジニアたちが一線を退き始めているのですが、全世界で頑張って対応した、西暦二千年問題です。メモリやディスクが高価だったために年を下二桁で扱っていたのが原因とか言われてますが、一番の原因はCOBOLのこの命令だと、作者は思ってます。COBOLのプログラム、特に日付を取り扱うプログラムではよく見かける命令がこれ。
ACCEPT 変数名 FROM DATE.
これをやるとシステム日付を取得できるのですが、六桁で返されるんですよね。つまり年下二桁、月二桁、日二桁がつながって六桁の数字として変数に格納される。COBOLが出来た当時ならともかく、COBOL85くらいの時期になったなら、なんか解決策を用意しておけよ、と突っ込みたくなります。ちなみに年が四桁で取得できるような命令はCOBOL2002から用意されたらしく……手遅れ感がすごい。もっと前に出せと。
そんなわけで、だいたいのCOBOLプログラムはこんな感じでシステム日付を定義していたりします。
03 TODAY-DATE.
05 TODAY-Y1 PIC 9(2).
05 TODAY-YMD.
07 TODAY-YY PIC 9(2).
07 TODAY-MM PIC 9(2).
07 TODAY-DD PIC 9(2).
んで、
ACCEPT TODAY-YMD FROM DATE.
MOVE 20 TO TODAY-Y1.
これで年が四桁のシステム日付が取得できました。
なお、日付の処理をするプログラムで二千年をまたぐ可能性があるときには苦肉の策でこんなものも。
IF TODAY-YY < 90
MOVE 19 TO TODAY-Y1
ELSE
MOVE 20 TO TODAY-Y1
END-IF.
まあ、この辺の微妙な苦労がついて回ったりする一方で、COBOLを取り巻く環境は色々変わっていて、ざっくり言うと三つほどに分かれてます。
一つ目が今までにも説明にあげてきたような汎用機系。今までずっとCOBOL、これからもCOBOLという、いわゆるネイティブなCOBOL環境で、今後どの程度サポートされるのかが注目されるところ。
二つ目がPC環境でCOBOLを動かすというもので、いくつかのベンダーが提供しています。割と普通にPC用の入力画面が作れたり、バッチ処理が実行できたりしてます。
三つ目がCOBOLをコンパイルするときに別の言語に変換しつつ実行プログラムを作るというもの。これは実際に数年触ってましたが、ちゃんとCOBOLのくせに、その中間の言語の特徴が生きていたりしてちょっと面白い挙動もしましたし、とんでもないバグを引き起こしてくれて、サポートに問い合わせましたが、修正パッチは出ませんでした。過去の話です、はい。
そんなわけで、使われているし、これからも使われ続けるんだろうけど、どういうわけか一部の界隈――かいわい言いたいだけだろという突っ込み歓迎――からは毛嫌いされている上に西暦二千年問題の元凶でもあったCOBOLでした。
なお、西暦二千年問題については色々ありますが、知りたいという方は感想欄にリクエストしてくださると、その気になるかも知れません。