はじめに
はじめまして、最近は花粉に苦しんでいる入社1年目の德永です。 部署配属されてから半年が過ぎましたが、まだまだ分からないことだらけで悩む毎日です。今回は配属後3ヶ月目辺りで関わらせていただいたCOBOLtoJavaプロジェクトで私が感じたことについてお話したいと思います。
COBOLtoJavaプロジェクトとは
システム運用保守の業務改善でレガシーマイグレーション(既存資産を活かしつつレガシーの脱却を図る)を行うプロジェクトです。現在バッチ処理で使用されているCOBOL言語で書かれたいくつかのプログラム部分をJava言語のプログラムに変更し、動作に問題がないかフィジビリティ検証を行いました。
なぜ今COBOLをJavaにする必要があるのか?
COBOLと聞いて普段業務で使用している人や「古っ」と感じた人、そもそもCOBOLって何、、?と思った人もいるかもしれません。僕は文系卒未経験で入社したのでCOBOLの存在すらほとんど知りませんでした。調べてみるとCOBOLという言語は1959年に事務処理用に開発されたプログラミング言語で、60年以上も使われ続ける歴史ある言語であることが分かりました。驚きですね。
そんな長年使われてきたCOBOLをJavaにマイグレーションする理由としては様々なものがありますが、今回の最も大きな理由としてはCOBOLエンジニアの不足が挙げられます。 弊社でも当時COBOLでの開発が主流だった時代のエンジニアは少なくなり、COBOLを読み書きできる人が減りつつあります。加えて新しい世代のエンジニアでCOBOLスキルをもつ人は珍しく後継者の人材確保も難しい中、保守性の観点でCOBOLを使い続けることが問題となっているわけです。 一方でJavaは弊社内外で開発言語の主流として広く利用されており、技術スタックの標準化の面でも適しているかつ広範なスキルセットを持つ人材の確保も比較的しやすいというメリットがあります。
マイグレーションの手法
COBOLをJavaにマイグレーションするといっても様々な方法があります。今回の場合は、既存資産を活かして構成などは変えず、バッチ処理のジョブの一つのCOBOLプログラムを、一つのJavaプログラムに書き換えるという方法を取りました。また、今回はフィジビリティを取ることが目的なのでバッチ処理の主要な以下の処理を行うプログラムのマイグレーションを行いました。
DBからのダウンロード処理
DBへのアップロード処理
マッチング処理
コントロールブレイク処理
大量データ処理
今回はそれぞれの処理についての詳細な説明は省きますが、マッチングやコントロールブレイクという言葉を聞いたことのない人も多いと思います。(私もそうでした) 簡単に説明すると、マッチング処理とは2つのファイルに含まれるデータを比較して一致するデータを見つける処理のことで、コントロールブレイク処理とは特定の項目(キー)でデータをソートしそのキーが変わるたびに異なる処理を行うことでデータを整理する処理のことです。
私自身は以下のフロー図のようなDBアップロード処理をメインで担当していました。
COBOLとJavaの違いで躓いたこと
私は入社してすぐの新人研修でJavaには触れていたのですが、COBOLとは完全初対面でした。 そんなJavaしか知らなかった私がCOBOLに触れてみて感じたJavaとの違いを書きたいと思います。
1. 構造の違い
まずCOBOLプログラムを見て一番に「なんだこれ?」となったのはJavaでは見慣れない”DATA DIVISION”や"PROCEDURE DIVISION"なる文です。 「DIVISION」をそのまま日本語に訳せば分割や区分といった意味になるので何か分けるためのものなのは分かりますが、英語にも癖があるため何を表しているのか分からず混乱しました。 通常、COBOLプログラムは次の4つのDIVISIONによって構成されています。
・IDENTIFICATION DIVISION(見出し部)
プログラムの名前やバージョン、作成者などのメタ情報がここに含まれます。
IDENTIFICATION DIVISION. PROGRAM-ID. SAMPLEPROGRAM.
・ENVIRONMENT DIVISION(環境部)
ファイルやDB、I/O装置に関する設定が含まれます。プログラムが実行される環境に関する情報を指定します。
ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL.
・DATA DIVISION(データ部)
データの型や構造を定義し、プログラム内で使用する変数やレコードがここで宣言されます。
DATA DIVISION. WORKING-STORAGE SECTION. USER-ID PIC 9(5). USER-NAME PIC X(10).
・PROCEDURE DIVISION(手続き部)
プログラムの実行手順や実際の処理が記述されます。具体的な業務ロジックや手続きが記される部分です。
PROCEDURE DIVISION. MAIN-RTN SECTION. MAIN-000. PERFORM PROG-INIT THRU PROG-INIT-EXT. PERFORM PROG-RTN THRU PROG-RTN-EXT UNTIL DATA-END-FLG = C-ON. PERFORM PROG-END THRU PROG-END-EXT. STOP RUN. MAIN-EXIT. EXIT.
こうしたCOBOLプログラムの4つのDIVISIONは使わなければ省略することも可能ですが、このDIVISIONを記述する順番は必ず守らなければなりません。 また、DIVISONの中ではSECTIONという節でさらに分けられており、階層構造になっています。 こうしてプログラムの機能が明確に分かれている点は分かりやすいですが、プログラムの規模が大きくなると定義部分だけで長大なコードになってしまいます。
JavaであればENVIRONMENT DIVISIONに記述する内容はプロパティファイルなどの設定ファイルで管理したり、DATA DIVISIONに定義する変数もクラス内で定義して具体的な業務ロジックはクラス内のメソッドで実装するなど、オブジェクト指向を活かした柔軟性の高い記述が可能です。これによりコードの再利用性や拡張性を高める事ができます。
2. 変数定義の違い
COBOLの全体的な構造が見えてきたところで、COBOLではプログラム内で使用するデータ項目の定義、Javaで言う変数の定義を一つの場所で全て行っている事が分かりました。DATA DIVISIONの WORKING-STORAGE SECTIONというところでそれが行われているのですが、いざ見てみると以下のようなPICや9のような謎の文字列が並んでいて初めてみた時は何が書かれているのかさっぱり分かりませんでした。
01 HOGEHOGE-ID PIC 9(3). 01 HOGEHOGE-NUM PIC 9(5)V99. 01 HOGEHOGE-NAME PIC X(20).
COBOLではデータ項目の定義の際PICTURE句によって指定されます。上記のPIC
というのはPICTUREの略ですね。このPICの後に続けてデータ項目の型やサイズを定義します。9やXはデータの型のことで、9は数値型、Xは文字列型を意味しています。そしてデータ型のあとのカッコ内の数字はそれぞれの項目の桁数を表しています。PIC 9(3)であれば3桁の数値型変数を定義しているということになります。小数点を指定する場合はVの後に小数部の桁数を記述します。PIC 9(5)V99というのは整数部が5桁、小数部が2桁の数値型変数を定義しているという意味になります。
Javaであれば変数定義の際にint型やString型で宣言するのに近いものですが、変数のサイズやメモリの確保が動的に行えるJavaとは異なり、COBOLではより厳密なデータフォーマットの指定や制約が求められる事が分かりました。
3. 固定長ファイルの入出力処理の違い
最後に、COBOL文法の話ではありませんが開発で苦労した固定長ファイルの処理について書きたいと思います。現在稼働しているバッチ処理間では固定長ファイルというデータが固定の長さ(バイト数)で構成されるファイル形式が扱われています。
COBOLは変数定義のところでもデータサイズを厳密に制御できたようにもともと固定長のデータフォーマットを扱うのに適した言語ですが、Javaは動的なデータ構造を扱うため固定長ファイルの処理方法について直接的なサポートはされていません。そのため、固定長ファイルの入出力の際にはバイト単位でデータを切り出していく操作を行う必要があります。今回は以下のような方法で試しました。
①固定長のファイルを読み込む
②指定したバイト数で1行分のデータを切り出し、リストに格納する
③②からさらに各列のバイト数ずつ切り出してリストへ格納していく
④全行分のデータが終わるまで繰り返す
文字コードが違っていたり、半角全角が混ざった項目があったりすると切り出しがずれてしまうことがあり苦戦しましたが、バイト単位で上記の方法を行うことでJavaでも固定長ファイルのデータを項目ごとに修正したり、改行やカンマ区切りを付与するなどの処理を行うことができました。しかし、データ量の大きいファイルを読み込む際に、COBOLでは数秒で終わる処理がJavaではバイト単位で切り出してリストへ格納するのに時間が大幅にかかってしまうという問題が見つかったため、パフォーマンスの観点において固定長ファイルの処理をJavaで行うことは難しい事がわかりました。
Javaであれば、固定長ファイルの代わりに分割処理の必要がないCSV形式のファイルを利用することでCOBOLと変わらない速度で処理を行えることも検証できたので、Javaを利用する場合はバッチ処理で扱うデータ形式においてもJavaに適した方法に変更する必要があると言えます。
おわりに
拙い文章ですが最後まで読んでいただいてありがとうございました。
今回のフィジビリティ検証は途中段階なので検証の結論を述べることはできませんが、今回のプロジェクトに関わってCOBOLに触れて感じたことなどを書いてみました。私はCOBOLに対して古い言語だから難しそうというイメージを持っていましたが、独自の構文だったり約束事が多かったりと初見では覚えることも多く戸惑う部分もある一方で、個人的には慣れれば処理部分自体は英語のようで読みやすい言語だと感じました。また、新人研修でJavaのオブジェクト指向の概念を理解するのに苦労したうえで今回COBOLに触れられたことで、改めてJavaの柔軟性や抽象さのメリットデメリットを学ぶ事ができました。(実際開発ではCOBOLよりもJavaの処理を記述するところで苦労しました) COBOLに得意なことJavaに得意なことはそれぞれ異なり、マイグレーションするにしてもただ書き換える以外にもたくさん考慮すべきことがあり、フレームワークや変換ツールの利用も状況に応じて検討していく必要があると思います。
まだまだ力不足を感じる毎日ですがもっと技術的な内容についてもブログに書けるよう、今後も日々勉強と経験を積み重ねてレベルアップしていきたいと思います。