COBOLをAWS上のマイクロサービスとして使ってみる

# 初めに
COBOLが使われだして60周年。

~~ビューが稼げるからか、言っとけば知ってる風に思われるからか常に悪者にされつつも、~~COBOLは使われ続けています。

今回はそんなCOBOLでも、いやCOBOLだからこそ、クラウド上のマイクロサービスとして提供できるといったところを実証していきたいと思います。

# COBOLとデータ処理

COBOLと聞いて、多くの皆様が一番に思い浮かべるのは金融システムかと思います。
そもそもCOBOLは事務処理用の言語として発展し、優位にある仕組みを持っています。

大きな特徴としては以下2点です。

- 十進演算
通常、PC上での計算は0,1のビットで数値を表すため、二進数での演算が行われます。
しかし、金融などの大きな金額を扱うシステムで金利計算などを行う際、一般に使われるdoble型などで浮動小数点の計算をしてしまうと、丸め誤差が発生してしまい、正しい金額が算出できない場合があります。
COBOLでは数値を固定十進演算で扱うため誤差が出ないという特長から、金融データなどの計算に主に使われてきました。

- テキストデータ処理
COBOLでは大量のテキストデータを処理することが得意です。
これにより、膨大なデータを1行ずつ読み込み集計するようなことが簡単に記述できます。

# COBOLとクラウド

COBOLや、COBOLが実行されている環境はクラウドの考え方を先取りしているといっても過言ではありません。
COBOLの得意とするバッチ処理の実行形態として、Job Control Language（JCL、ジョブ制御言語）があります。
JCLそのものはシェルスクリプトなどに近いものであり、なんでもできますが、COBOLを呼び出す際には以下のような構文が利用されます。
（Wikipediaよりコードの一部を拝借しています。[Job Control Language](https://ja.wikipedia.org/wiki/Job_Control_Language)）

```
//HCKTHN JOB CLASS=A,MSGCLASS=X
//STEP01   EXEC PGM=ABCDEFGH
//SYSPRINT DD  SYSOUT=*
//INPUT    DD  DSN=IS198.TEST.INPUT,DISP=SHR
//OUTPUT   DD  DSN=IS198.TEST.OUTPUT,DISP=OLD
```

複雑な例文ですが、簡単にいうとプログラム`ABCDEFGH`を、入力ファイルとしてファイル`IS198.TEST.INPUT`、出力ファイルとして`IS198.TEST.OUTPUT`を設定して実行するといったものになります。

このようなプログラムを複数つなげて、以下のような流れをバッチ処理として行います。

```
必要なデータをデータベースから取り出し、ファイルAを作成する
↓
プログラムXにファイルAを入力し、データを扱いやすく加工しファイルBを作成する
↓
プログラムYにファイルBを入力し、集計を行い、結果をファイルCに書き込み
```

お分かりいただけたでしょうか。
これは、プログラムX、プログラムYといった個別に作成されたマイクロサービスを、データ（ファイル）を用いた疎結合システムとして、JCLというフローで実現されている、非常に近代的なクラウドシステムと類似したものになっています。
つまりCOBOLはクラウドのアーキテクチャの祖先といっても過言ではない(｀･ω･´)

# 今回実現したこと、したいこと

前置きが長くなりましたが、今回我々が実現するものは以下になります。

* 大量データを高速で処理できるCOBOLコードが手軽に作れるようにする
* COBOLプログラムをクラウドのマイクロサービスであるAWS Lambdaで連携させる

## ファイル入出力処理のローコード開発化

ですが、現在では入出力として扱うファイルが純粋なテキストファイルであることはほぼなく、EXCELなどのアプリケーションで作られるファイルであったり、JSONなどの多システムで扱いやすいファイルであることが一般的です。

このためCOBOLの得意とするデータ加工、集計処理のロジック部分だけを作成し、入出力に関してはツールにまかせることで、前述したCOBOLの優位性を活用することを考えました。またCOBOLプログラムコーディングで記述が面倒（もしくは古臭い）と思われる箇所を不要とし、データ加工のみに注力できるローコードコンセプトを示したいとの思いもありました。

## 検証用のデータおよびプログラム

今回、我々としては２つのツールを作成し、検証を行いました。
また、データとしては、[東京都公金管理局の公金支出情報（一般会計・特別会計）](https://www.kaikeikanri.metro.tokyo.lg.jp/31koukaidata.htm)を一部抜粋し、利用させてもらいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/43b29f01-82ca-cee3-68b9-106d7a67b6b5.png)

集計対象としては、シートの「支払内容（件名）」列内にある、特定のワードを独自に（タクシー、補助金）などを指定し、各ワードごとの金額を集計します。

### 演算処理プログラム生成

ローコード開発化に当たり、次のようなプログラム自動生成のマクロを作成しました。

入力ファイル

* 入力ファイルのデータレイアウト
* 出力ファイルのデータレイアウト
* 演算処理のコード

出力ファイル

* COBOLプログラム

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/971c13ed-533a-82cb-0e5d-2a836d8e416c.png)


今回は一例としてEXCELとVBAマクロを利用して作成しました。
入力ファイルはEXCEL、出力はJSONとしています。
基本的にはデータベースの定義ファイルと、実行するSQLを記載しているものと考えていただければと思います。

COBOL用のレイアウトを記入し、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/55d5652d-e004-12ed-9b19-cd0bac2fcc50.png)

処理部分を記載します。（普通に描いたプログラムを転載する感じ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/ad459420-92ca-0f8d-5dc7-aafcd0631824.png)

マクロを実行するとCOBOLプログラムが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/4e1e98b2-cb84-b5c7-67e5-ad4d2fd6206b.png)



### EXCELtoTSVプログラム

理想としてはCOBOLそのものがEXCELを読み込めるようになるといいのですが、今回はそこまでの時間はなかったため、EXCELのデータをCOBOLが読み込めるTSVファイルに変換するプログラムを作成しました。
こちらはperlで作成しています。

以下のような利用イメージになります。

```
# ＥＸＣＥＬファイルをTSVファイルに置き換える。
#    引数１：EXCELファイル名
#    引数２：EXCELシートの先頭見出し行数（読み飛ばしたい行数）
#    引数３：出力先ファイル名
# - ブック内先頭シートのみをTSVファイル化する。
```

先ほどのEXCELをTSV化すると以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/bf57c703-9451-6114-34ba-13638c747f3b.png)

### ここまでのまとめ

ここまでで、COBOLのデータ処理部分を現状よく使われるファイル形式に対応することが容易になりました。

## COBOLのマイクロサービス化

### AWS Lmbda関数の構築

ここからは、上記で生成されたアプリケーションをAWS LambdaとS3のサービスを活用してマイクロサービス化していきます。
※Lambda上でカスタムランタイムにて様々なアプリを動かすためのあれやこれやは別途記事にしますので、ここでは省きます。

実現する手順は以下になります。
前書きに登場したプログラムXがperlで、プログラムYがCOBOLだと思っていただければ流れがわかりやすいかと思います。

* 処理したいEXCELファイルのデータをS3の`INPUT`フォルダにアップロードする
* Lambda上でperlにてファイルを加工し、出来上がったファイルをS3の`CONVERT`フォルダにアップロードする
* Lmbda上でCOBOLプログラムで集計を行い、結果をS3の`OUTPUT`フォルダにアップロードする
* ~~Lambda上でなんらかの処理を行い、集計結果をDBなどに格納する~~
* ~~ダッシュボードから集計結果を確認する~~

※下2件は時間の都合上未実装となりましたのであしからず
※S3のファイル操作についてはawscliにて行っています

基本的にユーザーはEXCELをS3の所定の場所にアップロードするだけで、自動的に集計が行われる仕組みです。

### 実行イメージ

動作のイメージを一部記載します。

lambda上の見た目（COBOL）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/6f2d8e7c-e045-cd61-3910-208c8cfa5214.png)


S3にEXCELファイルをアップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/4d74b87f-a6b5-dbd3-79fb-703ddf6ab897.png)

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/d47d2cb1-a417-0591-da0d-a33ff87350e8.png)

結果のファイル（成形済み）

```json:koukin_sample.xlsx.tsv.json
[
	{
		"トナー": 24603,
		"旅費": 16045227,
		"灯油": 0,
		"キーボード": 0,
		"オリンピック": 0,
		"公園": 0,
		"タクシー": 3684483,
		"奨励金": 0,
		"手当": 0,
		"観光": 0,
		"補助金": 269126906,
		"報償": 4389835,
		"漁業": 0,
		"働き方改革": 0
	}
]
```

Lambdaのログ（COBOL）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/e8d065bf-e14b-0fac-d3b3-05145a860fae.png)

### ここまでのまとめ

このような形でファイルの入出力を行うCOBOLのバッチ処理を、流れをそのままクラウドに乗せることができました。

# 最後に

今回、我々のチームが実装、検証した内容は、IoTやドローンなどあまり目新しいものはない取り組みでした。
しかしながら、これまでの様々なシステムを支えてきたCOBOLが、そのままクラウドでも堅実なシステムとしてやっていけることを実証できればと考えています。

# 参照

- 今回のサンプル環境については、以下記事に詳細をアップロードしています。
    - [「COBOLをAWS上のマイクロサービスとして使ってみる」の環境構築](https://qiita.com/nor51010/items/528d81bd923fce104cfa)

- 本件はCOBOLハッカソン2020の「チームOSSコンソーシアム」での成果物になります
    - [COBOLハッカソン2020](https://hackcamp.doorkeeper.jp/events/102572)