COBOL

COBOL（コボル）は、1959年に事務処理用に開発されたプログラミング言語である。名前は「」（共通事務処理用言語）に由来する。
概要.
非理系の事務員や官吏でもプログラミングできる言語として設計されたため、自然言語である英語に近い記述をめざしたコマンド語彙や構文（シンタックス）が採用されている。特に金額計算など事務処理用に広く使われている。COBOLは自然言語（英語）に近い構文を持つため、そのソースコードは記述が冗長にはなるが、可読性が高い。本のように、部、節、段落、文という階層で記述される。人によっては関数や数式だらけの言語よりもハードルが低い。リフレクションができないなど、モダンなプログラミング言語に比べて論理制御機能は貧弱である。一方、文字列解析や文字列編集、帳票、画面編集などの事務処理機能は豊富である。
COBOLは仕様の古い言語である。ただ、言語規格は拡張が続けられていて、2002年版以降ではオブジェクト指向にも対応して部品性を向上した。現実のプロジェクトで制約となるのは、COBOLの言語機能の不足よりは、稼働プラットフォーム、業務運用あるいは保守体制である場合も多い。
COBOLは、科学技術計算向けのFORTRANに次いで国際的な標準化が行われた、初期のプログラミング言語である。過去のバージョンとの互換性を重視した国際標準規格にしたがって多くのプラットフォームでコンパイラが開発されてきたので、COBOL to COBOLのマイグレーション（プラットフォームの更新）は比較的容易である。
膨大なCOBOLプログラムおよびそれらの処理するデータが、企業や政府機関に長年開発し続けられ稼働している。ガートナー発という情報によれば、メインフレームが世界1万サイト以上あって3万8千のレガシーシステムがあり、COBOLは全プログラム約3,100億行のうちの約65%の約2,000億行あって、毎年約50億行が増えているという
。これはFORTRANとアセンブラを合わせた資産の数十億行に比べて圧倒的に多い。また、世界の商用データの約75%、商用トランザクションの80%以上（Google検索の200倍以上）である。COBOL開発者は85万人以上いるが、COBOL開発者の増加より減少がずっと速いという。
日本国内では、2016-2021年のソフトウェア開発データ1,476件をまとめたIPAのレポートによると、1位のJava（42.4%）に次いでCOBOLは16.3%で2位である。
このように、誕生から60年以上たってもなお主流言語のひとつの座を占めている点で、他の初期の言語を引き離している。
誕生経緯.
1950年代、事務処理言語は開発メーカーごとに異なっていた。その統一の必要性を認識していたアメリカ国防総省によって、事務処理用の共通言語の開発が提案され、CODASYL（Conference on Data Systems Languages、データシステムズ言語協議会）が設立された。そうした背景の下、1959年にCODASYLによって開発された共通事務処理用言語がCOBOLである。
その後、1960年1月にCODASYL執行委員会によって最初の仕様書が承認され、合衆国政府印刷局に送られた。この最初の仕様書は1960年4月に発行され、通称COBOL-60と呼ばれている
COBOLの開発により、アメリカ政府の事務処理システムは全てCOBOLのみで納品されることとなった。これに伴い、COBOLは事務処理用言語として世界中に普及することになる。
現状.
C言語やJavaなどの登場後も、COBOLは主に商用計算記述用として、主に金融業界や行政サービスなどで広く使用されている。
COBOL言語規格は、ローカル変数が作りにくく論理制御機能面が弱かった古典的言語からの脱皮を図っている。オブジェクト指向を採用し、入れ子プログラムを可能としたうえ、COBOLからCOBOLクラスライブラリのみならずJavaのクラスライブラリも呼べるようにするなど、相互運用性や共同開発容易性、安全性を改善してきている。
2019年現在、COBOL Cowboys社の調査では2000億行のCOBOLプログラムが現役で、フォーチュン500企業の90%がCOBOLプログラムを使い続けている。またマイクロフォーカス社のDerek Britton氏は「COBOLシステムを運用している組織が万単位で存在」「この言語が世界のトランザクション処理システムのうちの70％で用いられている」と述べた。
数多くの新しい言語やフレームワークが現れた現代、COBOLで作られるシステムはレガシーであり、システム刷新時に仕様を把握した有識者が居ない事や、新技術への対応の難しさが問題になる事がある。
COBOLの言語仕様.
年齢を表すageという変数の値を、一定の年数を表すyearsという変数の値の分だけ増やす手続きは、例えば普通のプログラミング言語では
と書かれる。COBOLでも同様にCOMPUTE文によって
と記述することもできるが、
という表現も可能である。
このように、数学やアルゴリズムの知識を豊富にもっていなくても、全て現在形、語尾変化なし、など、構文上の約束事さえ覚えて、英語による理路整然とした記述ができれば、COBOLのプログラムを書けるように考えられている。つまり事務処理の手順を逐一細かく英語で書き下せば事務処理が電算化できるということである。さらにプログラムのコードそのものがプログラムの機能を説明する仕組みになっているので、そのまま読み下したときに分かりやすい。
こういった特性を、まだ人工知能、自然言語処理の研究が浅い時期に追求してCOBOLを設計したのは、意義深く、産業的にも効果があった。ただ、ソフトウェアが大規模化し相互に絡み合うように接続されてきた現代、動詞や前置詞を明示するかどうかという命令記述の次元だけでは視点が不足である。モジュール性、処理の強力さを含めて可読性と保守性を総合評価しなおすと、場面によってはまたちがう結果も生じてくる。
自然言語指向な書き方が優れているといっても、複雜な数式、関数を扱う科学技術計算分野における制御・演算には向いていない。二次方程式 A X2 + B X + C = 0 の解（の片方）を求める手続きは、COBOLでもCOMPUTE文を用いて簡潔に書こうとすれば、
と一文で済む。ただし、数式を極力使わない書き方にこだわれば、
と演算子1個あたり1文に膨れ上がって、見通しが明らかに悪くなる。もっとも、これほど複雑な式をこのように逐一書くプログラマはおよそ現代には存在しない。
COBOLでは同じ処理を書くのに、少なくとも「COMPUTE ～」と書く必要もあり、他節に述べるようにいろいろなDIVISIONの記述も必要となるなど、モダンな言語より長くなりがちである。また、パズルのように巧妙な制御機能がさほど多彩に備わっているわけではない。Eclipseなどの統合開発環境でCOBOLも使えるようになったが、Javaのような小粒度なモジュールに関してもインタフェースを明確に記述するスタイルの言語よりも、そこでされるサポートは少ない。
このようなことから、COBOLに習熟している人がモダンな言語でのプログラミング能力が高いとは限らない。それでも、世界的に蓄積され社会を動かしているCOBOL資産を保守・更新するという使命は重要である。他言語も習熟している技術者であっても、言語の欠点を多階層な共通モジュール作成やツール作成などでカバーしながら、社会基盤を支えるCOBOL関連プロジェクトで活動している。
COBOLの文法の概要.
主にANSI COBOL 1985の文法について述べる。
表記法.
COBOLの文法は英語の表現に近い。たとえば、ある数値型変数W-NOに対し数値100、英字型変数W-CHARに文字列'ABC'を代入する場合は、以下のような表記をする。
このように、COBOLの文法は自然言語（英語）に類似した文章的なものであることから、その可読性（ドキュメント性）の面で優れていると言われている。ただし、数学の定理を例にとれば、それを自然言語に直したところで理解が容易になるわけではないため、これは否定派にはCOBOLの冗長性と捉えられる部分でもある。
プログラムの書式.
典型的なCOBOLの原始（ソース）プログラムは、FORTRANと同様にカラム固定形式で記述する。
最近のCOBOLコンパイラには、行の長さが固定である必要がなく、一連番号の不要な自由形式をサポートするものがある。
COBOLプログラムの基本構造.
COBOLのプログラムは、次の4つのDIVISIONをこの順番で記述するのが基本となっている。
IDENTIFICATION DIVISION.
「PROGRAM-ID」（プログラム識別名）を記述する。
「AUTHOR」（作成者名）、「DATE-WRITTEN」（作成日）等の文法もあったが廃要素となった。
ENVIRONMENT DIVISION.
プログラムが実行されるコンピュータの環境を記述する。「ENVIRONMENT DIVISION」は、「CONFIGURATION SECTION」（環境節）と「INPUT-OUTPUT SECTION」（I-O節）に大別される。
DATA DIVISION.
プログラムで使用する変数及びデータ並びにその型について記述する。プログラムで使用する変数及びデータのすべては、DATA DIVISIONで定義しなければならない。
「DATA DIVISION」は、「FILE SECTION」と「WORKING-STORAGE SECTION」に大別される。データの型の宣言は、PICTURE(PIC)句によって行う。
呼ばれたプログラムが呼んだプログラムから引数でデータを受け取る場合は、それらの包含構造や基本項目の型を呼ばれたプログラムの「LINKAGE SECTION」で宣言する。
COBOLにおけるデータの分類.
COBOLのデータは、次の3つに分類される。
COBOLの扱うデータの特徴とメンテナンス.
COBOLの代表的な変数型（項類）に、次のものがある。
COBOLでは固定長のレコード（繰り返しデータ単位）の中に固定長でデータ項目を含むという使い方が多い。たとえば、
などである。データには包含関係の階層があり、領域再定義機能により同じメモリ領域を何通りかの構成で解釈できる。
他の多くの言語（VB、C、Javaなど）では、改行までが繰り返しデータ単位で、その中の項目は可変長でコンマやタブなどの区切り記号で区切るという使い方が多い。たとえばCSV形式
がある。最近のCOBOLコンパイラには、CSV形式の入出力をサポートするものもある。
COBOLでは基本項目を並べて集団項目を作る。レベル番号を用いて階層構造を作る。OCCURS句により多次元配列を作る。これらによる固定長や可変長の「レコード」（C言語などの構造体に相当）のレイアウトを定義する。なお、「レコード」という型はCOBOLによって初めて導入された概念である。
COBOLの階層的データの包含関係は、階層の深さを表すレベル番号"01"から"49"を各データ記述に付けることで記述される。
こうした階層や領域再定義などのデータ構造をもつファイルやレコードの定義と処理は、COBOLの得意とするところで、Java言語および従来のJavaのクラスライブラリによってはなかなかうまく再現できない。
COBOLでは、何百兆円という大きな金額の計算や、小数点以下何桁まで正確に複利計算をしても1円の誤差も出ない正確な小数計算が得意である。固定小数点数方式で整数とスケール（桁）を扱える数値項目は通常最大18桁（中間結果はそれ以上）あり、特に内部10進項目などの2進化10進数を用いれば、メモリを節約しつつ性能も確保できる。メインフレームではこれをサポートする専用のCPU命令まで設けられ、高速化が図られた。
このアプローチは、10進2進変換に伴う誤差が避けられない浮動小数点数によって実数を近似値で表現しようとする他の言語の発想とは対照的である。FORTRANには浮動小数点数はあっても内部10進項目などはなかった。Javaでは任意桁の整数、小数を扱えるBigInteger、BigDecimalというクラスが提供されているが、文字配列で処理しているために金額計算、利息計算をCOBOLほど少ないCPUステップでは行えていない。
COBOLでは無名の変数等として"FILLER"という名称を記述することができる。無名項目の"FILLER"は、COBOLにおける変数等の領域の定義は固定長となるため、そのような固定長領域内での予備的な領域の確保という意味合いも有している。たとえば
000100 01 PRODUCT-REC.
000200 03 PRODUCT-NO PIC 9(8).
000300 03 ...
000400 03 PRODUCT-NAME PIC X(20).
000500 03 FILLER PIC X(500).
で予備項目500バイトを含む製品レコードPRODUCT-RECを定義して他のシステムとデータを交換しはじめる。年月が経ってこのレコードに追加項目AD-START-DATE（広告開始日）が発生したら、FILLERを削ってその新項目に宛てることで、授受データのレコード長を変更しなくて済む。
000100 01 PRODUCT-REC.
000200 03 PRODUCT-NO PIC 9(8).
000300 03 ...
000400 03 PRODUCT-NAME PIC X(20).
000500 03 AD-START-DATE PIC 9(8).
000600 03 FILLER PIC X(492).
FILLERによって、固定長レコードファイルの運用が円滑になった。ただ、この例で500バイトを使い切れば、やはりレコード長の変更が必要になる。だからといってむやみに長いFILLERを入れると、容量的な効率低下を招くのでバランスが必要である。
製品が多くなってPRODUCT-NO（製品番号）を8桁から12桁に拡張しようとすると、後続の項目群の開始番地が順繰りにずれてしまうので変更の影響が大きい。
COBOLが扱うデータベースの領域定義も、多くの場合同様に固定長の項目からなるレコードという考えで行われてきた。
システムが実際に入力したデータがプログラムが用意した桁数を1桁でも超えたとき、SIZE ERRORとしてエラー処理を行うのが普通である。オプションにより上を切り落として続行も可能。桁数が不足したときにデータのミスでなければ、プログラムとそのデータを授受するシステムのプログラムで一斉に桁数を増やす修正をしなければならない。データの変換も必要となる。
このように桁数やバイト数の変更は大変なため、COBOLプログラマやSEは常に桁数やバイト数の設定や変更を意識し、プログラムの使用されるのが何十年でもその間になるべく桁溢れが起こらないように目を配って作業している。
以上のような特徴は、固定長レコードやその中の文字列や数値を容易にかつ厳密に扱えるというCOBOLの大きな長所にともなう、保守、機能追加していく上での大きな短所である。
PROCEDURE DIVISION.
実行されるプログラムの内、実際の処理部分のコードを記述する。
引数を受け取る場合は、「PROCEDURE DIVISION USING 引数名 [, 引数名……]」という書き方をする。
上記3つのDIVISIONを記述したあとやっと「PROCEDURE DIVISION」で実行手順のコードを記述する文法であるため、COBOLは「前置きが長い」言語ともいえる。
COBOLの予約語の数は膨大で、文字数の長いものが多い。
コードの実例.
実例1 (Hello world).
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLO.
000300 PROCEDURE DIVISION.
000400 DISPLAY 'HELLO, WORLD!'.
000500 STOP RUN.
出力
この例では DISPLAY命令を使って文字列をコンソールまたは標準出力に出力している。
COBOLはレコードレイアウトの決まったファイルの処理に使われることが多い。その場合はふつう、ファイル節（FILE SECTION）にレコードとそれを構成するデータ群の定義を書く。そして、実行部（PROCEDURE DIVISION）のREAD文、WRITE文などでそのレコードを読み書きする。
実例2 (Hello world).
作業領域節（WORKING-STORAGE SECTION）にデータを定義した例。
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLO.
000300 DATA DIVISION.
000400 WORKING-STORAGE SECTION.
000500 01 HELLO1 PIC X(15).
000600 01 HELLO2.
000700 03 FILLER PIC X(06) VALUE 'HELLO,'.
000800 03 FILLER PIC X(01) VALUE SPACE.
000900 03 FILLER PIC X(06) VALUE 'WORLD!'.
001000 03 FILLER PIC X(01) VALUE SPACE.
001100 03 FILLER PIC 9(01) VALUE 2.
001200 PROCEDURE DIVISION.
001300 MOVE 'HELLO, WORLD! 1' TO HELLO1.
001400 DISPLAY HELLO1.
001500 DISPLAY HELLO2.
001600 STOP RUN.
出力
実例3 (Fizz Buzz).
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. FIZZBUZZ.
000300 DATA DIVISION.
000400 WORKING-STORAGE SECTION.
000500 01 I PIC 9(3).
000600 PROCEDURE DIVISION.
000700 PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100
000800 EVALUATE FUNCTION MOD(I 3) = ZERO
000900 ALSO FUNCTION MOD(I 5) = ZERO
001000 WHEN TRUE ALSO TRUE
001100 DISPLAY 'FIZZBUZZ'
001200 WHEN TRUE ALSO FALSE
001300 DISPLAY 'FIZZ'
001400 WHEN FALSE ALSO TRUE
001500 DISPLAY 'BUZZ'
001600 WHEN OTHER
001700 DISPLAY I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)
001800 END-EVALUATE
001900 END-PERFORM.
002000 STOP RUN.
出力
COBOLでは剰余を求める際に、商・剰余それぞれを格納する変数を定義した上でDIVIDE文を用いることが多いが、商は不要で剰余のみが知りたい場合や、それを変数に格納しておく必要が無い場合は、組み込み関数のMODを用いても良い。
また、COBOLの数字項目は定義された桁数よりも少ない桁数の値が格納された場合、ゼロパディングした状態で扱うため、このまま表示させると001、002、…、098と先頭に0が補われて表示されてしまう。formula_1桁で定義された数字項目に、正の整数formula_2が格納された場合、その最上位桁の位置は左からformula_3カラム目であるから、上記のようにDISPLAY I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)と記述することで、パディングされた0を除いた部分だけを表示させることが出来る。
なお、0、負の数、小数を扱う場合は、下記のように数字編集項目によるゼロサプレスとUNSTRING文を組み合わせることでパディングされた0を除いて表示させることが出来る。
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. FIZZBUZZ.
000300 DATA DIVISION.
000400 WORKING-STORAGE SECTION.
000500 01 I PIC S9(3).
000600 01 HENSHU-IKI PIC X(4).
000700 01 HENSHU-NUM REDEFINES HENSHU-IKI PIC ---9.
000800 01 DUMMY-IKI PIC X(1).
000900 PROCEDURE DIVISION.
001000 PERFORM VARYING I FROM -100 BY 1 UNTIL I > 100
001100 EVALUATE FUNCTION MOD(I 3) = ZERO
001200 ALSO FUNCTION MOD(I 5) = ZERO
001300 WHEN TRUE ALSO TRUE
001400 DISPLAY 'FIZZBUZZ'
001500 WHEN TRUE ALSO FALSE
001600 DISPLAY 'FIZZ'
001700 WHEN FALSE ALSO TRUE
001800 DISPLAY 'BUZZ'
001900 WHEN OTHER
002000 COMPUTE HENSHU-NUM = I
002100 UNSTRING
002200 HENSHU-IKI DELIMITED BY ALL SPACE
002300 INTO DUMMY-IKI HENSHU-IKI
002400 END-UNSTRING
002500 DISPLAY HENSHU-IKI
002600 END-EVALUATE
002700 END-PERFORM.
002800 STOP RUN.
COBOLの数字編集項目によるゼロサプレスは、単純に0を空白に置き換えるだけであるから、先頭に空白が生じる（＝整数部分が右寄せになる）。ゼロサプレスを行い更に先頭の空白も除去したい（＝左寄せにしたい）場合は、空白を区切り文字に指定してUNSTRING文を用いれば良い。上記の例では、UNSTRING文実行後の変数DUMMY-IKIには常に空白が入り（対象の文字列がいきなり空白＝区切り文字から始まり、その前には何も無いため、何も入らない＝空白が入る）、変数HENSHU-IKIには数字の部分だけが入る。
実例4 (Fizz Buzz).
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. FIZZBUZZ.
000300 DATA DIVISION.
000400 WORKING-STORAGE SECTION.
000500 01 I PIC 9(3).
000600 01 HENSHU-IKI PIC X(8).
000700 PROCEDURE DIVISION.
000800 PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100
000900 MOVE SPACE TO HENSHU-IKI
001000 IF FUNCTION MOD(I 3) = ZERO
001100 MOVE 'FIZZ' TO HENSHU-IKI
001200 END-IF
001300 IF FUNCTION MOD(I 5) = ZERO
001400 STRING
001500 HENSHU-IKI DELIMITED BY SPACE
001600 'BUZZ' DELIMITED BY SIZE
001700 INTO HENSHU-IKI
001800 END-STRING
001900 END-IF
002000 IF HENSHU-IKI = SPACE
002100 MOVE I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)
002200 TO HENSHU-IKI
002300 END-IF
002400 DISPLAY HENSHU-IKI
002500 END-PERFORM.
002600 STOP RUN.
出力結果は実例3と同じであるが、STRING文による文字列の連結を利用することで、3の倍数かつ5の倍数（すなわち15の倍数）か否かの判定を無くしている。なお、上記の例におけるSTRING文は、Java等におけるhenshu_iki = henshu_iki + "Buzz";（あるいはこれを略記したhenshu_iki += "Buzz";）と同様の動作をする。
標準化.
CODASYLによって標準化が行われてきて、また、ANSIやISO/IEC JTC 1 SC22/WG4などによっても標準化されていた。
1992年1月にCODASYLのCOBOL委員会とANSIのCOBOL委員会は一本化された。
なお、国際規格は ISO/IEC 1989、日本規格は JIS X3002（旧JIS C 6205）である。
CODASYL COBOLの言語仕様の変遷.
CODASYLでは常時言語仕様の改定をおこなっており、その成果を1～5年ごとにとりまとめてCOBOLの仕様書を発行していた。