2 poin oleh GN⁺ 2024-02-07 | 1 komentar | Bagikan ke WhatsApp
  • Panduan ini merupakan pedoman desain open-source untuk membuat CLI yang nyaman digunakan manusia sekaligus tangguh untuk otomatisasi, dengan memperbarui prinsip UNIX tradisional secara modern
  • CLI yang baik harus beroperasi dengan mengutamakan manusia, tetapi tetap mematuhi konvensi seperti stdout/stderr, kode keluar, pipe, dan JSON agar dapat dikombinasikan secara alami dengan program lain
  • Bantuan, dokumentasi, pesan kesalahan, dan output harus membantu pengguna mengetahui tindakan berikutnya; --help, contoh, saran, indikator progres, dan penjelasan status berperan penting
  • Argumen, flag, interaksi, konfigurasi, dan variabel lingkungan harus mempertimbangkan penggunaan di skrip maupun terminal; untuk nilai rahasia, lebih aman untuk tidak menerimanya langsung lewat flag atau variabel lingkungan
  • Nama CLI, distribusi, hingga pengumpulan analitik tidak boleh merusak rasa kendali pengguna dan kompatibilitas jangka panjang; bahkan saat harus melanggar konvensi, tujuannya harus jelas

Filosofi dasar desain CLI

  • Panduan ini adalah dokumen open-source yang menyediakan prinsip desain dan panduan konkret untuk program baris perintah modern berdasarkan prinsip UNIX tradisional
  • Dahulu, baris perintah lebih mirip REPL di atas platform scripting, sebuah lingkungan mengutamakan mesin; tetapi CLI masa kini adalah UI berbasis teks untuk mengakses berbagai alat, sistem, dan platform, sehingga lebih kuat sifatnya sebagai alat yang mengutamakan manusia
  • Baris perintah memiliki keterbatasan lama dan kebiasaan yang unik, tetapi tersedia di hampir semua laptop, mendukung penggunaan interaktif maupun otomatisasi, dan berubah lebih lambat dibanding komponen sistem lainnya
  • Panduan ini tidak membahas program terminal layar penuh seperti emacs atau vim, dan tidak bergantung pada bahasa pemrograman atau toolchain tertentu

CLI yang mengutamakan manusia sekaligus dapat dikombinasikan

  • Jika CLI terutama merupakan alat yang digunakan manusia, maka manusia harus dipertimbangkan terlebih dahulu
    • Banyak program CLI ditujukan untuk pengguna manusia, tetapi masih mempertahankan desain interaksi lama yang berpusat pada mesin
  • Filosofi UNIX, yaitu program kecil yang bekerja bersama melalui antarmuka yang bersih, tetap penting
    • Konvensi seperti standard input, output, error, sinyal, dan kode keluar memungkinkan kombinasi antarprogram
    • Teks biasa berbasis baris mudah diteruskan melalui pipe, dan JSON berguna saat data yang lebih terstruktur diperlukan
  • Konsistensi adalah kunci yang mengubah biaya belajar CLI menjadi efisiensi jangka panjang
    • Dengan mengikuti pola yang sudah ada, pengguna dapat lebih mudah menebak perintah dan opsi
    • Jika konvensi merusak kegunaan, konvensi boleh dilanggar secara hati-hati
  • CLI yang baik tidak terlalu diam atau menghasilkan output terlalu banyak, dan harus memungkinkan pengguna memperoleh informasi sesuai kebutuhannya
  • CLI sering dianggap kurang mudah ditemukan dibanding GUI, tetapi kemampuan belajar dapat ditingkatkan dengan bantuan yang komprehensif, contoh, saran perintah berikutnya, dan panduan tindakan saat terjadi kesalahan

Interaksi dialogis dan ketangguhan

  • Penggunaan baris perintah lebih mirip dialog yang terdiri dari beberapa percobaan dan perbaikan daripada satu kali eksekusi
    • Untuk input yang salah, saran perbaikan dapat diberikan jika memungkinkan
    • Status antara dari pekerjaan bertahap dapat ditampilkan dengan jelas
    • Konfirmasi dapat diminta sebelum operasi berisiko
  • CLI harus benar-benar tangguh, sekaligus membuat pengguna merasa bahwa CLI itu tangguh
    • Input yang tidak terduga harus ditangani dengan anggun
    • Jika memungkinkan, operasi harus idempoten
    • Stack trace yang tampak menakutkan tidak boleh ditampilkan sebagai output default
  • Empati yang membuat pengguna merasa perangkat lunak berpihak pada mereka itu penting
    • Intinya bukan memakai emoji atau membuatnya seperti gim, melainkan merancang dengan cermat agar pengguna berhasil
  • Ekosistem terminal memang penuh inkonsistensi dan kebingungan, tetapi berkat batasan yang rendah, penemuan baru dapat terjadi
    • Ikuti pola yang sudah ada, tetapi standar yang merusak produktivitas atau kepuasan pengguna dapat ditinggalkan secara sengaja

Aturan dasar yang wajib diikuti

  • Jika memungkinkan, gunakan library parsing argumen baris perintah
  • Saat berhasil, kode keluar harus 0; saat gagal, harus mengembalikan nilai selain 0
    • Skrip menentukan keberhasilan atau kegagalan program melalui kode keluar
  • Output utama perintah harus dikirim ke stdout
    • Output yang dapat dibaca mesin pun pada dasarnya harus masuk ke stdout agar pipe bekerja dengan benar
  • Pesan yang ditampilkan kepada pengguna, seperti pesan log dan error, harus dikirim ke stderr
    • Saat dihubungkan dengan pipe, pesan tidak tercampur menjadi input untuk perintah berikutnya

Desain bantuan

  • Saat -h dan --help diberikan, bantuan yang memadai harus ditampilkan
    • Subperintah juga dapat memiliki bantuannya sendiri
    • -h tidak boleh dioverload dengan arti lain
  • Jika perintah yang membutuhkan argumen dijalankan tanpa argumen apa pun, bantuan singkat harus ditampilkan
    • Deskripsi program
    • Satu atau dua contoh pemanggilan
    • Penjelasan flag
    • Petunjuk untuk menggunakan --help untuk informasi lebih rinci
  • Sebaiknya sertakan jalur dukungan dalam bantuan
    • Tautan situs web atau GitHub umum digunakan
  • Jika ada dokumentasi web, bantuan harus menaut ke dokumentasi tersebut
    • Jika subperintah memiliki halaman atau anchor tertentu, menaut langsung ke sana akan berguna
  • Pengguna cenderung memakai contoh lebih dulu daripada dokumentasi, jadi sebaiknya letakkan contoh di bagian awal bantuan
    • Kasus penggunaan yang kompleks tetapi umum dapat ditampilkan lebih dulu
    • Jika contohnya banyak, lebih tepat menaruhnya di perintah cheat sheet terpisah atau halaman web
  • Bantuan dapat diformat agar mudah dipindai
    • Judul tebal meningkatkan keterbacaan
    • Harus diproses dengan cara yang independen dari terminal agar karakter escape tidak terlihat apa adanya
  • Jika pengguna salah mengetik dan maksudnya dapat diperkirakan, saran harus diberikan
    • Misalnya, brew update jq dapat bekerja dengan mengarahkan ke brew upgrade jq
    • Boleh menanyakan apakah pengguna ingin menjalankan perintah yang disarankan, tetapi hindari eksekusi paksa
  • Jika sebuah perintah harus menerima input dari stdin tetapi stdin adalah terminal interaktif, perintah harus segera menampilkan bantuan lalu keluar atau mencetak pesan ke stderr

Dokumentasi

  • Bantuan menyediakan ringkasan langsung dan panduan untuk tugas umum, sedangkan dokumentasi membahas secara rinci tujuan, non-tujuan, cara kerja, dan penggunaan lengkap alat
  • Dokumentasi berbasis web harus disediakan
    • Dapat dicari dan dapat ditautkan ke bagian tertentu
    • Dokumentasi web adalah bentuk dokumentasi yang paling komprehensif
  • Dokumentasi berbasis terminal juga harus disediakan
    • Dapat diakses dengan cepat
    • Tersinkronisasi dengan versi alat yang terpasang
    • Tetap berfungsi tanpa internet
  • Penyediaan halaman man dapat dipertimbangkan
    • Banyak pengguna akan memeriksa man mycmd terlebih dahulu
    • Seperti git dan npm, halaman man dapat diakses melalui subperintah help

Prinsip output

  • Output yang mudah dibaca manusia adalah yang paling penting
    • Kriteria sederhana untuk menentukan apakah stream output tertentu ditujukan untuk dibaca manusia adalah apakah itu TTY
  • Output yang dapat dibaca mesin harus disediakan sejauh tidak merusak kegunaan
    • Stream baris teks biasa adalah antarmuka universal UNIX
    • Pengguna mengharapkan hasil output dapat diteruskan ke alat seperti grep dan bekerja sesuai perkiraan
  • Jika output yang ramah manusia merusak output yang ramah mesin, Anda dapat menyediakan --plain
    • Dalam output berbentuk tabel, memecah sel menjadi beberapa baris dapat merusak ekspektasi satu record satu baris
    • --plain menyediakan output tabel tanpa manipulasi untuk skrip
  • Jika --json diberikan, output harus berupa JSON yang diformat
    • JSON memudahkan penanganan struktur data kompleks dan dapat digunakan bersama jq serta berbagai alat CLI JSON
    • Juga cocok untuk dipipe langsung dengan layanan web melalui curl
  • Saat berhasil, keluarkan output tetapi tetap singkat
    • Perintah UNIX tradisional sering kali tidak mengeluarkan output jika tidak ada masalah, tetapi bagi manusia ini bisa tampak seperti macet
    • Jika diperlukan tanpa output untuk skrip, opsi -q dapat menyembunyikan output yang tidak esensial
  • Perintah yang mengubah status harus memberi tahu pengguna apa yang berubah
    • git push adalah contoh yang menunjukkan pekerjaan yang sedang dilakukan dan status baru branch remote
  • Status sistem saat ini harus mudah dilihat
    • git status menampilkan status repositori bersama petunjuk perintah yang dapat dijalankan berikutnya
  • Operasi yang melewati batas dunia internal program biasanya harus eksplisit
    • Saat membaca atau menulis file yang tidak diberikan pengguna sebagai argumen
    • Saat berkomunikasi dengan server remote untuk mengunduh file
  • Warna harus digunakan dengan tujuan
    • Jika terlalu banyak digunakan, maknanya hilang dan menjadi sulit dibaca
    • Warna harus dimatikan jika bukan TTY, NO_COLOR disetel, TERM=dumb, atau --no-color diberikan
  • Jika stdout bukan terminal interaktif, jangan keluarkan animasi
    • Ini dapat mencegah indikator progres membuat log CI berantakan
  • Saat mengeluarkan banyak teks, pager seperti less dapat digunakan
    • Sebaiknya hanya digunakan ketika stdin atau stdout adalah terminal interaktif
    • less -FIRX dapat digunakan sebagai kumpulan opsi yang masuk akal

Pesan kesalahan

  • Membuat pesan kesalahan seperti dokumentasi dapat mengurangi waktu pengguna mencari dokumentasi
  • Kesalahan yang dapat diperkirakan harus ditangkap dan ditulis ulang agar dapat dipahami manusia
    • Contoh: memberi panduan bahwa file.txt tidak dapat ditulis dan mungkin perlu chmod +w file.txt
  • Rasio sinyal terhadap noise itu penting
    • Semakin banyak output yang tidak relevan, semakin sulit pengguna memahami masalah
    • Jika ada beberapa kesalahan dengan tipe yang sama, semuanya dapat dikelompokkan di bawah satu header penjelasan
  • Informasi paling penting sebaiknya ditempatkan di akhir output
    • Mata pengguna tertarik pada teks merah, jadi gunakan secara sengaja dan hemat
  • Jika kesalahan tidak terduga atau sulit dijelaskan, sediakan informasi debug/traceback dan cara melaporkan bug
    • Agar tidak membebani pengguna, log debug dapat ditulis ke file alih-alih ke terminal
  • Pelaporan bug harus dibuat mudah
    • Contohnya adalah menyediakan URL yang sudah diisi sebelumnya dengan informasi yang tersedia

Argumen dan flag

  • Argumen adalah parameter berbasis posisi, sedangkan flag adalah parameter bernama
    • Pada cp foo bar, path file adalah argumen
    • -r, --recursive, --file foo.txt adalah flag
  • Jika memungkinkan, flag sebaiknya lebih dipilih daripada argumen
    • Memang perlu mengetik lebih banyak, tetapi maknanya jelas
    • Lebih mudah mengubah cara input di masa depan
  • Semua flag harus menyediakan nama panjang
    • Misalnya menyediakan -h dan --help bersama-sama
    • Berguna untuk memperjelas makna dalam skrip
  • Flag satu huruf hanya boleh digunakan untuk opsi yang sering dipakai
    • Ini dapat mempertahankan ruang nama pendek untuk flag yang akan ditambahkan nanti
  • Jika menerapkan operasi sederhana yang sama ke beberapa file, beberapa argumen itu tepat
    • Bentuk seperti rm file1.txt file2.txt file3.txt cocok dengan globbing
  • Jika ada 2 argumen atau lebih dengan makna berbeda, kemungkinan desainnya buruk
    • Sebagai pengecualian, operasi yang umum dan inti seperti cp <source> <destination> cukup berharga untuk diingat karena singkat
  • Jika ada nama flag standar, ikuti nama tersebut
    • -a, --all
    • -d, --debug
    • -f, --force
    • --json
    • -h, --help
    • -n, --dry-run
    • --no-input
    • -o, --output
    • -p, --port
    • -q, --quiet
    • -u, --user
    • --version
  • Nilai default harus menjadi perilaku yang benar bagi sebagian besar pengguna
    • Jika diasumsikan pengguna akan menemukan flag yang tepat, mengingatnya, dan menggunakannya setiap kali, pengalaman sebagian besar pengguna akan memburuk
  • Jika tidak ada input, prompt dapat digunakan untuk bertanya, tetapi prompt tidak boleh wajib
    • Selalu sediakan cara untuk menyampaikan input melalui flag atau argumen
    • Jika stdin bukan terminal interaktif, lewati prompt dan minta flag atau argumen yang diperlukan
  • Harus ada konfirmasi sebelum operasi berbahaya
    • Dalam eksekusi interaktif, pengguna dapat diminta mengetik y atau yes
    • Dalam eksekusi noninteraktif, -f atau --force dapat diwajibkan
    • Untuk operasi serius, pengguna dapat diminta mengetik langsung nama target yang akan dihapus, atau menyediakan flag seperti --confirm="name-of-thing"
  • Jika menerima input/output file, dukung stdin atau stdout dengan -
    • Ini memungkinkan koneksi dengan output perintah lain tanpa file sementara
  • Jika memungkinkan, proses urutan argumen, flag, dan subperintah secara independen
    • Karena pengguna sering menambahkan opsi di akhir perintah sebelumnya lalu menjalankannya kembali
  • Nilai rahasia tidak boleh dibaca langsung melalui flag
    • Nilai --password dapat terekspos di output ps atau riwayat shell
    • Pertimbangkan input file seperti --password-file atau stdin

Interaksi

  • Prompt atau elemen interaktif hanya boleh digunakan ketika stdin adalah TTY
    • Karena prompt tidak akan bekerja selama input skrip atau pipe, beri tahu lewat kesalahan flag apa yang harus diberikan
  • Jika --no-input diberikan, jangan lakukan prompt atau perilaku interaktif
    • Jika input diperlukan, gagal dan jelaskan cara menyampaikannya melalui flag
  • Saat menerima input kata sandi, jangan tampilkan nilai yang diketik pengguna
    • Ini ditangani dengan mematikan echo terminal
  • Pengguna harus bisa keluar
    • Ctrl-C harus tetap berfungsi meskipun sedang berhenti karena I/O jaringan dan sebagainya
    • Jika berupa wrapper yang tidak dapat diakhiri dengan Ctrl-C seperti SSH, tmux, atau telnet, jelaskan cara keluar dengan jelas

Subperintah

  • Jika alat cukup kompleks, kompleksitas dapat dikurangi dengan sekumpulan subperintah
    • Menggabungkan beberapa alat terkait ke dalam satu perintah dapat memudahkan penggunaan dan penemuan
    • Ini memudahkan berbagi flag global, bantuan, konfigurasi, dan mekanisme penyimpanan
  • Konsistensi diperlukan antar-subperintah
    • Gunakan nama flag yang sama untuk makna yang sama
    • Format output juga harus serupa
  • Untuk subperintah bertingkat, gunakan skema penamaan yang konsisten
    • Pola yang terdiri dari dua tingkat nomina dan verba seperti docker container create umum digunakan
    • Baik noun verb maupun verb noun memungkinkan, tetapi noun verb tampaknya lebih umum
  • Hindari perintah dengan nama ambigu atau mirip
    • Jika update dan upgrade ada bersamaan, itu bisa membingungkan

Ketangguhan

  • Semua data yang dimasukkan pengguna harus divalidasi
    • Karena data yang tidak valid bisa masuk, periksa sejak awal dan hentikan dengan error yang dapat dipahami
  • Responsivitas lebih penting daripada kecepatan
    • Sebaiknya tampilkan sesuatu kepada pengguna dalam 100 ms
    • Bahkan sebelum request jaringan, tampilkan pesan agar tidak terlihat seperti macet
  • Untuk pekerjaan yang memakan waktu lama, tampilkan progresnya
    • Jika tidak ada output untuk beberapa waktu, program tampak seperti rusak
    • Jika indikator progres berhenti lama di satu titik, estimasi sisa waktu atau animasi dapat menunjukkan bahwa pekerjaan masih berlangsung
  • Pemrosesan paralel sebaiknya dilakukan jika memungkinkan, tetapi harus hati-hati
    • Menampilkan progres pekerjaan paralel di shell itu sulit, dan output yang bercampur akan membingungkan
    • Beberapa progress bar pada docker pull adalah contoh yang menunjukkan apa yang sedang terjadi
    • Sekalipun log disembunyikan di balik progress bar saat berjalan normal, saat terjadi error log harus ditampilkan agar debugging bisa dilakukan
  • Operasi jaringan harus memiliki timeout
    • Timeout harus dapat dikonfigurasi dan memerlukan nilai default yang masuk akal
  • Harus dapat pulih setelah kegagalan
    • Setelah kegagalan sementara, ketika dijalankan lagi dengan <up> dan <enter>, eksekusi harus dapat dilanjutkan dari titik terhenti
  • Jika memungkinkan, pendekatan crash-only lebih baik
    • Saat gagal atau dihentikan, program dapat langsung keluar, dan pembersihan dapat ditunda ke eksekusi berikutnya
  • Pengguna dapat menggunakan tool dengan cara yang tidak terduga
    • Mereka bisa membungkusnya dengan skrip, menggunakannya di internet yang tidak stabil, menjalankan beberapa instance sekaligus, atau menjalankannya di lingkungan yang belum diuji

Kompatibilitas masa depan

  • Subcommand, argumen, flag, file konfigurasi, dan variabel lingkungan semuanya adalah antarmuka, dan harus dijaga agar tetap berfungsi lama
  • Perubahan yang memungkinkan sebaiknya bersifat aditif
    • Alih-alih merusak perilaku flag yang ada, Anda dapat menambahkan flag baru
  • Jika perubahan non-aditif diperlukan, beri peringatan sebelumnya
    • Saat flag yang tidak lagi direkomendasikan digunakan, beri tahu perubahan mendatang dan juga cara yang kompatibel dengan masa depan yang dapat digunakan mulai sekarang
  • Output untuk manusia umumnya tidak masalah jika berubah
    • Arahkan pengguna agar menggunakan --plain atau --json untuk output yang stabil dalam skrip
  • Hindari subcommand catch-all
    • Pendekatan yang otomatis memperlakukan perintah yang bukan subcommand dikenal sebagai run dapat merusak penggunaan yang sudah ada saat menambahkan subcommand baru nanti
  • Jangan mengizinkan singkatan sembarang untuk subcommand
    • Jika install diizinkan sebagai i atau ins, akan sulit menambahkan perintah lain yang dimulai dengan i di kemudian hari
    • Alias harus dibuat eksplisit dan dijaga stabil
  • Pertimbangkan apakah perintah masih akan dijalankan dengan cara yang sama 20 tahun lagi
    • Jangan membuat bom waktu yang membuat perintah berhenti karena ketergantungan pada internet eksternal berubah atau hilang

Sinyal dan karakter kontrol

  • Jika pengguna mengirim Ctrl-C, yaitu sinyal INT, program harus keluar secepat mungkin
    • Sebelum memulai pekerjaan pembersihan, segera sampaikan sesuatu
    • Kode pembersihan harus memiliki timeout
  • Jika Ctrl-C dimasukkan lagi saat pembersihan yang lama berlangsung, pembersihan harus bisa dilewati
    • Docker Compose memberi tahu bahwa menekan Ctrl-C sekali lagi saat proses penghentian dapat langsung memaksa container berhenti
  • Program harus mengasumsikan bahwa ia dapat dimulai dalam keadaan pekerjaan pembersihan sebelumnya belum dijalankan

Konfigurasi dan variabel lingkungan

  • Metode konfigurasi harus bergantung pada kespesifikan, stabilitas, dan kompleksitas
    • Konfigurasi yang sering berubah setiap eksekusi cocok menggunakan flag
    • Konfigurasi yang relatif stabil dan berbeda menurut pengguna, proyek, atau mesin cocok menggunakan flag dan variabel lingkungan
    • Konfigurasi yang stabil untuk semua pengguna di dalam proyek cocok menggunakan file konfigurasi khusus perintah yang dikelola versi
  • Sebaiknya ikuti XDG Base Directory Specification
    • Tujuannya adalah mendukung lokasi konfigurasi serbaguna seperti ~/.config untuk mengurangi bertambahnya dotfile di direktori home
  • Jika secara otomatis mengubah file yang bukan konfigurasi program Anda sendiri, minta persetujuan pengguna dan beri tahu persis apa yang dilakukan
    • Lebih baik membuat file konfigurasi baru daripada menambahkan ke file konfigurasi sistem yang sudah ada
  • Prioritas konfigurasi harus diterapkan dari yang tertinggi ke yang terendah
    • Flag
    • Variabel lingkungan dari shell yang sedang berjalan
    • Konfigurasi tingkat proyek
    • Konfigurasi tingkat pengguna
    • Konfigurasi seluruh sistem
  • Variabel lingkungan cocok untuk perilaku yang berbeda sesuai konteks tempat perintah dijalankan
  • Nama variabel lingkungan harus hanya menggunakan huruf besar, angka, dan garis bawah demi portabilitas maksimal, serta tidak boleh diawali angka
  • Nilainya sebaiknya satu baris jika memungkinkan
    • Nilai multi-baris menimbulkan masalah usability saat digunakan bersama perintah env
  • Jangan sembarangan mengambil alih nama yang banyak digunakan
    • Daftar variabel lingkungan standar POSIX dapat dijadikan referensi
  • Jika memungkinkan, periksa variabel lingkungan umum
    • NO_COLOR, FORCE_COLOR
    • DEBUG
    • EDITOR
    • HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY
    • SHELL
    • TERM, TERMINFO, TERMCAP
    • TMPDIR
    • HOME
    • PAGER
    • LINES, COLUMNS
  • Jika sesuai, variabel lingkungan dapat dibaca dari .env
    • Berguna untuk variabel yang hampir tidak berubah selama bekerja di direktori tertentu
  • .env bukan pengganti file konfigurasi resmi
    • Sering kali tidak disimpan di source control
    • Hanya memiliki tipe string
    • Mudah menjadi tidak rapi
    • Mudah menimbulkan masalah encoding
    • Mudah berisi kredensial sensitif dan materi kunci
  • Nilai rahasia tidak boleh dibaca dari variabel lingkungan
    • Variabel lingkungan dapat terekspos melalui proses, log, docker inspect, systemctl show, dan sebagainya
    • Rahasia harus diterima melalui file kredensial, pipe, soket AF_UNIX, layanan manajemen rahasia, atau metode IPC lain

Nama, distribusi, dan pengumpulan analitik

  • Nama program CLI harus sederhana dan mudah diingat karena sering diketik pengguna
    • Jika terlalu umum, bisa bentrok dengan perintah lain atau membingungkan pengguna
  • Nama sebaiknya hanya menggunakan huruf kecil dan tanda hubung bila diperlukan
    • curl adalah nama yang baik, sedangkan DownloadURL adalah contoh yang tidak baik
  • Nama harus pendek, tetapi nama yang terlalu pendek lebih cocok untuk utilitas yang sangat umum seperti cd, ls, ps
  • Nama harus mudah diketik
    • Ada kasus nama awal Docker Compose adalah plum, lalu diubah menjadi fig karena canggung diketik dengan satu tangan
  • Jika memungkinkan, distribusikan sebagai satu binary
    • Jika satu binary sulit, distribusikan dengan cara yang mudah dihapus menggunakan installer paket bawaan platform
    • Tool khusus bahasa, misalnya linter kode, boleh berasumsi pengguna memiliki interpreter bahasa tersebut
  • Harus mudah dihapus
    • Karena pengguna sering ingin menghapus segera setelah instalasi, sebaiknya letakkan panduan penghapusan di bawah panduan instalasi
  • Metrik penggunaan dapat membantu meningkatkan tool, tetapi pengguna CLI mengharapkan kendali atas lingkungannya sendiri
  • Jangan mengirim data penggunaan atau crash tanpa persetujuan
    • Harus dijelaskan apa yang dikumpulkan, mengapa dikumpulkan, seberapa anonim datanya, bagaimana anonimisasi dilakukan, dan berapa lama disimpan
    • Idealnya opt-in; jika memilih opt-out dengan pengumpulan default, beri tahu dengan jelas di situs web atau saat pertama kali dijalankan, dan pastikan mudah dimatikan
  • Alternatif untuk pengumpulan analitik juga dapat dipertimbangkan
    • Menginstrumentasi dokumentasi web
    • Menginstrumentasi unduhan
    • Berbicara langsung dengan pengguna dan mendorong feedback serta permintaan fitur di dokumentasi dan repository

1 komentar

 
GN⁺ 2024-02-07
Opini Hacker News
  • Pernyataan bahwa “sekarang kebanyakan orang bahkan tidak tahu apa itu command line” memang benar, tetapi hal yang sama juga berlaku pada tahun 1980-an yang dijadikan patokan oleh TFA
    Bedanya, sekarang jumlah orang yang tahu dan bisa memakai command line adalah yang terbanyak dalam sejarah; setidaknya naik dalam skala satu digit, mungkin bahkan dua digit, jadi boleh saja disebut zaman keemasan CLI

    • Untuk memecah monolit, kami menempelkan alat command line ke sebagian aplikasi
      Global state dan dependensi mengganggu penalaran, dan pada akhirnya juga membuat debugging serta optimisasi performa menjadi sulit
      Jika kode sepanjang 500 baris, 1.000 baris, 5.000 baris, 10.000 baris, kadang 50 ribu baris, dipisahkan agar bisa dijalankan sendiri, banyak hal menjadi jauh lebih jelas
      Jika dilakukan dengan benar, ini juga bisa mendorong struktur Functional Core, Imperative Shell, karena command line yang sesuai filosofi Unix seharusnya punya banyak operasi tanpa efek samping dan sedikit operasi yang berefek samping
      Kita bisa membuat perintah kecil yang menghasilkan dan mencetak keadaan sistem tepat sebelum keputusan buruk diambil, dan secara praktis aman dijalankan bahkan di lingkungan produksi
      Dengan begitu, alat seperti ini juga lebih mudah diberikan kepada orang yang perlu termasuk dalam bus factor agar mereka bisa ikut terlibat
    • Jika “orang” diganti menjadi “pengguna komputer”, inti argumen penulis benar
      Apa pendapat orang di desa peradaban Amazon yang terpencil tentang terminal tidak relevan
    • Kita harus membedakan jumlah absolut dan rasio
      Untuk menilai perubahan kualitatif pada sesuatu yang jumlahnya membesar, yang perlu dilihat adalah rasionya; kalau hanya melihat jumlah absolut, hasilnya pernyataan yang benar tetapi tidak bermakna
      Misalnya jumlah absolut pendengar jazz saat ini mungkin lebih besar daripada pada masa kejayaan budaya genre itu, tetapi itu bukan karena jazz lebih populer, melainkan karena jumlah orang yang mendengarkan musik memang meningkat
      Namun sulit mengatakan bahwa jazz di Amerika kini lebih penting dan berpengaruh daripada pada masa kejayaannya
    • Intinya adalah apakah hal itu juga benar jika dilihat sebagai rasio di antara pengguna komputer pada tahun 1980-an
  • Saya juga berharap mereka mempertimbangkan opsi --dry-run yang menampilkan terlebih dahulu pekerjaan apa yang akan terjadi tanpa benar-benar melakukan perubahan
    Ini sangat berguna saat mempelajari sebuah alat, atau untuk memastikan opsi kompleks dan file glob sudah ditulis dengan benar sebelum menjalankan pekerjaan yang sulit dibatalkan

    • Jika perintah tidak bisa dibatalkan dan efek sampingnya besar, lebih baik menjadikan --dry-run sebagai default dan mewajibkan flag --execute untuk benar-benar menjalankannya
    • WhatIf di PowerShell adalah salah satu fitur favorit saya
      Saya tidak tahu bagaimana saya bisa bekerja tanpanya, dan fitur itu beberapa kali menyelamatkan saya dari situasi yang hampir benar-benar berantakan
    • Sebaliknya, saya lebih suka perilaku default dibuat tidak melakukan perubahan nyata, dan jika benar-benar ingin menjalankannya harus memberikan --commit
      Untuk skrip yang melakukan pekerjaan yang tidak bisa atau sulit dibatalkan, cara ini terasa lebih aman
    • Saya penasaran dengan contoh alat command line yang punya flag dry run
      Saya bingung bagaimana harus merancangnya untuk alat-alat yang sedang saya buat
      Kalau harus memanggil API untuk mengambil data, saya tidak tahu bagaimana membuat itu menjadi dry run
      Apakah harus memberikan contoh palsu dan output palsu?
    • Menurut saya dry-run seharusnya berupa fungsi yang bisa di-pipe ke perintah apa pun: do_thing.py | dry-run
      Anggap saja seperti meminta di prompt, “jelaskan proses kerjanya langkah demi langkah”
  • Bukan sekadar jangan menampilkan animasi jika standard output bukan terminal interaktif, tetapi jangan pernah menampilkan animasi di stdout
    TFA secara umum bagus, tetapi saya kecewa ketika mencari bagian yang menjelaskan perbedaan stderr dan stdout lalu melihat bahwa itu tidak dilakukan
    stderr bukan hanya untuk error, melainkan tempat untuk semua log dan output informatif, dan jika itu terminal, area ini juga bisa memuat animasi
    stdout harus berupa output nyata yang berguna, dan harus konsisten terlepas dari apakah itu terminal atau bukan
    Misalnya pada echo foo | mysed 's/oo/aa/' | cat, stdout dari mysed adalah faa, sedangkan stderr menjadi tempat log seperti informasi versi atau apa yang ditemukan
    Saya tidak ingin harus bertarung dengan tool menggunakan grep hanya untuk mendapatkan output nyata, dan saya juga tidak ingin debugging menjadi sulit karena perilakunya berubah ketika | cat dihapus

    • Jika aturan “stdout adalah output yang berguna” sedikit diperhalus, maka stdout seharusnya berisi apa yang diminta pengguna
      Jika yang diminta adalah --help, itu harus masuk ke stdout; jika yang diminta adalah log, log juga harus masuk ke stdout
      Jika informasinya tidak diminta, stderr adalah tempat yang tepat
    • Itu aturan yang bagus, tetapi namanya disayangkan
      Jika bisa memutar waktu, mungkin akan lebih baik dinamai stdin, stdout, dan stdext, sehingga orang lebih mungkin mengikuti konvensi ini
      Namun karena namanya stderr, developer secara masuk akal menganggapnya “untuk pelaporan error”, lalu memasukkan yang bukan error ke stdout
      Meski begitu, dari sisi struktur program cara ini lebih baik; walaupun awalnya bisa lebih membingungkan, output menjadi bisa melakukan hal yang lebih berguna, jadi ada manfaatnya
    • Kalau begitu, saya penasaran animasi seharusnya ditampilkan di mana
      Saya juga tidak yakin warna bisa dianggap sebagai informasi
  • Saya benar-benar berharap saran “gunakan simbol dan emoji di tempat yang membuatnya lebih jelas” dihindari
    yubikey-agent yang dijadikan contoh justru menunjukkan persis hal yang tidak saya sukai dari README GitHub dan antarmuka pengguna yang terlalu main-main
    Secara teknis, simbol dan emoji bisa dirender berbeda di tiap terminal sehingga membuat pesan membingungkan
    Secara estetika, toleransi orang terhadap nuansa jenaka dan ceria sangat berbeda-beda, jadi itu harus digunakan dengan sangat hemat, dan hanya jika benar-benar tahu apa yang sedang dilakukan

    • Saya suka output seperti itu
      Saya juga suka output terminal berwarna, dan emoji juga punya warna sehingga membantu menangkap gambaran situasi secara cepat
      Saya suka syntax highlighting, dan tanpa itu kode terasa jauh lebih sulit dibaca
      Tidak semua orang begitu, dan sebagaimana saya tidak berharap selera saya dijadikan default, selera yang berlawanan juga tidak boleh dipaksakan sebagai default
    • Kalau sebagai fitur opsional, itu bagus
      Ada yang suka dan ada yang tidak, jadi default-nya dimatikan saja, tetapi biarkan pengguna memilih
    • Sebagai pedoman, saya rasa bagus jika kosakata emoji yang dipakai dalam output dibatasi paling banyak dua
      Misalnya satu untuk sukses dan satu untuk gagal sudah cukup
      Dan informasi yang disampaikan emoji harus selalu diduplikasi juga dalam teks
    • Sangat setuju
      Saat pertama kali melihat CLI Guidelines, saya juga berhenti membaca di bagian itu
      Kali ini saya membaca sisanya juga, dan secara keseluruhan cukup bagus
  • Saya paham bahwa sebagian CLI sangat besar seperti aws sehingga perlu bersarang, tetapi mengikuti CLI bersarang itu benar-benar membuat frustrasi
    Untuk sebagian besar aplikasi, lebih baik help menampilkan semua opsi dan membiarkan saya mencari yang dibutuhkan dengan less

    • Saya banyak membuat aplikasi TUI, dan pada semua aplikasi saya menambahkan frontend TUI yang bagus agar bisa dipakai oleh orang yang kurang teknis, misalnya QA
      TUI ini murni UI/UX yang opsional, dan meneruskan pengaturan yang dipilih ke file hasil generate atau fungsi terpisah
      File atau fungsi itu selalu bisa dipanggil langsung dari terminal, dan juga menyediakan semua opsi serta bantuan yang digunakan di TUI
      Jadi bisa dipakai untuk skrip juga, dan berguna bagi pengguna dengan berbagai tingkat keahlian
    • Tergantung jumlah subperintah dan seberapa jelas perintah-perintah itu
      Jika tahu subperintah yang dibutuhkan, mempersempit opsi hanya ke yang diperlukan cukup berguna, tetapi kalau tidak tahu bisa menyakitkan
      Menyisir daftar opsi yang besar dengan grep juga melelahkan, jadi perlu keseimbangan
    • Bukankah itu peran halaman man?
    • Cara membentangkan --help subperintah ke perintah induk bisa membantu
      Misalnya git stash --help menampilkan bantuan git stash apa adanya, lengkap dengan setiap itemnya
  • Penjelasan bahwa “secara tradisional perintah UNIX ditulis terutama dengan asumsi akan dipakai program lain” tidak akurat
    Awalnya, yang terutama dimaksudkan adalah penggunaan interaktif di dalam login shell
    Ada program yang menghasilkan output ke stdout (ls, cat, find, tty, who, date) dan filter teks yang senyap (tr, grep, cut, uniq, sort, wc), dan pada masa itu pekerjaan komputasi dasar bisa dilakukan dengan perintah satu baris
    Program kompleks ditulis dalam C, dan setelah bahasa khusus domain seperti sed dan AWK muncul, sebagian program yang banyak memproses string berpindah ke shell
    Shell bukan lingkungan pemrograman yang layak, dan tidak pernah dimaksudkan untuk tujuan itu

    • Ada kasus program C 10 ribu baris bisa menjadi 10 baris shell, dan ada juga kasus program shell 1.000 baris mestinya cukup 100 baris C
      Sekarang sering kali lebih baik melakukan keduanya dengan Python atau Lua, tetapi shell dan C adalah yang paling umum terpasang
    • Layak atau tidak, shell adalah bahasa pemrograman, dan pada Unix awal hal itu jauh lebih menonjol
      Terpecahnya menjadi sh, bash, ksh, csh juga contoh yang bagus
      Saya rasa cukup masuk akal melihat kumpulan alat standar POSIX sebagai pustaka standar bagi berbagai bahasa shell
  • Baris perintah Unix saat ini di satu sisi “sangat berguna”, dan di sisi lain rusak secara desain
    Kegunaannya jelas jika membayangkan berapa lama waktu yang dibutuhkan untuk menulis yang berikut ini dalam C atau Rust:
    curl -sS https://go.dev/doc/devel/release | html2text | grep -o -P '\bgo\d+\.\d+\.\d+\b' | sort -V | uniq | tail -1
    Tetapi untuk melihat mengapa ia rusak secara desain, lihat https://news.ycombinator.com/item?id=29747034
    Masalahnya adalah antarmuka baris perintah harus mudah dibaca manusia sekaligus mudah dibaca mesin, dan tidak ada cara standar untuk menyelesaikannya

    • Contoh itu sendiri menunjukkan dengan baik mengapa ia rusak secara desain
      Untuk masalah bahwa sesuatu harus bisa dibaca manusia dan mesin sekaligus, mungkin sebenarnya pernah bisa ada solusi standar
      Apple membuat Human Interface Guidelines untuk mengonkretkan makna abstraksi visual pada UI desktop
      Namun baris perintah tidak dibuat oleh orang-orang yang berpikir seperti desainer Apple, melainkan oleh orang-orang yang berpikir, “kemalasan, ketidaksabaran, dan kesombongan adalah kebajikan, jadi bagaimana mengekspresikan yang saya inginkan dengan kode seminimal mungkin”
      Pada saat itu pilihan tersebut tidak salah, dan setiap byte memang penting, tetapi keputusan desain itu kini sudah tertanam dalam toolchain yang tidak bisa digeser
      Untuk mendapatkan sesuatu yang lebih baik dari sekarang, tampaknya kita pada dasarnya harus meninggalkan toolchain POSIX, dan sulit membayangkan membangun UX yang mudah ditemukan dan konsisten secara konseptual di atas fondasi saat ini
    • Pada akhirnya komputer ada untuk melayani kita, jadi solusi akhirnya seharusnya membuat mesin membaca sebaik manusia
    • Dalam praktiknya, biasanya bukan “sekaligus”, melainkan manusia dan mesin menggunakan perintah yang sama pada waktu yang berbeda
      Bahkan pada waktu yang sama pun ada banyak cara untuk memungkinkan output yang berbeda
      Namun harus ada standar yang diikuti semua orang, dan di titik itulah segalanya menjadi rumit
    • Contoh itu bukan hanya tidak membuktikan bahwa desainnya rusak, tetapi juga tampaknya menunjukkan solusi yang relatif mudah
      Jika masalahnya adalah hanya sedikit implementasi ls yang memungkinkan nama file diakhiri karakter NUL alih-alih baris baru, solusinya tampak begitu jelas sampai saya merasa mungkin ada sesuatu yang terlewat
      Apakah antarmuka shell menolaknya karena suatu alasan?
    • Cara yang dibahas dalam artikel adalah mode output yang dapat dibaca mesin seperti --json
  • Meski dikatakan “jangan membaca nilai rahasia dari variabel lingkungan”, panduan itu menyarankan file kredensial, pipe, soket AF_UNIX, layanan manajemen rahasia, dan komunikasi antarproses lainnya; saya penasaran mana di antaranya yang paling nyaman dan paling portabel
    Saya juga penasaran apakah layanan manajemen rahasia hanya dipakai di pekerjaan, atau juga di proyek pribadi

    • Saya salah satu penulis CLI Guidelines
      Tulisan yang membahas sedikit lebih dalam soal menangani nilai rahasia di command line ada di https://smallstep.com/blog/command-line-secrets/
      File kredensial adalah pilihan yang sederhana dan portabel
      File sudah memiliki model perizinan, dan tidak bergantung pada layanan eksternal atau API proprietari
      Jika sebuah program menerima file kredensial, itu juga kompatibel dengan systemd credentials
      systemd credentials lebih aman daripada file kredensial yang tidak terenkripsi, terenkripsi dan juga bisa diikat ke TPM, tetapi software yang memakai kredensial tidak perlu mendukung TPM sendiri
    • Akan bagus jika program memungkinkan kita menentukan perintah untuk mengambil nilai rahasia
      Misalnya mbsync(https://isync.sourceforge.io/mbsync.html) punya kira-kira tiga cara untuk menyediakan kata sandi autentikasi IMAP
      Jika kata sandi tidak diatur, saat dijalankan akan muncul prompt; kita juga bisa menaruh kata sandi plaintext di file konfigurasi, tetapi itu kurang praktis untuk dibagikan
      Selain itu, kita bisa mengatur perintah untuk mengambil kata sandi, sehingga pemrosesannya bisa didelegasikan ke password manager seperti pass(1)(https://www.passwordstore.org/) atau prompt grafis interaktif
    • Layanan manajemen rahasia mungkin yang paling nyaman
      Dokumentasinya bagus sehingga mudah dikonfigurasi tanpa perlu membuat tambahan sendiri
      Manajer rahasia seperti Doppler(https://Doppler.com) atau AWS Secrets Manager(https://aws.amazon.com/secrets-manager/) punya keunggulan karena melindungi nilai rahasia di tempat yang aman dan meminimalkan eksposurnya
      Bahkan eksposur terhadap developer internal pun bisa dikurangi, sehingga membantu mencegah kebocoran data yang sebenarnya mudah dihindari
      Kebocoran seperti ini bisa membahayakan seluruh perusahaan dan makin sering terjadi
  • Artikel terkait: Command Line Interface Guidelines - https://news.ycombinator.com/item?id=38053692 - Oktober 2023, 1 komentar
    Command Line Interface Guidelines - https://news.ycombinator.com/item?id=31651161 - Juni 2022, 1 komentar
    Command Line Interface Guidelines - https://news.ycombinator.com/item?id=25492119 - Desember 2020, 5 komentar

  • Sangat menyebalkan ketika beberapa terminal otomatis menjalankan perintah jika string yang ditempel dari clipboard berakhir dengan karakter baris baru
    Secara pribadi, menurut saya antarmuka command line seharusnya tidak melakukan itu

    • Di Bash, gunakan bind 'set enable-bracketed-paste on'
    • iTerm di macOS meminta konfirmasi saat kita mencoba menempelkan string yang berisi baris baru
      Jika terasa mengganggu, bisa dimatikan
    • Fish shell secara default hanya menyisipkan sesuai harapan dan memungkinkan kita mengedit perintah sebelum dijalankan
      Jika perlu, beberapa baris juga bisa, dan baru dijalankan setelah menekan Enter
      Fish shell sering punya default yang masuk akal, dan selain prompt, sejauh ini saya belum menemukan bagian yang benar-benar ingin saya kustomisasi
    • Layak mencoba clipboard manager
      Sebagian besar yang pernah saya coba punya opsi untuk menghapus baris baru dari isi clipboard
    • Jika tahu baris barunya paling banyak hanya satu, saya mengetik # terlebih dahulu lalu menempelkannya
      Meski baris baru diinterpretasikan, seluruh baris akan menjadi komentar sehingga aman, dan sebelum benar-benar menjalankannya cukup hapus # di awal baris