Perangkat modern

Modul modern untuk pekerjaan sehari-hari: Path::Tiny untuk berkas, Try::Tiny untuk error, dan JSON::PP untuk data JSON.

Daftar isi

Pekerjaan sehari-hari dengan Perl banyak menyangkut tiga hal, yaitu membaca dan menulis berkas, menangani error, serta mengolah data yang dipertukarkan antar program. Topik ini memperkenalkan tiga modul yang menyingkat pekerjaan tersebut, yaitu Path::Tiny untuk operasi berkas, Try::Tiny untuk penanganan error, dan JSON::PP untuk data berformat JSON. JSON::PP termasuk modul inti, sedangkan Path::Tiny dan Try::Tiny dipasang dari CPAN apabila lingkungan kerja belum menyediakannya. Setiap contoh dijalankan utuh beserta keluaran aslinya.

Mengelola berkas dengan Path::Tiny#

Pola klasik pengelolaan berkas dengan open, pembacaan baris demi baris, lalu close memerlukan kode yang panjang dan rawan lupa menutup berkasnya. Modul Path::Tiny mengemas seluruh operasi itu ke dalam objek path yang dibuat dengan fungsi path, sehingga satu metode menyelesaikan satu pekerjaan. Metode spew menulis seluruh isi ke berkas, slurp membaca seluruh isinya, append menambahkan teks di akhir berkas, lines mengembalikan daftar baris tanpa karakter baris baru, dan remove menghapus berkasnya.

perl catatan.pl
use strict;
use warnings;
use Path::Tiny;

# objek path dan penulisan berkas
my $catatan = path('catatan.txt');
$catatan->spew("Sensor suhu pagi: 24 derajat\nSensor suhu siang: 27 derajat\n");

# membaca kembali seluruh isi berkas
print "Isi awal:\n", $catatan->slurp;

# menambah satu baris di akhir berkas
$catatan->append("Sensor suhu sore: 26 derajat\n");

print "Isi akhir:\n", $catatan->slurp;

# menghitung baris tanpa menyalin isi berkas secara manual
my $jumlah = 0;
for my $baris ($catatan->lines) {
    $jumlah++;
}
print "Jumlah baris: $jumlah\n";

# menghapus berkas agar contoh dapat diulang dari awal
$catatan->remove;
print "Berkas catatan.txt sudah dihapus\n";
text Keluaran
Isi awal:
Sensor suhu pagi: 24 derajat
Sensor suhu siang: 27 derajat
Isi akhir:
Sensor suhu pagi: 24 derajat
Sensor suhu siang: 27 derajat
Sensor suhu sore: 26 derajat
Jumlah baris: 3
Berkas catatan.txt sudah dihapus

Skrip di atas membuat berkas catatan.txt di direktori kerjanya, mengubah isinya dua kali, membacanya kembali, lalu menghapusnya agar contoh dapat diulang dari keadaan bersih. Setiap panggilan metode mewakili satu langkah kerja yang bila ditulis manual memerlukan open, print, dan close masing-masing. Metode lines mengembalikan baris yang sudah dihilangkan karakter baris barunya, sehingga penghitungan jumlah baris tidak memerlukan chomp.

Objek path juga berperilaku seperti string ketika berada pada konteks teks, sehingga pencetakan print "Berkas: $catatan\n" menampilkan jalurnya tanpa konversi manual. Pemeriksaan keberadaan berkas dilakukan dengan metode exists, is_file, dan is_dir, sehingga percabangan sebelum membaca atau menulis berkas tidak memerlukan operator uji -e lagi. Ketiganya mengembalikan nilai boolean sehingga langsung digunakan sebagai syarat if.

Menangani error dengan Try::Tiny#

Pernyataan die menghentikan program dengan memunculkan error, dan mekanisme klasik penangkapannya adalah blok eval dengan pemeriksaan variabel $@. Pendekatan itu berfungsi, tetapi $@ mudah tertimpa oleh operasi lain sehingga penanganannya harus hati-hati. Modul Try::Tiny menyediakan blok try dan catch yang lebih terbaca, dan di dalam blok catch pesan error tersedia pada variabel $_.

perl bagi-nol.pl
use strict;
use warnings;
use Try::Tiny;

# subrutin yang memunculkan error pembagian nol
sub bagi {
    my ($pembilang, $penyebut) = @_;
    return $pembilang / $penyebut;
}

for my $pasangan ([10, 2], [10, 0]) {
    my ($pembilang, $penyebut) = @$pasangan;

    try {
        my $hasil = bagi($pembilang, $penyebut);
        print "$pembilang / $penyebut = $hasil\n";
    }
    catch {
        chomp(my $pesan = $_);
        $pesan =~ s/\s+at .*? line \d+\.$//;    # lokasi berkas tidak perlu ditampilkan
        print "Error tertangkap: $pesan\n";
    };
}
text Keluaran
10 / 2 = 5
Error tertangkap: Illegal division by zero

Pembagian 10 / 2 berjalan normal dan dicetak, sedangkan pembagian 10 / 0 memunculkan error Illegal division by zero yang dibangkitkan Perl sendiri. Blok catch menangkap pesan tersebut, membuang bagian lokasi berkas dan barisnya agar tampilannya ringkas, lalu program melanjutkan perulangan ke pasangan berikutnya. Tanpa blok try, error yang sama akan menghentikan program tepat pada perulangan kedua dan sisa pekerjaannya tidak pernah dijalankan.

Blok try mengembalikan nilai dari blok yang menampung eksekusi utamanya, yaitu isi blok try ketika berhasil dan isi blok catch ketika terjadi error, sehingga satu penetapan variabel dapat menampung kedua kemungkinan itu. Modul ini juga menyediakan blok finally yang dijalankan setelah try maupun catch, berguna untuk pekerjaan pembersihan yang wajib terjadi baik saat berhasil maupun saat gagal. Blok ini bersifat opsional dan ditempatkan setelah catch, atau setelah try apabila catch tidak digunakan.

Mengolah data JSON dengan JSON::PP#

JSON adalah format teks yang lazim digunakan untuk pertukaran data antar program, misalnya antara skrip dan layanan web. Modul JSON::PP mengubah struktur data Perl menjadi teks JSON dan sebaliknya, dan karena termasuk modul inti, modul ini selalu tersedia tanpa penginstalan. Metode encode menerima referensi struktur data dan menghasilkan teks JSON, sedangkan decode melakukan kebalikannya dan mengembalikan referensi tersebut.

perl produk-json.pl
use strict;
use warnings;
use JSON::PP;

my %produk = (
    kode => 'A-102',
    nama => 'Buku tulis',
    stok => 24,
);

# pengubah JSON dengan kunci yang diurutkan agar keluaran stabil
my $pengolah = JSON::PP->new->canonical(1);

# mengubah hash menjadi teks JSON
my $teks = $pengolah->encode(\%produk);
print "JSON   : $teks\n";

# mengubah teks JSON menjadi struktur data Perl
my $data = $pengolah->decode('{"kode":"A-102","nama":"Buku tulis","stok":24}');
print "Nama   : $data->{nama}\n";
print "Stok   : $data->{stok}\n";
text Keluaran
JSON   : {"kode":"A-102","nama":"Buku tulis","stok":24}
Nama   : Buku tulis
Stok   : 24

Metode encode menghasilkan teks JSON dengan string dalam tanda kutip dan bilangan tanpa kutip, persis seperti formatnya. Pengaturan canonical(1) mengurutkan kunci sebelum pencetakan, dan pengaturan ini penting karena hash tidak memiliki urutan tertentu, sehingga tanpa pengurutan teks JSON yang dihasilkan dapat berbeda urutannya antar eksekusi. Hasil decode adalah referensi hash biasa, sehingga aksesnya menggunakan panah, yaitu $data->{nama}, dan seluruh teknik referensi yang sudah dipelajari tetap berlaku.

Selain antarmuka objek, modul ini menyediakan fungsi encode_json dan decode_json yang langsung digunakan tanpa membuat objek. Fungsi encode_json menghasilkan byte UTF-8, sedangkan decode_json mengharapkan byte UTF-8 sebagai masukannya, sehingga antarmuka objek lebih luwes ketika teksnya perlu diperlakukan sebagai karakter. Pada data yang seluruh isinya ASCII seperti contoh di atas, keduanya memberikan hasil yang sama.

Kesalahan umum#

Tiga kekeliruan berikut paling sering muncul ketika modul-modul di atas baru digunakan.

  • Modul CPAN tidak ditemukan. Pesan error Can't locate Path::Tiny in @INC muncul ketika direktori local lib tempat modul terpasang tidak terdaftar pada @INC. Pastikan lingkungan local libnya diatur, misalnya melalui variabel PERL5LIB.
  • Menggunakan $@ di dalam blok catch. Try::Tiny menyerahkan pesan error melalui $_, dan $@ di tempat itu tidak dijamin berisi pesan yang benar. Ganti $@ menjadi $_.
  • Membiarkan error tidak tertangkap. Error seperti pembagian nol yang tidak dibungkus try menghentikan program pada barisnya, sehingga sisa pekerjaan yang sudah disiapkan tidak pernah dieksekusi.

Seluruh pesan pada daftar di atas menunjuk penyebabnya secara langsung, sehingga perbaikannya berupa satu perubahan kecil. Daftar direktori @INC dapat dilihat dengan menambahkan print "$_\n" for @INC; pada awal skrip, sehingga direktori yang tertinggal langsung terlihat.

Ringkasan#

  • Path::Tiny mengemas operasi berkas dalam objek path dengan metode seperti spew, slurp, append, lines, dan remove.
  • Try::Tiny membungkus kode berisiko dalam blok try dan menyediakan pesan error pada $_ di dalam blok catch.
  • JSON::PP mengubah struktur data Perl menjadi teks JSON dan sebaliknya, dengan canonical agar urutan kuncinya stabil.
  • Ketiganya menyingkat pola kerja yang bila ditulis manual memerlukan kode lebih panjang dan lebih rawan keliru.

Referensi#