Topik ini membahas pola fasad (facade) untuk menyediakan logika COBOL warisan di balik antarmuka modern tanpa menulis ulang logikanya. Dua strategi dibahas, yaitu menjalankan program COBOL sebagai layanan baris yang dipanggil dari proses lain dan menghasilkan modul C dari cobc agar dapat ditautkan langsung ke program pemanggil, kemudian strategi pertama diperagakan secara utuh. Pada contoh tersebut, program COBOL menerima satu baris permintaan dari standard input dan mengembalikan satu baris respons pada standard output, lalu skrip Python memanggilnya melalui subprocess dan mencetak respons berformat JSON.
Pola fasad di atas logika warisan#
Fasad adalah lapisan tipis yang berada di depan program warisan dan menerjemahkan antarmuka modern, misalnya permintaan HTTP berformat JSON, menjadi record yang dipahami program COBOL, lalu menerjemahkan responsnya kembali. Alasan utamanya adalah logika warisan yang sudah lama berjalan dan sudah teruji tidak perlu ditulis ulang, karena penulisan ulang hampir selalu membawa risiko perilaku yang berubah tanpa disengaja, sedangkan fasad menambah antarmuka tanpa menyentuh intinya. Strategi pertama memperlakukan program COBOL sebagai layanan record, yaitu menerima satu record permintaan dan mengembalikan satu record respons, sementara fasad mengeksekusinya melalui subprocess dan mengurus terjemahan format.
Strategi kedua memanfaatkan kemampuan cobc menghasilkan kode C sebagaimana dijelaskan pada pembahasan interop, sehingga modul hasil terjemahan dapat dibangun menjadi pustaka yang dimuat langsung dari bahasa modern melalui mekanisme FFI (foreign function interface). Demo topik ini menggunakan strategi pertama karena berlaku untuk bahasa apa pun dan tidak menuntut konfigurasi build tambahan. Kata kunci dari seluruh pola ini adalah perjanjian format, yaitu bentuk record yang disepakati kedua sisi dan tidak boleh berubah tanpa kesepakatan ulang.
Program COBOL sebagai layanan baris#
Perjanjian antara fasad dan program COBOL dibuat sesederhana mungkin, yaitu satu baris masukan berpanjang tetap 18 karakter dan satu baris keluaran berformat pasangan kunci dan nilai. Baris permintaan terdiri atas kode sepanjang 5 karakter, saldo 10 digit, dan lama pinjaman dalam bulan sepanjang 3 digit, sedangkan baris respons memuat STATUS, KODE, dan BUNGA, dengan nilai BUNGA sepanjang 10 digit. Perhitungannya adalah bunga datar satu persen per bulan, sehingga saldo 1500000 selama 12 bulan menghasilkan 180000.
IDENTIFICATION DIVISION.
PROGRAM-ID. FASADBUNGA.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 PERMINTAAN.
05 REQ-KODE PIC X(05).
05 REQ-SALDO PIC 9(10).
05 REQ-LAMA PIC 9(03).
01 BUNGA-HASIL PIC 9(10).
PROCEDURE DIVISION.
ACCEPT PERMINTAAN FROM CONSOLE
COMPUTE BUNGA-HASIL = REQ-SALDO * REQ-LAMA / 100
DISPLAY "STATUS=OK;KODE=" REQ-KODE
";BUNGA=" BUNGA-HASIL
STOP RUN.STATUS=OK;KODE=AB123;BUNGA=0000180000Kompilasi program dengan perintah berikut.
# kompilasi layanan bunga menjadi program yang dapat dieksekusi
cobc -x fasad-bunga.cblJalankan layanan dengan memberikan satu baris permintaan pada standard input, contohnya echo "AB1230001500000012" | ./fasad-bunga. Pernyataan ACCEPT PERMINTAAN FROM CONSOLE membaca satu baris dari standard input pada runtime GnuCOBOL, kemudian baris 18 karakter itu menempati record PERMINTAAN sehingga setiap field terisi pada posisinya tanpa penguraian tambahan. Baris permintaan contoh berarti kode AB123, saldo 0001500000, dan lama 012 bulan, yang menghasilkan bunga 180000 pada keluaran di atas.
Skema satu proses per permintaan membuat layanan ini tidak menyimpan keadaan di antara pemanggilan, sehingga dua pemanggilan tidak saling memengaruhi dan pemetaannya ke permintaan HTTP tanpa keadaan (stateless) menjadi sederhana. Konsekuensinya adalah biaya pembentukan proses pada setiap pemanggilan. Biaya itu wajar untuk layanan internal dengan lalu lintas rendah tetapi menjadi pertimbangan pada volume tinggi, dan pada situasi itulah strategi modul C yang ditautkan langsung menjadi pilihan yang lebih sesuai. Keduanya berbagi perjanjian record yang sama, sehingga perpindahan dari satu strategi ke strategi lainnya tidak mengubah program COBOL sama sekali.
Fasad Python dengan subprocess#
Fasad Python bertugas membangun baris permintaan, mengeksekusi program COBOL, lalu mengubah baris respons menjadi JSON. Baris permintaan dibangun dengan format lebar tetap :010d dan :03d agar saldo dan lama selalu diisi nol di depan, sedangkan respons diurai dengan pemisah titik koma dan tanda sama dengan, kemudian bunga diubah menjadi bilangan sebelum dicetak. Apabila format respons layanan berubah, hanya fungsi penguraian pada berkas ini yang perlu disesuaikan.
import json
import subprocess
def panggil_bunga(kode, saldo, lama):
"""Panggil program COBOL dan terjemahkan baris keluarannya menjadi dict."""
permintaan = f"{kode}{saldo:010d}{lama:03d}\n"
hasil = subprocess.run(
["./fasad-bunga"],
input=permintaan,
capture_output=True,
text=True,
check=True,
)
kolom = dict(bagian.split("=", 1) for bagian in hasil.stdout.strip().split(";"))
return {"status": kolom["STATUS"], "kode": kolom["KODE"], "bunga": int(kolom["BUNGA"])}
if __name__ == "__main__":
print(json.dumps(panggil_bunga("AB123", 1500000, 12))){"status": "OK", "kode": "AB123", "bunga": 180000}Jalankan python3 fasad.py pada direktori yang sama dengan program yang sudah dikompilasi. Seluruh aturan bisnis tetap berada di program COBOL, sedangkan skrip hanya membangun format masukan, menerjemahkan format keluaran, dan menyesuaikan tipe datanya. Apabila kelak layanan ini perlu dibuka sebagai API HTTP, fungsi panggil_bunga cukup dipanggil dari penangan permintaan web, dan tanggung jawab fasadnya tidak berubah.
Kesalahan umum#
Baris permintaan tidak berukuran tepat 18 karakter, misalnya saldo ditulis tanpa nol di depan. Field pada record COBOL bergeser sehingga hasil perhitungan salah. Bangun barisnya dengan lebar tetap sebagaimana format
:010dpada fasad.Baris permintaan lebih pendek dari record sehingga sisa field terisi spasi. Field numerik yang berisi spasi bukan nilai yang sah secara COBOL, karena itu fasad perlu memvalidasi panjang dan isi permintaan sebelum memanggil program, dan pemeriksaan panjang baris menjadi validasi paling sederhana yang efektif.
Aturan bisnis menumpang pada fasad, misalnya rumus bunga ditulis ulang di Python. Dua tempat yang menyimpan rumus yang sama lama-kelamaan berbeda isi, karena itu fasad hanya menerjemahkan format dan setiap perhitungan tetap di program COBOL.
Respons diurai tanpa memeriksa STATUS. Apabila program kelak menambahkan status gagal, fasad diam-diam meneruskan hasil yang salah. Karena itu, nilai STATUS diperiksa sebelum respons dicetak dan menjadi dasar pemilihan kode status HTTP.
Ringkasan#
- Fasad menyediakan antarmuka modern tanpa mengubah logika warisan yang sudah teruji.
- Program COBOL berperilaku seperti layanan, yaitu satu baris permintaan dari standard input dan satu baris respons ke standard output.
- Fasad Python mengeksekusi program melalui subprocess dan menerjemahkan baris respons menjadi JSON dengan tipe data yang tepat.
- cobc membuka strategi kedua berupa modul C hasil terjemahan yang dapat dimuat langsung dari bahasa modern melalui FFI.
Referensi#
- subprocess — Python Software Foundation — dokumentasi subprocess.run beserta parameter input dan capture_output yang dipakai fasad.
- GnuCOBOL Manual — GnuCOBOL project — opsi -C untuk menghasilkan kode C dari program COBOL.