【俺的】COBOL→Java言語移行ガイド（全体構造編）

## 検証環境
|COBOL|Java|
|:---:|:---:|
|cobc (GnuCOBOL) 3.1.2.0|java 14.0.1 2020-04-14|

## はじめに
[前回の記事](https://qiita.com/zama_8722/items/2e9f82a77c9bebfe12a8)では、「なぜマイグレーションが進んでいるのか」「マイグレーションのいいところと課題点」を見ていきました。今回はCOBOLとJavaで、「全体的な書き方でどう変わってくるのか」を書いていこうと思います。

### 閲覧してほしい方
* これからCOBOLからオープン系へのマイグレーションに従事する方
* COBOLとJavaの言語的違いを知っておきたい方
* COBOL習熟者で、将来オープン言語を触らなければならないがわからない方

COBOL未経験でマイグレーションされる方や、これからCOBOLエンジニアからJavaエンジニアに移る方の駆け出し資料として参考になれば幸いです。

## 全体構造の比較
まずはCOBOLの全体構造、Javaの全体構造（main）を見てみます。

__COBOL__

```
      *--1---------2---------3---------4---------5---------6
       IDENTIFICATION DIVISION.
       PROGRAM-ID. EXAMPLE.
       ENVIRONMENT    DIVISION.
       DATA           DIVISION.
       PROCEDURE      DIVISION.
       MAIN           SECTION.
       MAIN-S.
      * TODO CODE APPLICATION LOGIC HERE
       MAIN-E.
         STOP RUN.
```

__Java（mainクラス）__

```java
package com.qiita.zama_8722;

public class Example {

    public static void main(String[] args) {
        // TODO code application logic here
    }
    
}
```

オープン系言語同士であれば似通ったところが多いと思いますが、COBOLとオープン系言語の場合、全体的な書き方が大きく変わってきます。

### １．COBOLには4つの`DIVISION`がある
COBOLには

* `DENTIFICATION DIVISION`
* `ENVIRONMENT DIVISION`
* `DATA DIVISION`
* `PROCEDURE DIVISION`

があり、それぞれの`DIVISION`で何を書かなくてはいけないかが決められています。
詳細は[こちら](https://qiita.com/zama_8722/items/65935680e157de2c7927#cobol%E3%81%AE%E6%A7%8B%E6%88%90)を御覧ください。

例えば、データ項目（変数）は`DATA DIVISION`に（その中でもこのモジュールのみで使用すものは`WORKING-STORAGE SECTION`、呼び出し元モジュールの項目を引き継ぐ場合は`LINKAGE SECTION`に）まとめて書く必要がありました。
また、COBOLは古い言語で、入出力がテープの時代でしたので、メインプログラムでは`ENVIRONMENT DIVISION`に、「JCLで定義されたテープ1は入力なのか出力なのか」「そのテープのレイアウトはどうなっているのか」を定義してあげる必要がありました。
しかし、Javaになると、変数の定義は随所で可能になります。メソッドの中で定義すればそのメソッド内でのみ使用可能になり、メソッドの外に書けばそのクラス内で使用可能（クラス変数）になったりします（アクセス修飾子によればクラス外からも使用可能）。また、オープン系言語はテープを使いませんので、`ENVIRONMENT DIVISON`で定義している内容全体的に不要になります。

### ２．COBOLはモジュール、Javaはメソッドを呼ぶ
外部のライブラリや基盤機能を使用するにあたって、COBOLとJavaでは呼び出しや値の受け渡しの仕組みが違います。
下位の機能を呼び出したいとき、COBOLは`CALL`文を使用して下位モジュール自体を呼び出し、呼び出されたモジュールはメインから一通り実行します（つまり、下位モジュールのこの`SECTION`だけ実行というのはありません）。

#### COBOLで外部機能（モジュール）を呼び出す例

__メインモジュール__

```
      *--1---------2---------3---------4---------5---------6
       IDENTIFICATION  DIVISION.
       PROGRAM-ID. MAINMODULE.
       ENVIRONMENT     DIVISION.
       DATA            DIVISION.
       WORKING-STORAGE SECTION.
        01 MSG         PIC X(5).
       PROCEDURE       DIVISION.
       MAIN            SECTION.
       MAIN-S.
         PERFORM SUBMODULE.
         DISPLAY MSG.
       MAIN-E.
         STOP RUN.
      *****************************************************
       SUBMODULE       SECTION.
       SUB-S.
         CALL 'SUBMODULE'  USING MSG.
       SUB-E.
         EXIT.
```

__サブモジュール__

```
      *--1---------2---------3---------4---------5---------6
       IDENTIFICATION  DIVISION.
       PROGRAM-ID. SUBMODULE.
       ENVIRONMENT     DIVISION.
       DATA            DIVISION.
       WORKING-STORAGE SECTION.
        01 HELLO       PIC X(5) VALUE 'HELLO'.
       LINKAGE         SECTION.
        01 MSG         PIC X(5).
       PROCEDURE       DIVISION
                       USING MSG.
       MAIN            SECTION.
       MAIN-S.
         MOVE HELLO    TO MSG.
       MAIN-E.
         GOBACK.
```

一方Javaは、呼び出したいクラスをインスタンス化した上で、呼び出したいメソッドを指定し、呼び出し先クラスは呼び出されたメソッドのみを実行します。ただし、クラス変数等の初期化を行うコンストラクタ（ここでは`public Library()`）は、インスタンス化時に自動で実行されます。

#### Javaで外部クラスを呼び出す例

__呼び出し元Javaクラス__

```java
package com.qiita.zama_8722;

public class Example {

    public static void main(String[] args) {
        Library lib = new Library();
        String msg;
        msg = lib.getHello();
        System.out.println(msg);
    }
    
}
```

__呼び出し先Javaクラス__

```java
package com.qiita.zama_8722;

public class Library {
    
    private String msg;

    public Library() {
        // 初期値は"Hello"
        msg = "Hello";
    }
    
    public String getMsg() {
        return this.msg;
    }
    
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

```

COBOL、Javaの処理の流れを図にすると、以下のようになります。

![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163288/9694fade-3eaa-36c3-f456-6e88954526f0.png)

端的にまとめると、COBOLは手続型言語、Javaはオブジェクト指向言語です。ちなみに、それぞれの意味は、

>__手続き型言語 【procedural language】__
>手続き型言語とは、プログラミング言語の分類の一つで、コンピュータが実行すべき命令や手続きを順に記述していくことでプログラムを構成する言語。
>_[手続き型言語（procedural language）とは - IT用語辞典 e-Words](https://e-words.jp/w/%E6%89%8B%E7%B6%9A%E3%81%8D%E5%9E%8B%E8%A8%80%E8%AA%9E.html)_

>__オブジェクト指向言語 【object-oriented language】__
>オブジェクト指向言語とは、プログラミング言語のうち、互いに関連するデータの集合とそれらに対する手続き群をひとまとめにした「オブジェクト」（object）をプログラムの基本的な構成単位として扱うことができるもの。
>_[オブジェクト指向言語（object-oriented language）とは - IT用語辞典 e-Words](https://e-words.jp/w/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E8%A8%80%E8%AA%9E.html)_

です。

### ３．COBOLとJavaの値の受け渡し方の違い
上記の図でも少し説明を入れていますが、COBOLはモジュール間で値を受け渡しするとき、呼び出し元は`CALL`文の後ろに`USING`句を記載し、そこに呼び出し先モジュールに渡したい項目（もしくはCOPYレイアウト）を記載します。呼び出し先では、`LINKAGE SECTION`と`PROCEDURE DIVISION`の`USING`句に受け取る項目（もしくはCOPYレイアウト）を記載します。実行結果の返却も渡されたCOPYレイアウトに入れることによって、呼び出し元モジュールで`USING`句に記載したCOPYレイアウトに結果が入ります。

Javaの場合、「値が返ってくるメソッド」「値が返ってこないメソッド」の2つがあります。
「値が返ってくるメソッド」は、メソッド名の前に「返す値の型」を記載し、返す値は`return`文に記載します（先程の呼び出し先Javaクラスの`getMsg()`がまさにそうです）。
一方、「値が返ってこないメソッド」は、メソッド名の前に`void`を記載します。`void`と記載すれば、そのメソッドに`return`文は書きませんので、返却値がありません。

## まとめ

ここまで、COBOLとJavaで、全体的な構造や外部機能の呼び出し方がどう違うのかをざっくり見てきました。
次回は、項目の定義方法や基本文法の書き方の違いを見ていこうと思います。

続き→[基本文法編](https://qiita.com/zama_8722/items/0ae1aa4f144f10d8d324)