Topik ini membahas pernyataan COPY yang menempelkan isi sebuah berkas ke dalam kode sumber pada waktu kompilasi, beserta copybook sebagai tempat definisi record yang dipakai bersama. Satu copybook ditulis sekali, lalu digunakan oleh dua program sekaligus, yaitu program penulis berkas dan program pembaca berkas yang sama, sehingga kedua program mengenal layout record dari satu sumber definisi. Apabila layout berubah, perbaikan cukup dilakukan pada satu berkas copybook, kemudian seluruh program penggunanya dikompilasi ulang.
Cara kerja COPY#
COPY adalah pernyataan yang menyuruh compiler menempelkan isi sebuah berkas teks ke posisi pernyataan itu pada waktu kompilasi, sebelum pemeriksaan sintaks dan terjemahan dimulai. Isi berkas yang ditempel menjadi bagian dari program seolah-olah diketik langsung pada posisi tersebut, sedangkan berkasnya sendiri tidak pernah ikut ke dalam program yang sudah jadi. Tempat penyimpanan berkas salinan semacam ini disebut copybook. Pada mainframe IBM, copybook disimpan sebagai anggota sebuah partitioned dataset yang dapat dibuka oleh banyak program, sedangkan GnuCOBOL memperlakukannya sebagai berkas biasa pada sistem berkas.
GnuCOBOL mencari berkas salinan pada direktori berkas sumber yang sedang dikompilasi, kemudian pada direktori yang tercantum pada variabel lingkungan COB_COPY_DIR. Bentuk yang paling mudah diandalkan adalah literal bertanda kutip yang menyebut nama berkas beserta ekstensinya, sebagaimana pada COPY "pelanggan.cpy". Isi copybook lazimnya berupa layout record level 01 atau fragmen nomor level, dan penempatannya mengikuti jenis isinya, yaitu FILE SECTION untuk record berkas atau WORKING-STORAGE SECTION untuk record kerja.
FD BERKAS-PELANGGAN.
COPY "pelanggan.cpy".Pada potongan di atas, COPY digantikan oleh isi pelanggan.cpy, sehingga record REK-PELANGGAN menjadi satu-satunya record milik FD BERKAS-PELANGGAN. Apabila isi copybook mengandung kesalahan, compiler melaporkan pesan error dengan menyebut berkas copybook dan nomor barisnya, bukan berkas program, sehingga sumber masalah mudah ditemukan.
Layout record dalam pelanggan.cpy#
Copybook pada topik ini mendefinisikan record pelanggan dengan tiga field, yaitu kode sepanjang 5 karakter, nama sepanjang 15 karakter, dan saldo sepanjang 9 digit dengan dua desimal tersirat. Panjang ketiganya berjumlah 29 karakter untuk setiap baris data. Penamaan field diberi awalan PEL sesuai nama recordnya, sehingga apabila program memuat beberapa record sekaligus, tidak ada dua field yang bertabrakan namanya.
*> Definisi record pelanggan yang dipakai bersama.
01 REK-PELANGGAN.
05 PEL-KODE PIC X(05).
05 PEL-NAMA PIC X(15).
05 PEL-SALDO PIC 9(07)V99.Sifat panjang tetap menjadi dasar dari pemakaian bersama ini. Penulis berkas menempatkan setiap nilai pada posisi yang persis, dan pembaca mengurai posisi yang sama berdasarkan definisi yang sama, sehingga tidak perlu pembatas maupun penanda panjang pada datanya.
Klausa PIC 9(07)V99 memerlukan penjelasan singkat karena kesalahpahaman mengenai desimal sering muncul pada tahap ini. Huruf V menandai posisi desimal yang tersirat, artinya titik desimal tidak disimpan dalam data, sehingga data hanya memuat sembilan digit tanpa titik dan penempatan desimal baru diterapkan pada saat aritmetika. Nilai 150000.50 dengan demikian tersimpan sebagai 015000050, dan nilai tersebut kembali menjadi 150000.50 pada setiap program yang memuat copybook yang sama karena penafsiran desimalnya juga sama.
Dua program, satu definisi#
Program pertama menulis tiga record pelanggan ke pelanggan.dat. Program membuka berkas dengan mode OUTPUT, mengisi ketiga field record, lalu mengeksekusi WRITE untuk setiap record. Seluruh definisi datanya berasal dari COPY, dan tidak ada satu baris pun definisi field yang ditulis secara manual pada program ini.
IDENTIFICATION DIVISION.
PROGRAM-ID. TULISPEL.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT BERKAS-PELANGGAN ASSIGN TO "pelanggan.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD BERKAS-PELANGGAN.
COPY "pelanggan.cpy".
PROCEDURE DIVISION.
OPEN OUTPUT BERKAS-PELANGGAN
MOVE "A1001" TO PEL-KODE
MOVE "Ali" TO PEL-NAMA
MOVE 150000.50 TO PEL-SALDO
WRITE REK-PELANGGAN
MOVE "B1002" TO PEL-KODE
MOVE "Budi" TO PEL-NAMA
MOVE 2750000 TO PEL-SALDO
WRITE REK-PELANGGAN
MOVE "C1003" TO PEL-KODE
MOVE "Citra" TO PEL-NAMA
MOVE 98000.25 TO PEL-SALDO
WRITE REK-PELANGGAN
CLOSE BERKAS-PELANGGAN
DISPLAY "Tiga record pelanggan ditulis ke pelanggan.dat"
STOP RUN.Tiga record pelanggan ditulis ke pelanggan.datProgram kedua membaca berkas yang sama dengan memuat copybook yang sama pula. READ dijalankan sampai kondisi AT END, dan saldo ditampilkan melalui field SALDO-TAMPIL yang telah diformat agar titik desimalnya terlihat.
IDENTIFICATION DIVISION.
PROGRAM-ID. BACASPEL.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT BERKAS-PELANGGAN ASSIGN TO "pelanggan.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD BERKAS-PELANGGAN.
COPY "pelanggan.cpy".
WORKING-STORAGE SECTION.
01 TANDA-SELESAI PIC X VALUE "N".
88 SELESAI VALUE "Y".
01 SALDO-TAMPIL PIC ZZZZZZ9.99.
PROCEDURE DIVISION.
OPEN INPUT BERKAS-PELANGGAN
PERFORM UNTIL SELESAI
READ BERKAS-PELANGGAN
AT END
MOVE "Y" TO TANDA-SELESAI
NOT AT END
MOVE PEL-SALDO TO SALDO-TAMPIL
DISPLAY "KODE " PEL-KODE
" NAMA " PEL-NAMA
" SALDO " SALDO-TAMPIL
END-READ
END-PERFORM
CLOSE BERKAS-PELANGGAN
STOP RUN.KODE A1001 NAMA Ali SALDO 150000.50
KODE B1002 NAMA Budi SALDO 2750000.00
KODE C1003 NAMA Citra SALDO 98000.25Isi mentah pelanggan.dat memperlihatkan sifat panjang tetap tersebut. Nama terisi spasi hingga tepat 15 karakter dan saldo tersimpan sebagai 9 digit tanpa titik, sehingga setiap baris berukuran 29 karakter persis dan program pembaca cukup mengandalkan posisi.
A1001Ali 015000050
B1002Budi 275000000
C1003Citra 009800025Kompilasi kedua program dengan perintah berikut.
# kompilasi program penulis berkas
cobc -x tulis-pelanggan.cbl
# kompilasi program pembaca berkas
cobc -x baca-pelanggan.cblJalankan ./tulis-pelanggan lebih dahulu agar pelanggan.dat terbentuk, kemudian jalankan ./baca-pelanggan. Kedua program itu dapat ditulis oleh tim yang berbeda pada waktu yang berbeda, karena satu-satunya perjanjian yang dibutuhkan adalah berkas copybook yang sama. Pola inilah yang dipakai pada sistem mainframe, yaitu copybook menjadi kontrak data antara program penulis, program pembaca, dan langkah-langkah pemrosesan batch yang menggunakan berkas yang sama.
Pembaruan layout dari satu tempat#
Perubahan layout dilakukan pada copybook, bukan pada program-programnya. Contohnya, penambahan field kota dilakukan dengan satu baris berikut, kemudian kedua program dikompilasi ulang tanpa perubahan apa pun pada kode prosedurnya.
05 PEL-SALDO PIC 9(07)V99.
05 PEL-KOTA PIC X(10).Setelah kompilasi ulang, record pada kedua program berukuran 39 karakter dan field PEL-KOTA dapat diisi oleh program penulis serta dibaca oleh program pembaca. Penambahan di bagian akhir record merupakan perubahan yang paling aman karena posisi field yang sudah ada tidak bergeser. Namun, record lama pada berkas data masih berukuran 29 karakter. Isinya perlu dimigrasikan atau ditulis ulang dengan layout baru lebih dahulu, karena program pembaca akan menafsirkan posisi byte lama menurut layout baru sehingga nilainya bergeser.
Langkah konversi dalam praktiknya berupa program kecil yang membaca record lama dan menulis record baru dengan copybook masing-masing, sehingga kedua definisi hidup berdampingan selama masa migrasi. Itulah sebabnya perubahan copybook pada sistem nyata biasanya disertai rencana migrasi data dan kompilasi ulang seluruh program penggunanya.
Kesalahan umum#
COPY yang berisi layout data ditempatkan pada divisi PROCEDURE. Compiler menolaknya dengan pesan error sintaks karena pernyataan level 01 bukan pernyataan prosedur. Tempatkan COPY pada FILE SECTION setelah FD atau pada WORKING-STORAGE SECTION.
Nama copybook tanpa tanda kutip seperti
COPY PELANGGAN.membuat GnuCOBOL mencari berkas bernama PELANGGAN tanpa ekstensi dan berakhir dengan errorNo such file or directory. Gunakan bentuk bertanda kutip dengan ekstensi, misalnyaCOPY "pelanggan.cpy".Copybook diperbarui tetapi program tidak dikompilasi ulang. Program lama tetap membawa layout lama, dan masalah baru muncul pada data yang ditulis oleh program baru tetapi dibaca oleh program lama. Kompilasi ulang seluruh program pengguna setiap kali copybook berubah.
Definisi record ditulis secara manual pada satu program padahal copybook untuk definisi tersebut sudah ada. Dua definisi yang berdiri sendiri lama-kelamaan menyimpang, karena itu satu copybook digunakan oleh semua program yang menyentuh data tersebut.
Baris pada copybook melewati kolom 72. cobc memotong bagian yang melewati batas itu tanpa pesan error, sehingga definisi field dapat terpotong tanpa diketahui. Gunakan editor yang menampilkan nomor kolom agar setiap baris copybook terlihat masih berada dalam batas format tetap.
Ringkasan#
- COPY menempelkan isi berkas pada waktu kompilasi, sehingga copybook menjadi satu-satunya tempat definisi record yang dipakai bersama.
- GnuCOBOL mencari berkas copybook pada direktori berkas sumber dan pada direktori COB_COPY_DIR.
- Dua program yang menulis dan membaca berkas yang sama memperoleh layout identik selama keduanya memuat copybook yang sama.
- Perubahan layout dilakukan pada copybook, lalu diikuti kompilasi ulang seluruh program penggunanya dan migrasi data lama bila diperlukan.
Referensi#
- GnuCOBOL Manual — GnuCOBOL project — aturan pernyataan COPY dan pencarian berkas salinan pada GnuCOBOL.
- IBM Enterprise COBOL for z/OS documentation — IBM — dokumentasi pernyataan COPY dan copybook pada lingkungan mainframe IBM.