Pemilihan proyek

Menimbang layanan web, alat CLI, atau binding C sebagai bentuk proyek pertama.

Daftar isi

Proyek pertama dengan Crystal dapat mengambil salah satu dari tiga bentuk, yaitu alat command line yang sering disingkat CLI, layanan web, dan binding C. Topik ini membandingkan ketiganya dari sisi konsep yang dilatih, ketergantungan yang ditanggung, umpan balik yang diterima, dan batasan masing-masing. Sebagai contoh nyata, satu alat CLI bernama catatan dibangun dengan pustaka standar saja, mulai dari membaca argumen hingga menjadi binary hasil build. Dengan pembanding tersebut, keputusan memilih bentuk proyek dapat diambil dari kriteria yang terukur dan bukan dari selera semata.

Tiga bentuk proyek pertama#

Alat CLI adalah program yang menerima argumen melalui ARGV, mengerjakan tugasnya, lalu menampilkan keluaran teks di terminal. Bentuk ini melatih inti bahasa secara langsung, mulai dari percabangan, array, operasi berkas, hingga proses build menjadi satu berkas binary. Ketergantungannya paling kecil di antara ketiga bentuk karena pustaka standar sudah mencukupi, sehingga seluruh waktu belajar terpakai untuk bahasanya.

Layanan web menerima permintaan (request) HTTP dan mengembalikan respons (response), biasanya berupa HTML atau JSON. Pustaka standar menyediakan HTTP::Server, sedangkan framework Kemal yang dipasang sebagai shard, yaitu paket pihak ketiga, menyederhanakan routing dan pembacaan parameter. Bentuk ini melatih pemodelan endpoint, format data, dan alur permintaan-respons yang menjadi dasar aplikasi jaringan. Materinya dibahas lebih rinci pada modul Web, data, dan spec di jalur yang sama.

Kerangka layanan web paling sederhana terlihat seperti berikut. Program semacam ini berjalan terus menunggu permintaan dari browser, sehingga potongannya tidak dijalankan sebagai latihan. Tanda # tidak-dijalankan pada baris pertama menandai hal tersebut.

crystal Contoh: kerangka layanan web dengan HTTP::Server
# tidak-dijalankan
require "http/server"

server = HTTP::Server.new do |context|
  context.response.content_type = "text/plain"
  context.response.print "halo dari layanan web"
end

address = server.bind_tcp("127.0.0.1", 8080)
puts "server berjalan di #{address}"
server.listen

Binding C menghubungkan kode Crystal dengan pustaka yang ditulis dalam C melalui deklarasi lib dan fun. Bentuk ini melatih pertukaran struct dan pointer, sekaligus aturan antarmuka biner (ABI) yang menjadi kontrak antara dua bahasa. Ketergantungannya paling besar karena pustaka C turut dipersyaratkan, dan materinya dibahas pada modul Binding C. Bentuk inilah yang paling jarang dipilih sebagai proyek pertama, dan alasannya dibaca pada bagian perbandingan.

Perbandingan dan batasan#

Tabel berikut merangkum ketiga bentuk dari empat sisi yang menentukan pilihan.

AspekAlat CLILayanan webBinding C
Konsep inti yang dilatihARGV, percabangan, berkas, build binarypermintaan-respons, routing, JSONlib dan fun, pointer, struct, ABI
Ketergantunganpustaka standar sajapustaka standar atau shard Kemalpustaka C dan compiler C
Umpan balik pertamateks keluaran langsung di terminalrespons pada browser atau curlhasil pemanggilan fungsi C
Batasan utamamasukan dan keluaran terbatas pada teksbug dapat berada di sisi klien atau servererror memori sulit dilacak

Tabel di atas baru adil apabila kolom batasannya dibaca dengan saksama. Alat CLI tidak tepat apabila program harus menyediakan antarmuka grafis, diakses banyak pengguna sekaligus, atau dipanggil dari perangkat lain melalui jaringan, karena bentuk ini tidak menyediakan ketiganya secara bawaan. Layanan web tidak tepat sebagai proyek pertama apabila dasar bahasa belum mantap, karena framework menyembunyikan banyak mekanisme dan satu bug dapat berada di sisi klien maupun server. Binding C tidak tepat untuk proyek pertama tanpa pengalaman C, karena kesalahan pada pointer memunculkan segfault, yaitu kegagalan akses memori yang lokasinya tidak selalu ditunjukkan compiler.

Ketiga bentuk juga tidak saling mengunci arah jangka panjang. Logika yang ditulis untuk alat CLI dapat dipanggil ulang oleh layanan web karena keduanya ditulis dalam bahasa yang sama, sehingga pilihan awal lebih bersifat mengatur urutan belajar daripada menentukan bentuk akhir produk.

Studi kasus alat CLI catatan#

Berkas catatan.cr berikut adalah alat CLI lengkap yang hanya bergantung pada pustaka standar. Program membaca perintah dari argumen pertama, yaitu tambah atau daftar, lalu menyimpan catatannya sebagai JSON pada berkas /tmp/catatan-latihan.json. Fungsi muat dan simpan menangani pembacaan serta penulisan arsip, sedangkan case meneruskan alur sesuai perintah yang diterima.

crystal catatan.cr
# Alat CLI catatan: menyimpan dan menampilkan catatan singkat dalam berkas JSON.
require "json"

ARSIP = "/tmp/catatan-latihan.json"

def muat : Array(String)
  if File.exists?(ARSIP)
    Array(String).from_json(File.read(ARSIP))
  else
    [] of String
  end
end

def simpan(catatan : Array(String)) : Nil
  File.write(ARSIP, catatan.to_json)
end

perintah = ARGV[0]?
case perintah
when "tambah"
  teks = ARGV[1]?
  if teks.nil?
    puts "teks catatan belum diberikan"
    exit 1
  end
  daftar = muat
  daftar << teks
  simpan(daftar)
  puts "catatan tersimpan: #{teks}"
when "daftar"
  daftar = muat
  if daftar.empty?
    puts "belum ada catatan"
  else
    daftar.each_with_index do |teks, urut|
      puts "#{urut + 1}. #{teks}"
    end
  end
else
  puts "penggunaan: catatan tambah \"teks\" | catatan daftar"
  exit 1
end

Blok perintah berikut menambahkan dua catatan lalu menampilkan seluruh isinya. Arsip lama dibersihkan lebih dulu agar keluarannya selalu sama.

bash
# bersihkan arsip dari percobaan sebelumnya
rm -f /tmp/catatan-latihan.json
# perintah tambah menyimpan satu teks catatan
crystal run catatan.cr -- tambah "beli tinta"
crystal run catatan.cr -- tambah "kirim laporan mingguan"
# perintah daftar menampilkan seluruh catatan yang tersimpan
crystal run catatan.cr -- daftar
text Keluaran
catatan tersimpan: beli tinta
catatan tersimpan: kirim laporan mingguan
1. beli tinta
2. kirim laporan mingguan

Keluaran menunjukkan dua pemanggilan tambah masing-masing menyimpan satu teks, sedangkan daftar membaca arsip dan menampilkannya dengan nomor urut dari each_with_index. Dengan arsip yang dibersihkan di awal, perintah yang sama selalu menghasilkan keluaran yang sama. Sifat yang dapat diulang inilah yang membuat alat CLI nyaman digunakan sebagai wahana latihan.

Versi siap digunakan tidak perlu dikompilasi ulang pada setiap pemanggilan. Perintah crystal build menghasilkan satu berkas binary yang dipanggil langsung tanpa crystal run, dan binary inilah bentuk akhir yang dibagikan kepada pengguna alat. Blok perintah berikut juga membersihkan arsip dan binary lama agar keluarannya dapat diulang.

bash
# bersihkan arsip dan binary dari percobaan sebelumnya
rm -f /tmp/catatan-latihan.json catatan
# build menghasilkan satu berkas binary yang berdiri sendiri
crystal build catatan.cr -o catatan
# binary hasil build dipanggil langsung tanpa crystal run
./catatan tambah "ganti tinta printer"
./catatan daftar
text Keluaran
catatan tersimpan: ganti tinta printer
1. ganti tinta printer

Kesalahan umum#

Lupa pemisah -- pada crystal run. Tanpa pemisah ini, crystal membaca tambah sebagai berkas sumber berikutnya, berhenti dengan pesan error No such file or directory, dan program tidak pernah dijalankan. Pesan berkas tidak ditemukan muncul karena argumen program diperlakukan sebagai berkas sumber kedua, dan bukan karena arsip catatan yang hilang. Perbaikannya, sisipkan -- sebelum argumen program sehingga bentuk pemanggilannya menjadi crystal run catatan.cr -- tambah "beli tinta".

Menyamakan crystal run dengan program akhir. crystal run mengompilasi ke cache lalu menjalankan hasilnya seketika, sehingga nyaman untuk latihan tetapi tidak meninggalkan berkas yang dapat dibagikan. Pengguna alat yang sudah selesai dikembangkan juga tidak seharusnya memasang Crystal hanya untuk menjalankan satu program. Perbaikannya, gunakan crystal build untuk menghasilkan binary yang berdiri sendiri seperti pada studi kasus.

Menaruh arsip uji di direktori kerja tanpa kebiasaan pembersihan. Data dari percobaan sebelumnya tercampur dengan percobaan berikutnya, sehingga keluaran daftar berubah tanpa alasan yang terlihat. Kekacauan semacam ini sulit dilacak karena programnya sendiri berjalan sesuai perintah. Perbaikannya, tetapkan lokasi arsip pada satu konstanta seperti ARSIP di catatan.cr, lalu bersihkan arsip sebelum sesi percobaan baru dimulai.

Ringkasan#

  • Alat CLI melatih ARGV, percabangan, operasi berkas, dan build binary hanya dengan pustaka standar, sehingga menjadi bentuk proyek pertama yang paling ringan.
  • Layanan web melatih permintaan-respons dan JSON melalui HTTP::Server atau Kemal, dengan biaya pemahaman HTTP dan pelacakan bug di dua sisi.
  • Binding C melatih lib, fun, pointer, dan ABI, dengan risiko error memori yang paling sulit dilacak.
  • Bentuk proyek tidak mengunci arah produk, karena logika yang sama dapat dipanggil ulang oleh bentuk lain dalam bahasa yang sama.

Referensi#