Format Dokumen Pengajaran & Panduan Siswa
BINUS University @ Bekasi SMAS St. John Pertemuan 16 dari 17

MODUL 16 — Final Project Development

Ekstrakurikuler CSSE: Computer Science & Software Engineering (Python)

Jenjang Peserta Siswa SMA (Kelas 10–12)
Alokasi Waktu 120 Menit
Fokus Materi while True menu, list[dict], def modular, file I/O, try-except
Target Selesai Aplikasi CLI berjalan: menu 5 opsi, data tersimpan di list[dict] dan ke file, minimal 4 fitur + statistik
Tools VS Code & Python (Run ▶)
Prioritas sesi: Wajib: aplikasi CLI "Pengelola Data" dengan menu while True (Lihat, Tambah, Cari, Hapus, Statistik, Keluar), data di list[dict], kode modular per fungsi, simpan & load ke file, validasi try-except — baseline ini adalah kriteria lulus (B). Pilih 1 domain: Nilai Siswa, Perpustakaan, Kasir, Kontak, atau Todo.
Materi pengayaan (opsional jika waktu cukup)

Level stretch untuk A: edit/update data, sorting dengan sorted(), statistik max/min/rata-rata lebih kaya, atau laporan otomatis ke file terpisah.

1. Tujuan Pembelajaran

  1. Memilih domain proyek dan menetapkan scope yang realistis untuk satu sesi kerja (struktur dict-nya jelas).
  2. Merancang alur aplikasi berbasis menu (flowchart menu + daftar fungsi) sebelum mulai coding.
  3. Membangun menu while True dengan 5 opsi + Keluar sebagai kerangka utama aplikasi.
  4. Menyimpan banyak data dalam list[dict] dan menambah/menghapus isinya lewat fungsi.
  5. Menyusun kode secara modular: satu fungsi untuk satu menu (tampilkan_data(), tambah_data(), dst.).
  6. Menerapkan file I/O: load saat program dibuka, save setiap kali data berubah.
  7. Melindungi program dengan try-except untuk input angka dan file yang tidak ada.
  8. Menguji sendiri semua cabang menu (termasuk kasus "data tidak ditemukan") dan mengecek diri terhadap rubrik.

2. Peta Jalan 17 Pertemuan

Hari ini siswa menempuh barisan ke-16 dari 17 — 94% perjalanan:

[ 01-02 ] Fondasi: konsep program, algoritma, flowchart [ 03-05 ] Mulai coding: print, variabel, input/output [ 06-07 ] Operator & percabangan if/elif/else [ 08 ] Mini Project 1: Decision Making [ 09 ] Looping / Perulangan [ 10 ] Nested Loop & Pattern Programming [ 11-13 ] List, Functions, String [ 14 ] Mini Project 2: Simple App [ 15 ] AI-Assisted Coding <-- SUDAH LEWAT [ 16-17 ] Final Project: Development & Presentation <-- HARI INI (120 Menit)

3. Rundown Waktu Terperinci (120 Menit)

WaktuBlokAktivitas
10'PembukaCover, tujuan sesi, rekap Sesi 15 (prompt KBT + verifikasi — AI boleh dipakai sebagai asisten, verifikasi tetap wajib)
15'Finalisasi idePilih 1 dari 5 domain (Nilai Siswa / Perpustakaan / Kasir / Kontak / Todo), tetapkan field dict-nya, tulis scope realistis: "1 fitur selesai sempurna daripada 5 fitur setengah jadi"
20'Rencana fiturFlowchart menu + daftar fungsi (1 menu = 1 fungsi); urutan kerja: kerangka menu → tambah → lihat → cari → hapus → statistik → file I/O
60'Kerja coding bertahapBangun fitur per fitur: menu while True jalan dulu, lalu tambah → lihat → cari → hapus → statistik, tutup dengan load/save file + try-except; guru berkeliling dampingi individu
10'Self-testUji semua cabang: tambah dengan input huruf di kolom angka, cari nama yang tidak ada, hapus data kosong, keluar — data masih ada setelah program ditutup-dibuka?
5'Checklist rubrikCek cepat terhadap rubrik: Fungsi jalan 30%, Struktur 25%, Logika 20%, Demo & Penjelasan 15%, Kreativitas 10% — catat yang belum, selesaikan di rumah bila perlu

4. Pedagogi & Penjelasan Konsep

A. Aplikasi Menu = Restoran dengan Pelayan

Analogi: aplikasimu itu restoran. while True adalah pelayan yang selalu standby di meja: datang saat dipanggil, catat pesanan, kembali menunggu — sampai tamu bilang "sudah dulu" (pilihan Keluar → break). list[dict] adalah dapur tempat semua bahan tersimpan; setiap dict satu piring berisi padanan padat: {"nama": "Budi", "nilai": 85}. Dan tiap menu punya juragan masak sendiri — itulah fungsi modular: satu menu, satu koki, satu tanggung jawab. Kalau pesanan aneh datang (input huruf di kolom nilai), koki tidak panik — dia punya prosedur darurat try-except.

B. Scope Realistis — 1 Fitur Sempurna Mengalahkan 5 Fitur Setengah Jadi

Jebakan terbesar hari ini bukan kode sulit, tapi nafsu fitur: tiba-tiba mau bikin login, gambar, sampai database. Padahal rubrik menilai fungsi yang jalan, bukan daftar mimpi. Aturan emasnya: satu fitur selesai sempurna lebih berharga daripada lima fitur setengah jadi. Urutkan pekerjaan sebagai tangga: menu jalan dulu (walau masih kosong) → Tambah → Lihat → Cari → Hapus → Statistik → file. Setiap anak tangga harus di-Run ▶ sebelum naik. Kalau waktu menipis, kamu berhenti di anak tangga mana pun dengan aplikasi yang tetap jalan — bukan di tengah lima fitur yang semuanya error.

C. Data Harus Selamat — Load di Awal, Save Tiap Berubah

List hidup di memori: program ditutup, hilang semua — seperti papan tulis terhapus tiap jam istirahat. File adalah buku catatan yang tersimpan di disk. Kontraknya cuma dua: load_file() dipanggil sekali di awal program, simpan_file() dipanggil setiap kali data berubah (setelah tambah, hapus, atau edit). Lupa salah satu = data palsu di sesi berikutnya. Ini juga pola yang dipakai aplikasi sungguhan: draft chat-mu tersimpan karena ada save di tiap perubahan.

D. Error Itu Alarm — try-except Adalah Alarm yang Kamu Pasang Sendiri

Semester ini siswa sudah sering dengar alarm: ValueError dari int(input()) saat user mengetik "lima", IndexError dari list kosong. Bedanya hari ini: kita tidak cuma mendengar alarm, tapi memasangnya sendiri dengan try-except — "kalau user nakal, jangan crash; tanya ulang". Error tetap bukan aib: aplikasi yang tahan-banting justru dibangun dari daftar error yang sudah ditangani. Setiap except yang kamu tulis hari ini adalah bukti kamu sudah pernah jatuh di situ — dan itu nilai plus saat demo Q&A minggu depan.

Catatan pengajar: pastikan scope realistis; bantu siswa memecah jadi langkah kecil (dari kurikulum resmi). Ingatkan terus load di awal & save tiap tambah/hapus. Siswa yang belum siap dengan file boleh fallback ke list dulu — menu + list[dict] yang jalan tetap lebih baik daripada file yang error semua.

5. Panduan Praktik Langkah demi Langkah

Langkah 1: Finalisasi Ide & Scope (15 menit)

Siswa pilih satu domain dan tulis field dict-nya di papan/kertas sebelum menyentuh kode:

Domain (pilih 1)Struktur dict-nya
1. Sistem Nilai Siswa (default demo){"nama": "Budi", "nilai": 85} + turunkan huruf & lulus/tidak saat tampil
2. Perpustakaan Mini{"judul": "...", "penulis": "...", "status": "tersedia"}
3. Kasir/Inventory Warung (challenge){"barang": "...", "harga": 5000, "stok": 12} + cetak struk
4. Kontak/Buku Alamat{"nama": "...", "hp": "...", "email": "..."}
5. Todo/Agenda Harian{"tugas": "...", "deadline": "...", "status": "belum"}

Diskusi scope cepat: fitur mana yang wajib (4 fitur + statistik), mana yang ditunda ke stretch? Tulis kalimat ini di kertas kerja: "Aplikasiku bernama ___, datanya ___, fitur wajibnya ___."

Langkah 2: Rencana Fitur — Flowchart Menu (20 menit)

Gambar flowchart kecil: Mulai → load_file() → tampilkan menu → baca pilihan → cabang ke fungsi → kembali ke menu (loop) → Keluar = break. Lalu tulis daftar fungsi dengan kontrak satu baris per fungsi:

# Daftar fungsi (satu menu = satu fungsi):
def load_file():        ...   # baca data.txt -> list[dict] (kosong kalau file belum ada)
def simpan_file():      ...   # tulis list[dict] -> data.txt
def tampilkan_data():   ...   # cetak semua data rapi
def tambah_data():      ...   # minta input, validasi, append, save
def cari_data(kata):    ...   # hasil pencarian nama (lowercase, case-insensitive)
def hapus_data():       ...   # cari index, del, save
def statistik():        ...   # jumlah data, max, min, rata-rata

Kontrak satu baris ini adalah pengganti flowchart detail untuk yang lebih suka teks — yang penting ada gambar besar sebelum mengetik.

Langkah 3: Kerangka Menu Dulu (20 menit)

Mulai dari tulang punggung — menu yang bisa jalan walau semua fiturnya masih placeholder:

data = []   # list[dict] — dapur aplikasi

while True:
    print("\n=== APLIKASI NILAI SISWA ===")
    print("1. Lihat  2. Tambah  3. Cari  4. Hapus  5. Statistik  6. Keluar")
    pilihan = input("Pilih menu (1-6): ")

    if pilihan == "1":
        print("(fitur Lihat menyusul)")
    elif pilihan == "6":
        print("Sampai jumpa!")
        break
    else:
        print("Menu belum tersedia.")

# Output saat pilih 6:
# === APLIKASI NILAI SISWA ===
# 1. Lihat  2. Tambah  3. Cari  4. Hapus  5. Statistik  6. Keluar
# Pilih menu (1-6): 6
# Sampai jumpa!

Moment penting: Run ▶ sekarang. Menu ini muncul berulang dan berhenti rapi di 6 — kerangka aman sudah berdiri. Sisa pekerjaan tinggal mengisi kotak-kotaknya.

Langkah 4: Fitur Inti Satu per Satu (25 menit)

Isi dalam urutan tangga. Setiap fitur selesai → Run ▶ → uji → baru lanjut:

def tambah_data():
    while True:   # validasi: angka atau ulangi
        try:
            nilai = int(input("Nilai (0-100): "))
            break
        except ValueError:
            print("Harus angka! Contoh: 85")
    nama = input("Nama: ")
    data.append({"nama": nama, "nilai": nilai})
    print(f"Data {nama} ditambahkan.")

# Output:
# Nilai (0-100): lima
# Harus angka! Contoh: 85
# Nilai (0-100): 85
# Nama: Budi
# Data Budi ditambahkan.

Perhatikan pola while True + try-except: tanya berulang sampai input sah — jangan sampai satu huruf menjatuhkan seluruh aplikasi. Lanjutkan dengan cari_data() (pakai kata.lower() in item["nama"].lower() biar "budi" ketemu "Budi") dan hapus_data() (temukan dulu, baru del — kalau tidak ketemu, tampilkan pesan jujur).

Langkah 5: File I/O — Load & Save (15 menit)

Tutup aplikasi dengan memori permanen:

FILE = "data.txt"

def load_file():
    try:
        with open(FILE, "r", encoding="utf-8") as f:
            for baris in f:
                baris = baris.strip()
                if baris == "":
                    continue
                nama, nilai = baris.split(",")
                data.append({"nama": nama, "nilai": int(nilai)})
    except FileNotFoundError:
        print("File belum ada — mulai dengan data kosong.")

def simpan_file():
    with open(FILE, "w", encoding="utf-8") as f:
        for item in data:
            f.write(f"{item['nama']},{item['nilai']}\n")

# Output saat pertama kali jalan (belum ada data.txt):
# File belum ada — mulai dengan data kosong.

Panggil load_file() satu kali sebelum loop menu, dan simpan_file() di akhir tambah_data() serta hapus_data(). Uji penuhnya: tambah 1 data → tutup program → jalan lagi → data masih ada.

Langkah 6: Self-Test & Checklist Rubrik (15 menit)

Jalankan sendiri daftar uji berikut, centang satu per satu:

  1. Semua menu bisa dibuka dan kembali ke menu tanpa crash.
  2. Tambah dengan input huruf di kolom nilai → program menolak dengan sopan, tidak crash.
  3. Cari nama yang tidak ada → pesan jujur, bukan error.
  4. Hapus data saat list kosong → tidak crash.
  5. Keluar → buka lagi → data tetap ada (bukti file bekerja).
  6. Cek rubrik: Fungsi jalan 30% · Struktur kode 25% · Logika 20% · Demo & Penjelasan 15% · Kreativitas 10% — pilih 1 fungsi yang akan "dibanggakan" saat demo minggu depan.

6. Master Solution Code (kode.py — Sesi 16)

Kerangka aplikasi final project lengkap (domain contoh: Sistem Nilai Siswa — struktur sama persis untuk 4 domain lain, tinggal ganti field dict-nya). Simpan sebagai final_project.py dan jalankan:

# Final Project — Aplikasi Pengelola Data (Sistem Nilai Siswa)
# Baseline: menu while True + list[dict] + modular + file I/O + try-except

FILE = "data.txt"
data = []   # list[dict] — contoh: [{"nama": "Budi", "nilai": 85}]

def load_file():
    try:
        with open(FILE, "r", encoding="utf-8") as f:
            for baris in f:
                baris = baris.strip()
                if baris == "":
                    continue
                nama, nilai = baris.split(",")
                data.append({"nama": nama, "nilai": int(nilai)})
    except FileNotFoundError:
        print("File belum ada — mulai dengan data kosong.")

def simpan_file():
    with open(FILE, "w", encoding="utf-8") as f:
        for item in data:
            f.write(f"{item['nama']},{item['nilai']}\n")

def tampilkan_data():
    if len(data) == 0:
        print("Belum ada data.")
        return
    for i, item in enumerate(data, start=1):
        if item["nilai"] >= 75:
            status = "Lulus"
        else:
            status = "Remedial"
        print(f"{i}. {item['nama']} - nilai {item['nilai']} ({status})")

def tambah_data():
    nama = input("Nama: ")
    while True:
        try:
            nilai = int(input("Nilai (0-100): "))
            break
        except ValueError:
            print("Harus angka! Contoh: 85")
    data.append({"nama": nama, "nilai": nilai})
    simpan_file()
    print(f"Data {nama} ditambahkan.")

def cari_data(kata):
    hasil = []
    for item in data:
        if kata.lower() in item["nama"].lower():
            hasil.append(item)
    return hasil

def hapus_data():
    kata = input("Nama yang dihapus: ")
    ketemu = None
    for i, item in enumerate(data):
        if item["nama"].lower() == kata.lower():
            ketemu = i
            break
    if ketemu is None:
        print(f"Data '{kata}' tidak ditemukan.")
    else:
        del data[ketemu]
        simpan_file()
        print(f"Data '{kata}' dihapus.")

def statistik():
    if len(data) == 0:
        print("Belum ada data untuk dihitung.")
        return
    nilai = [item["nilai"] for item in data]
    rata = sum(nilai) / len(nilai)
    print(f"Jumlah data : {len(nilai)}")
    print(f"Nilai tertinggi : {max(nilai)}")
    print(f"Nilai terendah : {min(nilai)}")
    print(f"Rata-rata : {rata:.1f}")

# ---- Program utama ----
load_file()   # load sekali di awal

while True:
    print("\n=== APLIKASI NILAI SISWA ===")
    print("1. Lihat  2. Tambah  3. Cari  4. Hapus  5. Statistik  6. Keluar")
    pilihan = input("Pilih menu (1-6): ")

    if pilihan == "1":
        tampilkan_data()
    elif pilihan == "2":
        tambah_data()
    elif pilihan == "3":
        kata = input("Cari nama: ")
        hasil = cari_data(kata)
        if len(hasil) == 0:
            print(f"Tidak ada data dengan nama '{kata}'.")
        else:
            for item in hasil:
                print(f"Ketemu: {item['nama']} - {item['nilai']}")
    elif pilihan == "4":
        hapus_data()
    elif pilihan == "5":
        statistik()
    elif pilihan == "6":
        simpan_file()   # jaring pengaman terakhir sebelum keluar
        print("Sampai jumpa!")
        break
    else:
        print("Menu 1-6 saja!")

# Output harapan (skenario singkat):
# File belum ada — mulai dengan data kosong.
# === APLIKASI NILAI SISWA ===
# 1. Lihat  2. Tambah  3. Cari  4. Hapus  5. Statistik  6. Keluar
# Pilih menu (1-6): 2
# Nama: Budi
# Nilai (0-100): 85
# Data Budi ditambahkan.
# ...
# Pilih menu (1-6): 1
# 1. Budi - nilai 85 (Lulus)
# ...
# Pilih menu (1-6): 5
# Jumlah data : 1
# Nilai tertinggi : 85
# Nilai terendah : 85
# Rata-rata : 85.0
# ...
# Pilih menu (1-6): 6
# Sampai jumpa!

Penjelasan singkat: data dideklarasikan di atas sebagai satu-satunya sumber kebenaran; tiap fungsi membaca atau mengubahnya lalu simpan_file() menjamin kekal. cari_data() mengembalikan list hasil (bisa kosong — penelepon yang memutuskan pesannya), hapus_data() jujur saat tidak ketemu, dan try-except ganda menahan ValueError (input) sekaligus FileNotFoundError (file pertama kali). Ini baseline B penuh: menu loop + list[dict] + modular + file + validasi.

7. Troubleshooting Guide (Pegangan Guru)

Masalah Penyebab Tindakan Perbaikan
FileNotFoundError saat load, atau program crash saat pertama jalan load_file() dibaca sebelum file ada — tanpa try-except. Bungkus dengan try-except FileNotFoundError → "mulai dengan data kosong". File tercipta otomatis saat save pertama.
ValueError saat user mengetik huruf di kolom nilai int(input()) langsung tanpa penjagaan — "lima" meledak. Pola while True + try-except ValueError: tanya ulang sampai sah. Ini fitur, bukan tambalan.
Data hilang setelah program ditutup simpan_file() lupa dipanggil setelah tambah/hapus, atau hanya dipanggil saat keluar — keluar pakai Ctrl+C artinya tak pernah sampai. Kontrak save: panggil di dalam tiap fungsi yang mengubah data. Sesi 14 sudah belajar ini — ingatkan lagi.
Data lama muncul dua kali setelah load load_file() dipanggil dua kali (mis. saat restart menu), append menumpuk. load_file() hanya sekali, sebelum loop menu. Atau kosongkan data di awal load_file().
Menu tidak berhenti / pilihan "6" dianggap menu lain Perbandingan salah tipe: if pilihan == 6 padahal input() menghasilkan string "6". Bandingkan string dengan string (== "6") — konsisten, tanpa konversi. Cek juga break benar di dalam cabang Keluar.
NameError: fungsi tidak dikenal saat dipanggil Fungsi didefinisikan setelah loop menu, atau indentasi salah membuat def terinduk ke dalam fungsi lain. Semua def di bagian atas file, rata kiri. Python baca atas-ke-bawah: definisikan dulu, panggil kemudian.
Siswa kehabisan waktu, semua fitur setengah jadi Terlalu ambisius: tambah fitur baru sebelum yang lama stabil. Terapkan tangga: satu fitur selesai + di-Run ▶ baru naik. Kalau sempit, pilih 4 fitur wajib saja — file boleh menyusul (fallback list dulu).

8. Checklist Evaluasi Siswa

9. Jembatan ke Pertemuan Berikutnya (Sesi 17)

Aplikasimu hari ini sudah jalan — minggu depan giliran menjualnya. Sesi 17 adalah Demo Day: tiap kelompok presentasi 5–7 menit dengan alur Masalah → Fitur → Demo Live → 1 potongan kode dibanggakan → Q&A. Mulai sekarang pikirkan dua hal: fitur mana yang kamu jalankan live, dan fungsi mana yang kamu pilih untuk dijelaskan — yang bisa kamu jelaskan paling meyakinkan, bukan yang paling panjang. Rumah kerja yang sama, panggung yang berbeda.

# Cerita demo-mu nanti tinggal diisi seperti ini:
# Masalah : mencatat nilai kelas masih pakai kertas, sering hilang
# Fitur   : lihat, tambah, cari, hapus, statistik (5 menu!)
# Demo    : tambah "Budi" nilai 85 -> lihat -> statistik
# Kode    : def tambah_data() — try-except-nya melindungi dari input nakal
# Q&A     : "kalau 2 orang namanya sama, bagaimana?" — siap jawab!

Rubrik demo konsisten dengan hari ini: Fungsi jalan 30% · Struktur kode 25% · Logika 20% · Demo & Penjelasan 15% · Kreativitas 10%. Yang sempurna hari ini adalah modal terbesar minggu depan.