Gaya penulisan kode yang seragam mempermudah pembacaan, tetapi menegakkannya secara manual terasa lambat dan tidak konsisten antaranggota tim. Pemformatan otomatis menyusun ulang kode mengikuti aturan yang tetap, sedangkan linting membaca kode tanpa menjalankannya untuk melaporkan pelanggaran gaya dan pola yang berpotensi menjadi bug. Topik ini membahas ruff sebagai alat pemformatan sekaligus linter, menunjukkan cara kerja linter dalam bentuk paling sederhana, serta mengotomatiskan keduanya pada setiap commit melalui hook pre-commit, yaitu skrip yang dijalankan Git sebelum commit dibuat. Setelah membacanya, pemeriksaan gaya berjalan sendiri tanpa mengandalkan ingatan perorangan.
Formatter dan linter#
Formatter adalah alat yang menulis ulang kode sumber mengikuti aturan bentuk yang tetap, seperti lebar indentasi, jumlah baris kosong antarfungsi, dan panjang baris maksimum. Linter membaca kode yang sama secara statis, lalu melaporkan pelanggaran konvensi beserta nomor barisnya, mulai dari impor yang tidak digunakan sampai pola yang sering menyembunyikan kesalahan logika. Keduanya tidak mengubah perilaku program, karena formatter hanya menyusun ulang teksnya, sedangkan linter hanya melaporkan tanpa menulis ulang apa pun. Tabel berikut merangkum perbedaan keduanya.
| Aspek | Formatter | Linter |
|---|---|---|
| Keluaran | berkas kode yang ditulis ulang | daftar temuan beserta nomor barisnya |
| Fokus | bentuk visual kode | bentuk kode dan pola berisiko |
| Pola kerja | menulis ulang secara langsung | melaporkan, sebagian dapat diperbaiki otomatis |
Perbedaan sebelum dan sesudah pemformatan terlihat pada dua potongan berikut. Keduanya berperilaku sama ketika dijalankan, tetapi bentuk kedua mengikuti aturan indentasi empat spasi dan pemecahan baris yang ditetapkan alat pemformatan.
def statistik(nilai):
return {"jumlah": sum(nilai),"rata_rata": sum(nilai)/len(nilai),"maks": max(nilai)}def statistik(nilai):
return {
"jumlah": sum(nilai),
"rata_rata": sum(nilai) / len(nilai),
"maks": max(nilai),
}Alat pemformatan yang gayanya menjadi acuan luas di ekosistem Python adalah black, dan hasilnya menetapkan standar bentuk kode bagi banyak proyek. Menjalankan formatter di akhir pekerjaan lebih andal daripada merapikan spasi secara manual, karena hasilnya selalu sama untuk kode yang sama.
Ruff untuk pemformatan dan linting#
ruff adalah alat tunggal yang ditulis dengan bahasa Rust dan menyatukan dua tugas sekaligus. Subperintah ruff format menyusun ulang kode dengan gaya black, sedangkan subperintah ruff check menjalankan ratusan aturan linting yang mencakup konvensi PEP 8, impor yang tidak terpakai dengan kode F401, dan baris yang melebihi batas panjang dengan kode E501. Setiap temuan dilaporkan lengkap dengan nama berkas, nomor baris, dan kode aturannya, sehingga perbaikan dapat dikerjakan satu per satu secara terarah.
# tidak-dijalankan
# memasang ruff, memeriksa proyek, lalu memformat seluruh berkasnya
pip install ruff
ruff check .
ruff format .Perintah ruff check . memeriksa seluruh berkas pada folder saat ini dan mengembalikan kode keluar selain nol apabila ada temuan, sehingga perintah ini dapat dipasangkan dengan CI untuk menggagalkan build yang melanggar aturan. Sebagian temuan dapat diperbaiki otomatis dengan ruff check --fix, misalnya impor yang tidak terpakai dihapus dan urutan impor disesuaikan. Perbaikan otomatis semacam ini aman untuk aturan yang perubahannya tidak menyentuh perilaku, sedangkan temuan lainnya tetap memerlukan keputusan manusia.
Cara kerja linter dalam bentuk mini#
Inti pekerjaan linter adalah membaca berkas baris demi baris dan membandingkan setiap baris dengan sekumpulan aturan. Pemeriksa berikut meniru prinsip tersebut dalam bentuk paling sederhana, yaitu memeriksa spasi di akhir baris dan baris yang melebihi 79 karakter, dua aturan bawaan PEP 8 yang paling sering muncul.
"""Pemeriksa gaya mini yang meniru cara kerja linter."""
import sys
from pathlib import Path
def periksa(berkas: Path) -> list[str]:
"""Mengembalikan daftar temuan gaya untuk satu berkas."""
temuan = []
for nomor, baris in enumerate(berkas.read_text(encoding="utf-8").splitlines(), start=1):
if baris != baris.rstrip():
temuan.append(f"{nomor}: spasi di akhir baris")
if len(baris) > 79:
temuan.append(f"{nomor}: baris melebihi 79 karakter")
return temuan
for nama in sys.argv[1:]:
for temuan in periksa(Path(nama)):
print(f"{nama}: {temuan}")# membuat berkas contoh dengan dua pelanggaran gaya
printf 'nilai = [10, 20, 30] \nkata = "kata yang sangat panjang sehingga barisnya melewati batas tujuh puluh sembilan karakter"\n' > contoh-gaya.py
# memeriksa berkas contoh dengan pemeriksa mini
python3 periksa_mini.py contoh-gaya.pycontoh-gaya.py: 1: spasi di akhir baris
contoh-gaya.py: 2: baris melebihi 79 karakterLinter sungguhan bekerja dengan prinsip yang sama, tetapi kode yang diperiksa diuraikan terlebih dahulu menjadi pohon sintaks sehingga aturan dapat melihat struktur program, bukan hanya teksnya. Jumlah aturannya juga jauh lebih banyak, dan keluarannya berformat seragam yang dapat dibaca editor maupun alat CI.
Hook pre-commit#
Git menjalankan hook pada kejadian tertentu, dan hook pre-commit dipanggil tepat sebelum commit dibuat. Kerangka pre-commit mengelola daftar hook tersebut dari satu berkas konfigurasi, sehingga alat pemformatan dan linter berjalan konsisten pada komputer setiap anggota tim tanpa pengaturan ulang. Konfigurasi berikut mengaktifkan ruff dan ruff-format sebagai dua hook yang diambil dari repositori resmi ruff.
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
hooks:
- id: ruff
- id: ruff-format# tidak-dijalankan
# memasang kerangka pre-commit dan mengaitkannya dengan repositori Git
pip install pre-commit
pre-commit install
# menjalankan seluruh hook secara manual atas semua berkas
pre-commit run --all-filesSaat git commit dijalankan, kerangka pre-commit memanggil ruff terlebih dahulu. Apabila ruff check menemukan pelanggaran, commit dibatalkan dan temuan ditampilkan, sehingga kode yang tidak lolos pemeriksaan tidak pernah masuk ke sejarah. Commit baru hanya dibuat ketika seluruh hook selesai tanpa temuan, sebagaimana digambarkan diagram berikut.
Kesalahan umum#
Kesalahan pertama adalah memperlakukan linter sebagai alat yang dijalankan sekali sebelum serah terima. Aturan yang hanya ditegakkan sesaat cepat terabaikan, dan kode yang melanggar gaya kembali masuk tanpa terdeteksi. Penegakan harus otomatis dan berulang, misalnya melalui hook pre-commit, sehingga hasilnya tidak bergantung pada disiplin perorangan.
Kesalahan kedua adalah membungkam temuan dengan komentar # noqa di setiap baris yang dilaporkan. Komentar itu menonaktifkan aturan pada barisnya tanpa menjelaskan alasannya, sehingga pola berisiko ikut lolos bersama pelanggaran gaya yang memang tidak berbahaya. Komentar tersebut dipakai hanya pada baris yang benar-benar membutuhkannya dan disertai penjelasan singkat, sedangkan temuan lainnya diperbaiki.
Kesalahan ketiga adalah menggabungkan pemformatan seluruh proyek dengan perubahan logika dalam satu commit. Diff yang dihasilkan membengkak, sehingga review sulit membedakan penyusunan ulang baris dari perubahan perilaku. Pemformatan besar-besaran dikerjakan dalam commit tersendiri sebelum pekerjaan logika dimulai.
Ringkasan#
- Formatter menulis ulang kode mengikuti aturan bentuk yang tetap, sedangkan linter melaporkan pelanggaran gaya dan pola berisiko tanpa mengubah perilaku program.
- ruff menyatukan kedua tugas melalui
ruff formatdanruff check, dan sebagian temuan dapat diperbaiki otomatis dengan--fix. - Linter membaca berkas baris demi baris lalu membandingkannya dengan aturan, sebagaimana ditiru pemeriksa mini pada topik ini.
- Hook pre-commit menjalankan pemformatan dan linting otomatis sebelum setiap commit dibuat, sehingga kode yang tidak lolos tidak pernah masuk sejarah.
Referensi#
- Ruff documentation — Astral — Dokumentasi resmi ruff untuk aturan linting, subperintah format, dan integrasi pre-commit.
- Black documentation — Black — Gaya pemformatan black yang menjadi acuan kompatibilitas ruff format.
- pre-commit — pre-commit — Situs resmi kerangka pre-commit beserta contoh konfigurasinya.
- PEP 8 – Style Guide for Python Code — Python Software Foundation — Konvensi gaya yang menjadi dasar sebagian besar aturan linter Python.