Single-File Tool Architecture
On this page
Single-File Tool Architecture adalah bentuk yang saya berikan pada tool kecil: satu file yang mengerjakan satu tugas, dengan seksi-seksi yang urutannya selalu sama dan kontrak tetap tentang cara menjalankannya serta cara ia melaporkan hasil. Ini kesepakatan saya sendiri, bukan rancangan dari buku. Bentuknya lahir dari menulis banyak tool kecil yang memeriksa server, membuat deployment stack, dan mengonversi file.
Ini salah satu arsitektur yang saya pakai, dan ia mengisi ujung terkecil pekerjaan saya. Untuk service yang memegang aturan bisnis sungguhan dan hidup bertahun-tahun, saya memakai yang lebih berat; untuk tool yang mengerjakan satu hal lalu selesai, bentuk ini sudah cukup.
Sekilas
| Asal | Kesepakatan saya sendiri, terbentuk dari banyak tool command-line kecil |
|---|---|
| Saya pakai untuk | Tool dengan satu tugas jelas yang dijalankan orang atau script lain: pemeriksa kesiapan, generator stack, konverter |
| Tak saya pakai untuk | Service berumur panjang dengan banyak use case |
| Bahasa | Python, Bash |
Gagasannya secara singkat
A. Satu file, satu tugas
Seluruh tool tinggal di satu script. Di sebelahnya cuma ada yang dibacanya: daftar dependency, contoh file konfigurasi, dan untuk generator, folder berisi template. Tak ada package, tak ada impor antarfile dalam satu tool, dan tak ada yang perlu dipasang selain dependency-nya.
B. Dibaca dari atas ke bawah
File-nya dibagi menjadi seksi yang ditandai komentar banner, dan urutan seksinya selalu sama: konfigurasi, helper, reporter, langkah-langkah yang mengerjakan tugasnya, ringkasan, lalu entry point. Membaca file dari atas ke bawah sama dengan mengikuti perjalanan satu kali jalan.
C. Kontrak di bagian atas
Baris-baris pertama file menyatakan apa yang dikerjakan tool itu dan apa arti exit code-nya. Exit code adalah angka yang dikembalikan program saat berakhir, dan dari situlah script lain membedakan sukses dari gagal tanpa membaca output.
D. Tiga pintu masuk
Tool menerima input lewat paling banyak tiga cara: argumen command-line untuk opsi, file konfigurasi untuk semua yang menggambarkan satu target, dan prompt interaktif untuk nilai yang berubah tiap kali jalan. Tiap jenis nilai punya satu pintu masuk, jadi satu kali jalan mudah diulang.
Kenapa saya memilihnya
Lapisan membuat hal kecil jadi rumit. Tool dengan satu tugas tak butuh domain, use case, dan adapter. Memecah beberapa ratus baris ke beberapa folder akan membuat strukturnya lebih besar daripada programnya, dan saya akan lebih banyak bernavigasi ketimbang membaca.
Satu file mudah disalin dan dipindah. Saya bisa membawa tool ke mesin lain sebagai satu script, konfigurasinya, dan daftar dependency-nya. Tak ada package yang harus di-build atau diterbitkan dulu supaya ia bisa jalan di tempat lain.
Urutan yang sama di tiap tool memberi tahu saya letak sesuatu. Karena tiap tool menjaga urutan seksinya tetap sama, saya tahu di mana konfigurasi divalidasi atau di mana ringkasan dicetak pada tool yang berbulan-bulan tak saya buka, sebelum membaca satu baris pun.
Script lain bisa memanggilnya. Exit code yang tetap, dan input yang bisa datang dari argumen atau environment, membuat tool yang hari ini saya jalankan dengan tangan bisa dijalankan scheduler atau pipeline besok tanpa diubah.
Kesepakatan saya
Tool saya yang menyatakan mengikuti arsitektur ini punya bentuk seperti berikut. Di Python:
#!/usr/bin/env python3
"""What the tool checks or does.
Exit code:
0 - every check passed
1 - a check failed
2 - the configuration is missing or invalid
130 - cancelled by the user
"""
# --- Config ------------------------------------------------------------
# --- Helpers -----------------------------------------------------------
# --- Reporter ----------------------------------------------------------
# --- Steps -------------------------------------------------------------
# --- Summary -----------------------------------------------------------
# --- Entrypoint --------------------------------------------------------| Seksi | Isinya |
|---|---|
| Config | memuat file konfigurasi dan memvalidasi tiap field dengan ketat, sebelum koneksi apa pun dibuka |
| Helpers | fungsi kecil yang dipakai bersama oleh langkah-langkahnya, misalnya mengubah error menjadi satu baris yang mudah dibaca |
| Reporter | mencetak satu baris per check, lolos atau gagal, dan mengumpulkan fakta untuk ringkasan |
| Steps | pekerjaan yang sesungguhnya, satu seksi per bagian tugas |
| Summary | jumlah check yang lolos dan status akhir |
| Entrypoint | mengurai argumen, menjalankan langkah-langkahnya, dan memilih exit code |
Tiap jenis input punya pintu masuknya sendiri:
| Input | Dipakai untuk | Contoh |
|---|---|---|
| argumen command-line | opsi yang mengubah cara tool berjalan | --timeout 30 |
| file konfigurasi | semua yang menggambarkan satu target, satu file per target | --config server-a.json |
| prompt interaktif | nilai yang berubah tiap kali jalan | alamat tujuan pesan uji |
Dependency pihak ketiga yang belum terpasang juga mengakhiri jalan dengan exit code 2 dan pesan tentang cara memasangnya. Di sebelah tiap tool ada contoh file konfigurasi berisi placeholder, dan file konfigurasi sungguhan, yang memuat kredensial, tak pernah di-commit.
Varian Bash dipakai untuk generator — script yang membuat folder siap pakai dari template. Header-nya mendaftar environment variable yang dihormatinya, dan tiap input dibaca dengan cara yang sama: dari environment bila sudah di-set, kalau belum, lewat pertanyaan dengan nilai default.
# ask VAR "Prompt" "default": pakai environment variable bila ada, kalau tidak, tanyakan
Satu aturan itu membuat generator yang sama bisa jalan interaktif untuk saya dan tanpa penunggu di automation, dengan satu variable tambahan untuk melewati semua konfirmasi. Template-nya tinggal di folder di sebelah script, jadi generator membawa semua yang dibutuhkannya.
Cara saya memeriksa tool
Inilah pertanyaan yang saya ajukan kepada tool yang sudah selesai, diambil dari kesepakatan di atas:
| Bidang | Pertanyaan yang saya ajukan | Sumber |
|---|---|---|
| Kontrak | Apakah baris-baris pertama menyatakan apa yang dikerjakan tool dan arti tiap exit code? | kontrak di bagian atas |
| Urutan | Apakah seksinya berada dalam urutan tetap, masing-masing bertanda banner? | urutan seksi |
| Konfigurasi | Apakah tiap field divalidasi sebelum apa pun disambungkan, dengan exit code sendiri bila gagal? | seksi Config |
| Input | Apakah tiap jenis nilai punya tepat satu pintu masuk? | tiga pintu masuk |
| Laporan | Apakah tiap check mencetak satu baris, dan apakah ringkasannya menghitungnya? | Reporter dan Summary |
| Rahasia | Apakah ada contoh konfigurasi berisi placeholder, dan apakah yang sungguhan dijauhkan dari repository? | file konfigurasi |
| Automation | Bisakah tool jalan tanpa orang, lewat argumen, konfigurasi, atau environment variable? | varian Bash dan exit code |
Di mana saya tidak memakainya
Ketika tool tumbuh menjadi service
Tool yang mulai memegang beberapa tugas, melayani request, atau perlu hidup dan dirawat bertahun-tahun sudah terlalu besar untuk satu file. Pada titik itu lapisan yang tadinya membebani justru sepadan dengan ongkosnya, dan saya memindahkannya ke Clean Architecture, tempat aturannya dipisahkan dari tool di sekelilingnya.
Rujukan
Arsitektur ini tak punya buku di belakangnya; ini kesepakatan yang saya bangun dari tool-tool saya sendiri. Dua bagiannya mengikuti kesepakatan lama program command-line Unix: exit code 0 untuk sukses dan bukan nol untuk gagal, serta 130 untuk jalan yang disela Ctrl+C, yang dilaporkan shell sebagai 128 ditambah nomor signal interupsinya.
Istilah
- Exit code
- Angka yang dikembalikan program saat berakhir. Script memakainya untuk membedakan sukses dari berbagai jenis kegagalan tanpa membaca output.
- File konfigurasi
- File, di sini JSON, yang menggambarkan satu target yang dikerjakan tool, misalnya satu server beserta kredensialnya.
- Prompt interaktif
- Pertanyaan yang diajukan tool di terminal selama ia berjalan, untuk nilai yang berubah tiap kali jalan.
- Environment variable
- Nilai bernama yang di-set di luar program dan bisa dibacanya, sehingga script bisa memberi jawaban tanpa diketik.
- Generator
- Script yang membuat folder siap pakai, misalnya deployment stack, dari template dan beberapa jawaban.