Proyek pipeline yang mulai dari satu skrip cepat berubah menjadi belasan berkas dalam hitungan minggu: skrip ekstraksi, transformasi, konfigurasi, berkas data sementara, lalu skrip perbaikan bernama final_v2.py. Tanpa tata letak yang disepakati, setiap anggota tim menyimpan berkas di tempat berbeda dan tidak ada yang yakin kode mana yang sedang berjalan di production. Struktur folder standar menyelesaikan masalah tersebut sebelum mulai: setiap jenis berkas punya rumahnya, kode teruji dapat dijalankan ulang, dan pendatang baru langsung tahu ke mana harus melihat.

Peta Folder Standar #

Berikut struktur proyek pipeline yang kita pakai sebagai patokan sepanjang course ini, ditampilkan dengan perintah tree dari dalam folder proyek:

text
.
├── README.md
├── config
│   └── etl.toml
├── data
│   ├── processed
│   └── raw
├── scripts
│   └── jalankan_uji.sh
├── src
│   └── etl
│       ├── ekstrak.py
│       └── muat.py
└── tests
    └── test_etl.py

9 directories, 6 files

Peran setiap bagian terpetakan sebagai berikut:

BagianIsiPeran
README.mdcara instalasi dan menjalankan pipelinepintu masuk bagi anggota tim baru
config/etl.toml, berkas .envpengaturan terpisah dari kode
data/raw/data mentah hasil ingestionarea baca-saja, tidak diubah manual
data/processed/hasil transformasikeluaran pipeline
src/kode Python proyekmodul yang diimpor pipeline
tests/pengujian pytestpenjaga perilaku kode
scripts/skrip pembantutugas sekali jalan seperti menjalankan uji

Pemisahan data/raw/ dan data/processed/ bukan formalitas: prinsip immutable raw data menyatakan data mentah tidak pernah diubah di tempat. Setiap perbaikan menghasilkan berkas baru di data/processed/, sehingga kita selalu dapat menelusuri ulang proses dari titik awal yang sama.

Modularitas di Dalam src #

Folder src/etl memecah pipeline menjadi modul kecil dengan satu tanggung jawab: ekstrak.py mengambil data dari sumber, muat.py menuliskan hasil ke tujuan. Isi kedua modul tersebut masih pendek di tahap ini:

python
def ekstrak(sumber):
    """Ambil data mentah dari sumber."""
    return []
python
def muat(data, tujuan):
    """Muat data hasil transformasi ke tujuan."""
    return len(data)

Ketika transformasi bertambah, kita cukup menambah berkas transform.py di samping keduanya — bukan menumpuk logika dalam satu berkas raksasa. Pengujian lalu mengimpor modul tersebut secara langsung:

python
from src.etl.ekstrak import ekstrak

def test_ekstrak_mengembalikan_daftar():
    hasil = ekstrak("contoh.csv")
    assert isinstance(hasil, list)

Perintah python3 -m pytest tests -v dijalankan dari akar proyek, dan Python menemukan paket src.etl karena eksekusi python3 -m memasukkan folder kerja ke jalur pencarian modul. Output yang Dihasilkan:

text
...
tests/test_etl.py::test_ekstrak_mengembalikan_daftar PASSED              [100%]

============================== 1 passed in 0.13s ===============================

Baris PASSED di atas disalin dari eksekusi nyata; baris ringkasan sesi di bagian awal keluaran dipangkas karena memuat detail lingkungan penulisan yang tidak relevan. Satu pengujian hijau tersebut membuktikan struktur folder sekaligus jalur impor bekerja.

Kapan Struktur Bertambah #

Struktur di atas tumbuh mengikuti kebutuhan, bukan sejak awal. Folder dags/ muncul ketika pipeline pindah ke Airflow; folder models/ muncul ketika transformasi pindah ke dbt; folder docker/ muncul ketika layanan dikemas ke container. Menahan diri dari struktur berlebih di awal sama pentingnya dengan menata ulang ketika proyek membesar — struktur terbaik adalah struktur yang seluruh timnya pahami.

Dokumentasi pytest untuk menulis pengujian yang baik tersedia di https://docs.pytest.org/ . Satu berkas masih menyimpan risiko besar di dalam struktur tersebut: .env yang berisi kredensial. Cara mengamankannya menjadi topik chapter Pengelolaan Secrets.