動機
オブジェクト指向言語じゃない、COBOLで依存性逆転の法則を実践してみて、疎結合の理解を深める。
プログラミング言語の制約が色々あるので、イマイチですが(COBOLには動的に依存性を注入するような仕組みがなく、コンパイル&リンク時に具象モジュールを結合しなければいけないなど)、疎結合な内部設計の発想を広げるということで。
この原則に従うとソフトウェアの振る舞いを定義する上位レベルのモジュールから下位レベルモジュールへの従来の依存関係は逆転し、
結果として下位レベルモジュールの実装の詳細から上位レベルモジュールを独立に保つことができるようになる。
A. 上位レベルのモジュールは下位レベルのモジュールに依存すべきではない。両方とも抽象に依存すべきである。
B. 抽象は具象に依存してはならない。具象が抽象に依存すべきである。
この上位レベル、下位レベルの両方とも抽象に依存しなければならないと言う要求により、この設計原理は一部の人々のオブジェクト指向プログラミングに対する考え方を反転させる。
シナリオ1
CSV形式で商品名と価格を出力するCOBOLアプリ、PRICE-APPを作ります。
APPLE,12345
従来のレイヤーパターン
上位レベルのプログラム(PRICE-APP)は下位レベルのプログラム(SHOW-PRICE-CSV)をCALL。
ソースファイル名=PRICE-APP.cbl(PROGRAM-ID=PRICE-APP)
---> ソースファイル名=SHOW-PRICE-CSV.cbl(PROGRAM-ID=SHOW-PRICE-CSV)
依存性逆転パターン
COBOLには抽象クラスがないので、どうするか? PROGRAM-ID
を抽象クラスに見立て、ソースファイル名を具象クラスに見立てます。
ソースファイル名=PRICE-APP.cbl(PROGRAM-ID=PRICE-APP) ---> PROGRAM-ID=SHOW-PRICE
^
|
ソースファイル名=SHOW-PRICE-CSV.cbl
図を書き換えているだけで、コードは何も変わっていないように見えますが、
PROGRAM-ID
を抽象クラス名に見立てSHOW-PRICE
に書き換えて(CSV
を取り外し抽象的な名前にしてみました)、
ソースファイル名
を具象クラス名に見立てて、SHOW-PRICE-CSV.cbl
にして俯瞰してみると、
PROGRAM-ID
さえ同じなら、具象クラスは何でも良くて、差し替え可能と見えてきます。
シナリオ2
PRICE-APPの変更しないで、JSON形式で商品名と価格を出力するCOBOLアプリを作ります。
{"NAME":"APPLE","PRICE":12345}
呼び出し元のPRICE-APPを変更しないで、JSON形式のプログラムに差し替える
PROGRAM-ID
とその引数を変えずに、ソースファイル名を別の名前にしてJSON形式で出力するプログラムを作り、
コンパイル&リンク時にそのソースに差し替えればJSON形式の出力アプリができます。
ソースファイル名=PRICE-APP.cbl(PROGRAM-ID=PRICE-APP) ---> PROGRAM-ID=SHOW-PRICE
^
|
ソースファイル名=SHOW-PRICE-JSON.cbl
COBOLソース
下記dockerコンテナの/home/cobol
直下に次の3つのファイルを作ります。
000000 IDENTIFICATION DIVISION.
000000 PROGRAM-ID. PRICE-APP.
000000*--------------------------------------------------------------
000000 ENVIRONMENT DIVISION.
000000*--------------------------------------------------------------
000000 DATA DIVISION.
000000*--------------------------------------------------------------
000000 WORKING-STORAGE SECTION.
000000 01 POUT SYNC.
000000 03 POUTNAME PIC X(5) VALUE 'APPLE'.
000000 03 POUTPRICE PIC 9(5) VALUE 12345.
000000*--------------------------------------------------------------
000000 PROCEDURE DIVISION.
000000 A00-MAIN SECTION.
000000 A00-010.
000000 CALL 'SHOW-PRICE' USING POUT.
000000 A00-EXIT.
000000 MOVE ZERO TO RETURN-CODE.
000000 GOBACK.
000000 IDENTIFICATION DIVISION.
000000 PROGRAM-ID. SHOW-PRICE.
000000*--------------------------------------------------------------
000000 ENVIRONMENT DIVISION.
000000*--------------------------------------------------------------
000000 DATA DIVISION.
000000*--------------------------------------------------------------
000000 WORKING-STORAGE SECTION.
000000*--------------------------------------------------------------
000000 LINKAGE SECTION.
000000 01 POUT SYNC.
000000 03 POUTNAME PIC X(5).
000000 03 POUTPRICE PIC 9(5).
000000*--------------------------------------------------------------
000000 PROCEDURE DIVISION USING POUT.
000000*--------------------------------------------------------------
000000 A00-MAIN SECTION.
000000 A00-010.
000000 DISPLAY POUTNAME ',' POUTPRICE.
000000 A00-EXIT.
000000 MOVE ZERO TO RETURN-CODE.
000000 GOBACK.
000000 IDENTIFICATION DIVISION.
000000 PROGRAM-ID. SHOW-PRICE.
000000*--------------------------------------------------------------
000000 ENVIRONMENT DIVISION.
000000*--------------------------------------------------------------
000000 DATA DIVISION.
000000*--------------------------------------------------------------
000000 WORKING-STORAGE SECTION.
000000*--------------------------------------------------------------
000000 LINKAGE SECTION.
000000 01 POUT SYNC.
000000 03 POUTNAME PIC X(5).
000000 03 POUTPRICE PIC 9(5).
000000*--------------------------------------------------------------
000000 PROCEDURE DIVISION USING POUT.
000000*--------------------------------------------------------------
000000 A00-MAIN SECTION.
000000 A00-010.
000000 DISPLAY '{"NAME":"' POUTNAME '","PRICE":' POUTPRICE '}'.
000000 A00-EXIT.
000000 MOVE ZERO TO RETURN-CODE.
000000 GOBACK.
実行環境
COBOLのちょいお試しのdockerコンテナイメージを公開してくださっているので、こちらを活用しました。
プログラムちょい替え(4)COBOLを40年ぶりにうごかしてみた:dockerでcobol, docker(81)
コンテナイメージの取得と実行
docker run -v /home/madilloar/prj/cobol:/home/cobol -it kaizenjapan/cobol /bin/bash
コンテナイメージの起動と停止
docker start boring_mendeleev
docker stop boring_mendeleev
コンテナ内に入る
docker exec -it --user root boring_mendeleev bash -p
コンパイル&リンク、及び実行
CSV形式プログラムのコンパイル&リンク
cd /home/cobol
cobc -x -o PRICE-APP PRICE-APP.cbl SHOW-PRICE-CSV.cbl
./PRICE-APP
APPLE,12345
JSON形式プログラムのコンパイル&リンク
cd /home/cobol
cobc -x -o PRICE-APP PRICE-APP.cbl SHOW-PRICE-JSON.cbl
./PRICE-APP
{"NAME":"APPLE","PRICE":12345}