Bagaimana Saya Mengubah Catatan untuk Mesin Jadi Catatan untuk Orang
On this page
- Pendahuluan
- A. Pesan commit ditulis untuk siapa
- B. Apa yang berubah ketika pembacanya berganti
- C. Kenapa ini bukan menulis laporannya
- D. Kenapa jawabannya sebuah file, bukan sebuah perintah
- E. Tujuh hambatan yang menghalangi
- Metode
- A. Mengambil empat kolom lalu menyimpan dua
- B. Menjalankan riwayatnya maju
- C. Memutuskan sebuah tanggal itu artinya apa
- D. Membuang andaian bahwa ada yang menonton
- E. Memilih pekerjaan siapa yang dihitung
- F. Menjadikan rentangnya sebuah argumen
- G. Menghitung yang sungguh terekspor
- Hasil dan Pembahasan
- A. Tiap keputusan adalah keputusan yang sama
- B. Kenapa format keluarannya tak menarik dipandang
- C. Di mana ini berhenti jadi tool yang tepat
- Simpulan
- Istilah
Ada yang bertanya apa saja yang saya kerjakan bulan lalu. Jawabannya sudah ada — ia menumpuk di sebuah repository sepanjang waktu itu, satu commit per satuan pekerjaan, bertanggal dan berurutan. Yang belum ada adalah versi jawaban itu yang sanggup dibaca orang yang bertanya.
Pendahuluan
A. Pesan commit ditulis untuk siapa
Pesan commit punya dua pembaca, dan tak satu pun di antaranya adalah orang yang menanyakan bulan lalu kepada saya.
Pembaca pertama git sendiri, yang membutuhkan pesannya cuma sebagai label — sesuatu untuk dicetak di samping hash supaya satu revisi bisa dibedakan dari revisi lain. Git tak membaca pesannya; ia menyimpannya.
Pembaca kedua saya sendiri enam bulan lagi, menatap satu baris di tengah bisect sambil berusaha memahami kenapa sebuah fungsi berubah. Versi saya yang itu berbagi seluruh konteks: project-nya, kosakatanya, arti singkatan-singkatannya, subsistem mana yang dimaksud "resolver". Saya menulis untuk orang itu, dan saya menulis dengan hemat, sebab orang itu sudah tahu hampir segalanya.
Tak satu pun dari keduanya adalah atasan atau klien. Keduanya membaca teks yang sama tanpa konteks bersama sedikit pun dan dengan pertanyaan yang sama sekali berbeda di kepala — bukan "kenapa ini berubah" melainkan "apa yang berhasil dikerjakan".
B. Apa yang berubah ketika pembacanya berganti
Bagian menariknya adalah seberapa banyak yang harus bergeser begitu pembaca ketiga itu muncul, dan seberapa sedikit dari pergeseran itu yang menyangkut isi pesannya.
Kata-katanya tetap. Yang berubah justru segala yang mengelilinginya: kolom mana yang ditampilkan, urutan barisnya seperti apa, tanggalnya dirender bagaimana, pekerjaan siapa yang ikut, dan apakah hasilnya berupa aliran teks atau file yang bisa dibuka di spreadsheet lalu disortir.
Tiap satunya keputusan kecil, dan tiap satunya punya jawaban yang jelas benar untuk developer yang membaca di terminal sekaligus jawaban lain yang jelas benar untuk orang yang menilai sebulan pekerjaan. Jarak antara kedua kumpulan jawaban itulah yang disebut laporan.
C. Kenapa ini bukan menulis laporannya
Saya ingin tepat soal cakupannya, sebab ada versi lain dari perkara ini yang jauh lebih besar dan bukan itu yang dibahas di sini.
Mengubah commit jadi narasi — mengelompokkan pekerjaan yang berkerabat, menjelaskan maknanya, menyebut bagian mana yang penting — itu menulis, dan tak ada tool yang mengerjakannya. Yang sanggup dikerjakan sebuah tool adalah menghasilkan bahan mentahnya dalam bentuk yang memungkinkan penulisan itu: daftar yang akurat, berurutan, dan terbaca tentang apa yang terjadi dan kapan — yang kalau tidak, harus saya susun sendiri dari ingatan sambil menggulir layar.
Jadi keluaran di sini bukan laporan. Ia bahan berbentuk spreadsheet untuk sebuah laporan, dan pembedaan itu menentukan sebab ia menjelaskan kenapa formatnya CSV ketimbang format yang lebih enak dipandang.
D. Kenapa jawabannya sebuah file, bukan sebuah perintah
Membaca riwayat di terminal sudah terpecahkan — git mengerjakannya, dan mengerjakannya dengan baik. Alasan itu belum cukup sama sekali tak menyangkut kemampuan.
Terminal menghasilkan aliran yang menggulir lewat. Orang yang membutuhkan ini ingin menyortirnya, menyaring satu minggu, menghitung barisnya, lalu menempelkan sebagian ke dokumen yang lebih besar. Semua itu operasi spreadsheet, dan semuanya menuntut file berkolom beserta pemisahnya — benda yang berbeda dari aliran teks terformat, bahkan ketika keduanya memuat keterangan yang sama.
E. Tujuh hambatan yang menghalangi
Jadi tujuannya gampang dirumuskan: menghasilkan, dari sebuah repository, catatan akurat tentang apa yang dikerjakan sepanjang rentang waktu tertentu, dalam bentuk yang terbuka di spreadsheet dan terbaca benar oleh orang yang tak pernah memakai git. Bisa diulang, sebab pertanyaannya datang lagi tiap bulan.
Gampang dirumuskan, canggung dibangun. Tujuh hambatan berdiri antara tujuan itu dan sebuah file yang berani saya serahkan kepada orang, dan tiap satunya tempat di mana default git benar untuk developer sekaligus keliru untuk keperluan ini.
Yang pertama, keluaran git dibentuk untuk orang yang men-debug, bukan orang yang menilai. Entri log bawaannya dibuka dengan hash, disusul nama author dan timestamp lengkap, lalu menghiasi branch dan tag — seluruhnya penting saat memburu regresi dan seluruhnya kebisingan di ringkasan pekerjaan. Perbaikan yang menggoda adalah memangkasnya langsung jadi dua kolom yang memang dibutuhkan, dan itu ternyata agak keliru karena alasan yang baru muncul belakangan.
Yang kedua, git mengurutkan riwayat terbalik dari cara laporan dibaca. Terbaru dulu memang benar untuk terminal, di mana puncak layar tempat perhatian bermula dan commit terkini biasanya yang dicari orang. Laporan sebulan dibaca dari awal bulan, dan daftar yang mengalir sebaliknya memaksa pembacanya membalik urutannya di kepala sebelum ia sanggup mengikuti apa pun.
Yang ketiga, timestamp membawa zona waktu sementara laporan tidak. Git mencatat kapan sebuah commit terjadi lengkap dengan offset tempat ia terjadi. Laporan berurusan dengan tanggal, bukan momen. Merender timestamp itu tanpa memutuskan zona mana yang berlaku berarti commit yang dibuat larut malam bisa mendarat di hari berikutnya — dan di batas bulan, itu menaruh pekerjaan di laporan yang sama sekali keliru.
Yang keempat, git mengandaikan ada manusia yang menonton. Ketika keluarannya melebihi satu layar, git membuka pager lalu menunggu. Itu menolong di terminal dan fatal di dalam script, di mana pager-nya tak punya siapa pun untuk menekan tombol dan seluruhnya berhenti, tanpa menghasilkan apa pun, tanpa error yang menjelaskan sebabnya.
Yang kelima, repository memuat pekerjaan semua orang. Tiap commit di repository bersama ada di dalam log, dan laporan pekerjaan saya cuma sebagian darinya. Penyaringan jadi wajib — dan penyaring itulah keputusan paling berkonsekuensi di seluruh tool ini, sebab dialah yang diam-diam menentukan apa yang diklaim dicakup laporannya.
Yang keenam, rentang waktu adalah pertanyaannya, bukan pengaturannya. Memakai bulan berjalan sebagai default memang nyaman, sebab itu keadaan yang paling sering. Ia juga cukup sering keliru sampai berarti: pertanyaannya datang sebagai kuartal, sebagai sprint, sebagai rentang satu project. Default yang biasanya benar menghasilkan laporan yang percaya diri membahas tanggal yang keliru.
Yang ketujuh, satu angka yang meleset merusak kepercayaan pada angka lainnya. Tool-nya melaporkan berapa commit yang ia ekspor, dan angka itu sepele diturunkan dari file yang baru saja ia tulis — kecuali bahwa file-nya punya baris header, dan header bukan commit. Keliru satu di sini menghasilkan angka yang diam-diam palsu, di dalam dokumen yang seluruh tujuannya justru untuk dipercaya.
Masing-masing punya seksi di bawah. Empat yang pertama soal membentuk ulang keluarannya; dua berikutnya soal memutuskan apa yang berhak masuk; yang terakhir soal laporannya bisa dipercaya — dan cuma sifat itulah yang berarti begitu ada orang lain yang membacanya.
Metode
A. Mengambil empat kolom lalu menyimpan dua
Inilah jawaban atas hambatan pertama, dan ia memuat keputusan yang kelihatan mubazir sampai alasannya muncul.
| Empat kolom diminta dari git: hash pendek, nama author, tanggal, subjek. Lalu awk, tool pengolah teks kecil yang memecah tiap baris menjadi kolom, cuma mencetak yang ketiga dan keempat. Dua yang pertama diambil lalu seketika dibuang.
Meminta tanggal dan subjek saja kepada git akan menghasilkan keluaran identik dengan kerja lebih sedikit, dan saya sengaja tak melakukannya. Kedua baris itu lapisan yang berbeda. Tugas git mengekstrak kolom dari repository; tugas penyaringnya memutuskan mana di antaranya yang pantas dilihat pembaca. Memisahkan keduanya membuat perubahan atas apa yang tampil di laporan cukup jadi perubahan pada satu ungkapan awk, tanpa menyentuh bagian yang berbicara dengan git.
Ini juga menjelaskan kedua pemisahnya, yang mengerjakan tugas berbeda walau rupanya seperti trik yang sama. Garis tegak adalah batas kolom milik git, internal di dalam pipeline dan tak pernah dilihat siapa pun. Titik koma adalah batas kolom CSV, bagian dari benda hasilnya. Yang satu milik perpipaan dan yang lain milik keluarannya, dan meleburkan keduanya jadi satu pilihan akan mengikat format laporannya pada cara datanya diambil.
--no-decorate membuang keterangan branch dan tag. Di terminal keduanya memberitahu developer ia sedang di mana; di laporan keduanya kosakata kedua yang tak berguna bagi pembacanya dan tak ada cara menafsirkannya.
B. Menjalankan riwayatnya maju
Inilah jawaban atas hambatan kedua, dan ia satu flag.
Default git — terbaru dulu — benar untuk tujuan biasanya. Yang membuka log hampir selalu menanyakan pekerjaan terkini, dan menaruhnya di puncak berarti jawabannya langsung ada di layar.
Laporan justru kebalikannya. Ia mencakup rentang yang sudah berakhir, dan ia dibaca sebagai urutan: beginilah bulan itu dimulai, begini jalannya, begini akhirnya. Menyajikannya terbalik tak membuatnya mustahil dibaca, tapi memaksa pembacanya mengerjakan satu transformasi sebelum ia sanggup mengikuti bentuk pekerjaannya — dan pembaca yang harus berjuang pada formatnya menyisakan lebih sedikit perhatian untuk isinya.
Satu flag, dan itulah beda antara daftar commit dengan catatan sebulan pekerjaan.
C. Memutuskan sebuah tanggal itu artinya apa
Inilah jawaban atas hambatan ketiga, dan ia pilihan format yang sebenarnya pilihan makna.
--date=format-local:--Ada dua perkara yang sedang diputuskan. Formatnya membuang jamnya sama sekali, menyisakan tanggal kalender, sebab laporan adalah catatan atas hari dan jam sebuah commit dibuat tak membawa makna apa pun bagi yang membacanya.
Bagian local-nya yang sungguh menentukan. Git menyimpan tiap commit beserta offset zona waktu mesin yang membuatnya, dan merender itu tanpa mengambil keputusan berarti tanggal yang tampil bergantung pada saya sedang duduk di mana ketimbang pada hari kerja mana ia termasuk. Menambatkan segalanya ke waktu lokal membuat tanggalnya berarti seperti yang diandaikan pembacanya: hari sebagaimana terasa saat pekerjaannya berlangsung.
Akibatnya kelihatan di batas rentang. Commit yang dibuat menjelang tengah malam di hari terakhir sebuah bulan adalah pekerjaan bulan itu, dan render yang menggesernya maju menaruhnya di laporan berikutnya — sekaligus jadi tambahan bagi rentang yang bukan miliknya dan kekosongan di rentang yang memang miliknya.
D. Membuang andaian bahwa ada yang menonton
Inilah jawaban atas hambatan keempat, dan ia flag yang sama sekali tak mengubah isinya.
Git membuka pager ketika keluarannya panjang, dan itu perilaku yang penuh perhatian untuk pemakaian interaktif sekaligus kegagalan telak di dalam script. Pager-nya menunggu tombol ditekan. Tak ada siapa pun di sana. Script-nya tak error, tak kehabisan waktu, dan tak menghasilkan file — ia sekadar berhenti, dan satu-satunya gejalanya perintahnya tak pernah kembali.
Yang membuat ini pantas dipertimbangkan sendiri adalah cara kegagalannya menampakkan diri. Script yang jatuh memberitahu di mana. Script yang menggantung tak memberitahu apa-apa, dan sebabnya justru fitur yang dirancang untuk menolong, di keadaan yang tak punya siapa pun untuk ditolong.
E. Memilih pekerjaan siapa yang dihitung
Inilah jawaban atas hambatan kelima, dan ia satu baris yang membentuk seluruh makna keluarannya.
Repository bersama memuat commit semua orang berselang-seling. Laporan pekerjaan saya cuma sebagian darinya, dan penyaringnya yang menetapkan bagian mana.
Memaku nama author di dalam script ketimbang membukanya sebagai argumen adalah keputusan tentang keadaan yang paling sering. Nyaris tiap kali saya menjalankan ini, jawabannya saya sendiri, dan argumen yang akan saya isi sama persis tiap kali adalah argumen yang cepat atau lambat terisi keliru.
Ia sekaligus menetapkan cakupan tool ini dengan sengaja. Laporan yang mencakup satu tim butuh penyaring lain atau tak butuh penyaring sama sekali, dan itu pertanyaan yang berbeda; tool ini menjawab satu pertanyaan dengan baik, dan pertanyaan itu tentang satu orang.
F. Menjadikan rentangnya sebuah argumen
Inilah jawaban atas hambatan keenam: rentangnya wajib, dan script-nya menolak menebak.
if [; then
Memakai bulan berjalan sebagai default memang menggoda dan akan benar di sebagian besar kesempatan. Alasan penolakannya terletak pada ongkos "sebagian besar" di sini: pertanyaannya datang sebagai kuartal ketika ada yang sedang melakukan tinjauan, sebagai rentang project ketika klien bertanya apa yang sudah diserahkan, sebagai sepasang tanggal sembarang ketika sebuah rentang perlu disusun ulang belakangan.
Tool yang memilih default masuk akal pada keadaan semacam itu menghasilkan file yang tampak benar sambil mencakup tanggal yang keliru — dan tak ada di keluarannya yang menyatakan begitu, sebab tanggal di dalamnya seluruhnya nyata. Mewajibkan kedua batasnya berarti rentang di dalam file selalu rentang yang ditanyakan.
Argumen ketiganya path keluaran, dan folder yang ia sebut dibuat bila belum ada:
Laporan ditulis ke folder yang disusun menurut rentangnya, dan folder itu kerap belum ada. Gagal karena satu folder belum dibuat akan jadi kegagalan soal pembukuan filesystem di dalam tool yang pokok urusannya sebuah repository.
G. Menghitung yang sungguh terekspor
Inilah jawaban atas hambatan ketujuh, dan ia perkara aritmetika yang memikul bobot lebih besar dari ukurannya.
TOTAL_LINES=
COMMIT_COUNT= # the header row is not a commitScript-nya melaporkan berapa commit yang ia ekspor, dan sumber paling kentara untuk angka itu adalah file yang baru saja ia tulis. Sumber paling kentara itu meleset satu, sebab awk mencetak satu baris header dan header bukan commit.
Angkanya sendiri sepele. Yang dipengaruhinya tidak. Laporan diserahkan di atas premis bahwa ia akurat, dan pembaca yang menyadari jumlah yang disebut tak cocok dengan barisnya sudah belajar sesuatu tentang dokumennya secara keseluruhan — bukan bahwa satu angka keliru, melainkan bahwa angkanya tak diperiksa. Segala isi lainnya berubah dari fakta jadi klaim.
Hasil dan Pembahasan
A. Tiap keputusan adalah keputusan yang sama
Dijajarkan bersama, flag-flag itu berhenti terlihat sebagai kumpulan perbaikan yang tak berkaitan.
| Keputusan | Benar untuk developer | Benar untuk laporan |
|---|---|---|
| Kolom yang tampil | Hash, author, timestamp lengkap | Tanggal dan subjek saja |
| Urutan | Terbaru dulu | Terlama dulu |
| Tanggal | Momen persis beserta offset | Tanggal kalender, lokal |
| Keluaran panjang | Membuka pager | Menulis ke file |
| Commit siapa | Semua orang | Satu orang |
Tak satu pun default git yang keliru. Tiap satunya pilihan yang benar bagi orang yang membaca di terminal dengan seluruh konteks repository-nya di kepala. Seluruh tool ini empat puluh lima baris yang menimpa default yang benar, semata-mata karena pembacanya berganti.
Pembingkaian ulang itulah yang saya bawa dari membangunnya. Pekerjaannya tak pernah ada pada mengalahkan perilaku git; melainkan pada menyadari bahwa tiap default memuat andaian tentang siapa yang membaca, dan bahwa seluruh andaian itu jadi keliru sekaligus begitu keluarannya meninggalkan terminal.
B. Kenapa format keluarannya tak menarik dipandang
CSV bukan format yang enak dilihat, dan bukan untuk itu ia ada.
File-nya bukan barang yang diserahkan. Ia bahan bagi apa pun yang nanti jadi barang serahannya — ringkasan yang ditulis di sebuah dokumen, tabel yang ditempel ke slide, angka yang dikutip di email. Yang dibutuhkan orang yang mengerjakan itu adalah menyortir menurut tanggal, menyaring satu minggu, menghitung baris, lalu menyalin sebagian — dan semuanya dikerjakan spreadsheet dengan baik sementara dokumen terformat tidak.
Markdown atau PDF akan lebih enak dipandang sekaligus lebih sulit dipakai, sebab keduanya dioptimalkan untuk dibaca apa adanya, sementara yang ini tak dibaca apa adanya. Memilih format yang lebih polos berarti memilih melayani langkah berikutnya ketimbang langkah sekarang.
C. Di mana ini berhenti jadi tool yang tepat
Cakupannya sempit dengan cara-cara yang pantas dinyatakan terang-terangan.
Penyaring author-nya dipaku, jadi laporan tim di luar jangkauannya tanpa menyunting script. Ia membaca satu repository, jadi pekerjaan yang tersebar di beberapa repo menuntut beberapa kali jalan lalu digabung dengan tangan. Lalu ia melaporkan commit, dan commit cuma proksi atas pekerjaan ketimbang ukuran atasnya — seminggu perancangan yang cermat bisa menghasilkan satu commit sementara sehari penggantian nama yang mekanis bisa menghasilkan tiga puluh, dan tak ada di keluarannya yang membedakan keduanya.
Simpulan
Empat puluh lima baris, dan nyaris seluruhnya flag. Tool-nya tak mengerjakan pengolahan yang pantas disebut begitu: ia meminta daftar kepada git, membuang dua kolom, lalu menulis hasilnya ke sebuah file.
Yang membuatnya sepadan ditulis: tiap flag itu koreksi atas satu andaian tentang siapa yang membaca. Default git disetel untuk developer di terminal, dan tiap satunya — pemilihan kolomnya, urutannya, ketelitian timestamp-nya, pager-nya, log yang tak disaring — persis benar untuk pembaca itu dan persis keliru untuk orang yang menilai sebulan pekerjaan. Tool ini bukan transformasi atas datanya. Ia transformasi atas pembacanya, dan begitu itu jadi bingkainya, pertanyaan flag mana yang perlu diraih berhenti jadi pertanyaan.
Istilah
- Pesan commit
- Teks yang menempel pada sebuah revisi, ditulis untuk git sebagai label dan untuk diri penulisnya di masa depan sebagai pengingat. Tak satu pun dari keduanya adalah pembaca yang menilai pekerjaannya.
- Pager
- Program yang dibuka git ketika keluarannya melebihi satu layar, menunggu tombol ditekan untuk menggulir. Menolong saat interaktif; di dalam script ia menunggu masukan yang tak pernah datang.
- Decoration
- Keterangan branch dan tag yang ditambahkan git di samping commit, menunjukkan letak sebuah revisi di dalam graph-nya. Berguna saat menjelajah, tak bermakna di dalam ringkasan.
- Penyaring author
- Pembatasan yang mengurung log pada commit milik orang tertentu. Menetapkan apa yang sebenarnya dicakup laporan hasilnya, dan itu membuatnya setelan paling berkonsekuensi di tool ini.
- Render waktu lokal
- Menampilkan timestamp dalam zona waktu pembacanya ketimbang zona yang tercatat bersama commit-nya, supaya sebuah tanggal berarti hari saat pekerjaannya berlangsung.
- Baris header
- Baris pertama sebuah CSV, yang menamai kolomnya. Bukan baris data, dan karena itu perhitungan apa pun yang diturunkan dari file-nya harus memperhitungkannya.
Technologies covered
- Bash
- awk
- Git