COPY dan Copybook

Berbagi definisi record lintas program dan sistem melalui anggota copybook.

Daftar isi

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.

cobol Penempatan COPY pada FILE SECTION
       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.

cobol pelanggan.cpy
      *> 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.

cobol tulis-pelanggan.cbl
       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.
text Keluaran
Tiga record pelanggan ditulis ke pelanggan.dat

Program 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.

cobol baca-pelanggan.cbl
       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.
text Keluaran
KODE A1001  NAMA Ali              SALDO  150000.50
KODE B1002  NAMA Budi             SALDO 2750000.00
KODE C1003  NAMA Citra            SALDO   98000.25

Isi 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.

text Isi berkas pelanggan.dat
A1001Ali            015000050
B1002Budi           275000000
C1003Citra          009800025

Kompilasi kedua program dengan perintah berikut.

bash
# kompilasi program penulis berkas
cobc -x tulis-pelanggan.cbl
# kompilasi program pembaca berkas
cobc -x baca-pelanggan.cbl

Jalankan ./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.

cobol Penambahan field pada copybook
           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#

  1. 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.

  2. Nama copybook tanpa tanda kutip seperti COPY PELANGGAN. membuat GnuCOBOL mencari berkas bernama PELANGGAN tanpa ekstensi dan berakhir dengan error No such file or directory. Gunakan bentuk bertanda kutip dengan ekstensi, misalnya COPY "pelanggan.cpy".

  3. 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.

  4. 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.

  5. 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#