8 menit

Dari User Stories ke Skema Database: Metode Berpanduan AI

Pelajari metode praktis mengubah user stories, entitas, dan alur kerja menjadi skema database yang jelas, serta bagaimana penalaran AI membantu mengecek celah dan aturan.

Dari User Stories ke Skema Database: Metode Berpanduan AI

Apa yang Anda Bangun: Skema yang Cocok dengan Pekerjaan Nyata

Sebuah skema database adalah rencana bagaimana aplikasi Anda akan menyimpan hal-hal. Secara praktis, itu adalah:

  • Tabel: “wadah” informasi (Customers, Orders, Tickets)
  • Kolom (fields/atribut): detail yang Anda simpan tentang tiap hal (customer_name, order_date)
  • Relasi: bagaimana wadah terhubung (sebuah Order milik satu Customer; satu Customer bisa punya banyak Orders)

Ketika skema cocok dengan pekerjaan nyata, ia mencerminkan apa yang orang sebenarnya lakukan—membuat, meninjau, menyetujui, menjadwalkan, menugaskan, membatalkan—bukan hanya apa yang terdengar rapi di papan tulis.

Mengapa mulai dari user stories?

User stories dan acceptance criteria menjelaskan kebutuhan nyata dengan bahasa biasa: siapa melakukan apa, dan apa arti “selesai”. Jika Anda menggunakan itu sebagai sumber, skema cenderung tidak melewatkan detail penting (mis. “kita harus melacak siapa yang menyetujui pengembalian dana” atau “sebuah booking bisa dijadwal ulang beberapa kali”).

Mulai dari stories juga membuat Anda jujur tentang lingkup. Jika itu tidak ada di stories (atau workflow), perlakukan sebagai opsional daripada diam-diam membuat model rumit “untuk berjaga-jaga.”

Apa yang bisa dan tidak bisa dilakukan AI di sini

AI bisa membantu Anda bergerak lebih cepat dengan:

  • Menarik kandidat entitas (hal penting dalam stories)
  • Menyarankan kolom yang diimplikasikan oleh acceptance criteria (timestamp, status, referensi)
  • Menemukan relasi dan celah yang mungkin (“Anda menyebut persetujuan tapi tidak menyimpan approver”)

AI tidak dapat diandalkan untuk:

  • Mengetahui aturan bisnis tersembunyi atau edge case yang tidak Anda tulis
  • Memilih tingkat detail “yang benar” tanpa pertukaran (sederhana vs fleksibel)
  • Menjamin skema cocok untuk kebutuhan reporting, keamanan, atau kepatuhan Anda

Anggap AI sebagai asisten yang kuat, bukan pengambil keputusan.

Jika Anda ingin mengubah asisten itu menjadi momentum, platform vibe-coding seperti Koder.ai bisa membantu Anda beralih dari keputusan skema ke aplikasi React + Go + PostgreSQL yang bekerja lebih cepat—sambil tetap menjaga Anda mengontrol model, constraint, dan migrasi.

Atur ekspektasi: iteratif, bukan sekali jadi

Desain skema adalah loop: draft → uji terhadap stories → temukan data yang hilang → perbaiki. Tujuan bukan keluaran sempurna pertama; melainkan model yang bisa Anda lacak kembali ke setiap user story dan dengan yakin mengatakan: “Ya, kita bisa menyimpan semua yang dibutuhkan workflow ini—dan kita bisa jelaskan kenapa setiap tabel ada.”

Input: User Stories, Acceptance Criteria, dan Contoh Nyata

Sebelum Anda mengubah requirement menjadi tabel, pastikan jelas apa yang Anda modelkan. Skema yang baik jarang mulai dari kertas kosong—ia mulai dari pekerjaan konkret yang orang lakukan dan bukti yang Anda perlukan nanti (layar, output, dan edge case).

Input tipikal yang ingin Anda satukan

User stories adalah judul, tapi tidak cukup sendirian. Kumpulkan:

  • User stories + peran (siapa melakukan apa dan mengapa)
  • Acceptance criteria (aturan “harus benar”)
  • Form/screen (kolom yang diisi, dipilih, atau dilihat pengguna)
  • Laporan/ekspor (apa yang perlu disarikan, dikelompokkan, difilter)
  • Contoh nyata (sample orders, invoices, tickets, kalender—apa pun yang representatif)

Jika Anda menggunakan AI, input-input ini menjaga model tetap relevan. AI bisa mengusulkan entitas dan kolom dengan cepat, tapi ia butuh artefak nyata agar tidak menciptakan struktur yang tidak cocok dengan produk Anda.

Acceptance criteria: sumber tersembunyi constraint

Acceptance criteria sering mengandung aturan database paling penting, bahkan ketika tidak menyebut data secara eksplisit. Cari pernyataan seperti:

  • “Email harus unik” (keunikan)
  • “Status bisa Draft, Submitted, Approved” (nilai yang diizinkan)
  • “Hanya manager yang bisa menyetujui” (permissions, mungkin kolom audit)
  • “Tidak bisa menghapus invoice yang punya pembayaran” (aturan referensial)

Kesalahan umum yang harus diperbaiki lebih awal

Story yang kabur (“Sebagai user, saya bisa mengelola projects”) menyembunyikan banyak entitas dan workflow. Kesenjangan lain yang sering muncul adalah edge case yang hilang seperti pembatalan, retry, refund parsial, atau reasignment.

Checklist cepat kualitas story (sebelum memodelkan)

  • Aktor/peran eksplisit.
  • Objek spesifik (bukan “data” atau “hal-hal”).
  • Minimal satu contoh nyata.
  • Acceptance criteria termasuk validasi dan batasan.
  • Kasus error dan “bagaimana jika” disebutkan (atau didefer secara eksplisit).

Langkah 1 — Ekstrak Entitas dari Stories (Kata Benda)

Sebelum berpikir tentang tabel atau diagram, baca user stories dan sorot kata benda. Dalam penulisan requirements, kata benda biasanya menunjuk ke “hal” yang harus diingat sistem—ini sering menjadi entitas dalam skema Anda.

Model mental cepat: kata benda menjadi entitas, sedangkan kata kerja menjadi aksi atau workflow. Jika story mengatakan “Seorang manager menugaskan teknisi pada sebuah job,” entitas yang mungkin adalah manager, technician, dan job—dan “menugaskan” menunjukkan relasi yang akan Anda modelkan nanti.

Cara mengetahui apakah sebuah kata benda memang entitas

Tidak setiap kata benda pantas jadi tabel. Sebuah kata benda adalah kandidat kuat entitas ketika:

  • Punya identitas sendiri: Anda bisa menunjuk satu instance spesifik (Job #1042, Customer A).
  • Berubah seiring waktu: memiliki lifecycle (job pindah dari scheduled → completed).
  • Digunakan di banyak tempat: beberapa stories merujuknya, atau banyak workflow menyentuhnya.

Jika sebuah kata benda muncul hanya sekali, atau hanya menjelaskan sesuatu lain (“tombol merah”, “Jumat”), mungkin bukan entitas.

Atribut vs entitas terpisah (tes “Alamat” dan “Tag”)

Kesalahan umum adalah mengubah setiap detail menjadi tabel. Gunakan aturan praktis ini:

  • Jika itu satu nilai yang menggambarkan sebuah hal, biasanya atribut (mis. Customer.phone_number).
  • Jika itu boleh berulang, dibagikan, atau terstruktur, sering kali entitas terpisah.

Dua contoh klasik:

  • Alamat: Jika Anda menyimpan alamat pengiriman dan tagihan, menyimpan riwayat, atau menggunakan ulang alamat antar customer/locasi, Address kemungkinan besar entitas sendiri. Jika Anda hanya butuh satu alamat pos dan tak pernah pakai ulang, bisa jadi atribut.
  • Tag: Tag hampir selalu entitas sendiri karena bisa berulang dan banyak-ke-banyak (satu Job punya banyak Tags; satu Tag berlaku untuk banyak Jobs).

Menggunakan AI untuk menyarankan kandidat entitas (dengan hati-hati)

AI bisa mempercepat penemuan entitas dengan memindai stories dan mengembalikan daftar draf kata benda yang dikelompokkan berdasarkan tema (orang, item kerja, dokumen, lokasi). Prompt berguna: “Ekstrak kata benda yang mewakili data yang harus disimpan, dan grupkan sinonim/duplikat.”

Anggap output sebagai titik awal, bukan jawaban final. Ajukan follow-up seperti:

  • “Mana yang punya lifecycle atau perlu ID sendiri?”
  • “Mana yang sebenarnya status, kategori, atau atribut?”
  • “Apakah ada sinonim (mis. ‘client’ vs ‘customer’)?”

Tujuan Langkah 1 adalah daftar entitas pendek dan bersih yang bisa Anda pertahankan dengan menunjuk kembali ke stories nyata.

Langkah 2 — Ubah Detail menjadi Kolom (Hal yang Harus Kita Simpan)

Setelah menamai entitas (seperti Order, Customer, Ticket), pekerjaan berikutnya adalah menangkap detail yang akan Anda butuhkan nanti. Di database, detail itu adalah kolom (juga disebut atribut)—pengingat yang tidak boleh sistem lupa.

Cara memilih kolom (tanpa menebak)

Mulailah dari user story, lalu baca acceptance criteria seperti daftar cek apa yang harus disimpan.

Jika requirement mengatakan “Pengguna bisa memfilter order berdasarkan tanggal pengiriman,” maka delivery_date bukan opsional—ia harus ada sebagai kolom (atau bisa diturunkan dengan andal dari data lain). Jika dikatakan “Tunjukkan siapa yang menyetujui permintaan dan kapan,” Anda kemungkinan perlu approved_by dan approved_at.

Tes praktis: Apakah seseorang akan membutuhkan ini untuk menampilkan, mencari, mengurutkan, mengaudit, atau menghitung sesuatu? Jika ya, kemungkinan besar itu kolom.

Aturan sederhana untuk kolom yang bersih

  • Simpan nilai atomik: simpan “First name” dan “Last name” terpisah jika Anda akan mencari atau mengurutkan berdasarkan mereka. Hindari menggabungkan banyak nilai dalam satu kolom (mis. “merah, biru”).
  • Gunakan tipe konsisten: tanggal sebagai tipe tanggal, uang sebagai decimal, boolean sebagai true/false—jangan campur format seperti “$10”, “10 USD”, dan “10”.
  • Hindari teks yang diduplikasi: jangan menyalin alamat customer ke setiap baris order. Simpan sekali di tempat yang tepat dan referensikan.

Kosakata terkontrol: status, tipe, dan kategori

Banyak story menyebut kata seperti “status,” “type,” atau “priority.” Perlakukan ini sebagai kosakata terkontrol—set nilai yang dibatasi.

Jika set kecil dan stabil, enum sederhana bisa bekerja. Jika bisa berkembang, perlu label, atau butuh permissions (mis. dikelola admin), gunakan tabel lookup terpisah (mis. status_codes) dan simpan referensinya.

Ini cara stories berubah menjadi kolom yang dapat dipercaya—dapat dicari, dilaporkan, dan sulit salah masuk.

Langkah 3 — Hubungkan Entitas dengan Relasi

Setelah Anda mendaftar entitas (User, Order, Invoice, Comment, dll.) dan mendraf kolomnya, langkah berikut adalah menghubungkannya. Relasi adalah lapisan “bagaimana hal-hal ini berinteraksi” yang diimplikasikan oleh stories Anda.

Tiga bentuk relasi (dalam bahasa biasa)

Satu-ke-satu (1:1) berarti “satu hal punya tepat satu hal lain.”

  • Frase story: “Setiap user mempunyai satu profile.”
  • Ide model: UserProfile (sering kali Anda bisa gabungkan kecuali ada alasan memisahkan).

Satu-ke-banyak (1:N) berarti “satu hal bisa punya banyak hal lain.” Ini paling umum.

  • Frase story: “Seorang user bisa punya banyak orders.”
  • Ide model: UserOrder (simpan user_id di Order).

Banyak-ke-banyak (M:N) berarti “banyak hal bisa berhubungan dengan banyak hal.” Ini perlu tabel tambahan.

  • Frase story: “Sebuah order bisa berisi banyak produk, dan sebuah produk bisa ada di banyak order.”

Banyak-ke-banyak: trik tabel join

Database tidak menyukai menyimpan “daftar product ID” di Order tanpa masalah ke depan (pencarian, pembaruan, pelaporan). Sebaiknya buat tabel join yang mewakili relasi itu.

Contoh:

  • Order
  • Product
  • OrderItem (tabel join)

OrderItem biasanya berisi:

  • order_id
  • product_id
  • detail dari story seperti quantity, unit_price, discount

Perhatikan bagaimana detail story (mis. “quantity”) sering kali milik relasi, bukan entitas manapun.

Wajib vs. opsional (tanpa jargon)

Stories juga memberitahu apakah koneksi itu wajib atau kadang tidak ada.

  • “Sebuah order harus milik user” → setiap Order butuh user_id (jangan biarkan kosong).
  • “Seorang user mungkin punya nomor telepon” → phone bisa kosong.
  • “Order bisa punya shipping address (jika barang fisik)” → shipping_address_id mungkin kosong untuk order digital.

Pengecekan cepat: jika story memberi kesan Anda tidak bisa membuat record tanpa link, perlakukan sebagai wajib. Jika story mengatakan “bisa”, “mungkin”, atau memberi pengecualian, perlakukan sebagai opsional.

Ubah kalimat story menjadi kalimat relasi

Saat membaca story, tulis ulang sebagai pasangan sederhana:

  • “Seorang user bisa meninggalkan banyak komentar” → User 1:N Comment
  • “Sebuah comment milik satu user” → Comment N:1 User

Lakukan ini untuk setiap interaksi dalam stories. Pada akhirnya, Anda akan punya model terhubung yang mencerminkan bagaimana pekerjaan terjadi—sebelum membuka alat diagram ER.

Langkah 4 — Gunakan Workflow untuk Menemukan Status, Event, dan Celah

Ubah skema tanpa khawatir
Iterasi dengan aman menggunakan snapshot dan rollback saat Anda menyesuaikan tabel dan batasan.

User stories memberi tahu apa yang diinginkan orang. Workflow menunjukkan bagaimana pekerjaan bergerak, langkah demi langkah. Menerjemahkan workflow ke data adalah salah satu cara tercepat untuk menangkap masalah "kita lupa menyimpan itu"—sebelum membangun apa pun.

Mulai dengan workflow sederhana

Tulis alur kerja sebagai urutan aksi dan perubahan status. Misalnya:

  • Buat permintaan → Draft
  • Submit permintaan → Submitted
  • Manager review → Approved atau Rejected
  • Jika disetujui, pekerjaan dijadwalkan → In progress
  • Selesai → Done

Kata-kata yang diberi tebal itu sering menjadi field status (atau tabel kecil “state”), dengan nilai yang jelas diizinkan.

Workflow mengungkap kolom yang hilang

Saat Anda melangkah melalui tiap langkah, tanya: “Apa yang perlu kita ketahui nanti?” Workflow biasanya mengungkap kolom seperti:

  • timestamp: submitted_at, approved_at, completed_at
  • kepemilikan: created_by, assigned_to, approved_by
  • alasan/konteks: rejection_reason, approval_note
  • urutan: sequence untuk proses multi-langkah

Jika workflow termasuk menunggu, eskalasi, atau serah-terima, biasanya Anda butuh setidaknya satu timestamp dan satu kolom “siapa yang pegang sekarang”.

Workflow mengungkap tabel yang hilang

Beberapa langkah workflow bukan hanya kolom—mereka struktur data terpisah:

  • Audit log / history untuk “siapa mengubah status kapan”
  • Approvals untuk persetujuan multi-approver atau conditional
  • Attachments saat pengguna mengunggah file selama langkah
  • Comments bila diskusi bagian dari proses

Menggunakan AI untuk cross-check celah

Berikan AI kedua hal: (1) user stories + acceptance criteria, dan (2) langkah-langkah workflow. Minta AI mencantumkan setiap langkah dan mengidentifikasi data yang diperlukan untuk tiap langkah (state, aktor, timestamp, output), lalu soroti persyaratan yang tidak didukung oleh kolom/tabel saat ini.

Di platform seperti Koder.ai, "cek celah" ini jadi praktis karena Anda bisa iterasi cepat: sesuaikan asumsi skema, regenerasi scaffolding, dan terus bergerak tanpa harus melalui boilerplate manual panjang.

Kunci, Keunikan, dan Constraint Dasar (Tanpa Jargon)

Saat Anda mengubah user stories menjadi tabel, Anda tidak hanya mendaftar kolom—Anda juga memutuskan bagaimana data tetap teridentifikasi dan konsisten dari waktu ke waktu.

Primary key: kartu identitas stabil untuk setiap baris

Primary key mengidentifikasi unik satu record—anggap sebagai kartu ID permanen baris.

Kenapa setiap baris butuh satu: stories mengimplikasikan update, referensi, dan history. Jika sebuah story mengatakan “Support bisa melihat order dan mengeluarkan refund,” Anda perlu cara stabil menunjuk order itu—meski customer ganti email, alamat diedit, atau status order berubah.

Dalam praktik, ini biasanya id internal (angka atau UUID) yang tak berubah.

Foreign key: pointer antar tabel

Foreign key adalah cara satu tabel menunjuk aman ke tabel lain. Jika orders.customer_id merefer customers.id, database bisa menegakkan bahwa setiap order punya customer yang nyata.

Ini cocok dengan story seperti “Sebagai user, saya bisa melihat invoice saya.” Invoice tidak mengambang; ia terikat ke customer (dan sering ke order atau subscription).

Aturan keunikan: ubah “harus unik” menjadi enforcement

User stories sering menyembunyikan aturan keunikan:

  • “Users mendaftar dengan email” → terapkan email unik (atau unik per tenant jika mendukung multi-akun).
  • “Finance mencari berdasarkan nomor invoice” → terapkan invoice_number unik.

Aturan ini mencegah duplikat membingungkan yang muncul nanti sebagai “bug data.”

Indexing (tingkat tinggi): buat lookup umum jadi cepat

Index mempercepat pencarian seperti “temukan customer berdasarkan email” atau “daftar orders per customer.” Mulailah dengan index yang sesuai query paling umum dan aturan keunikan.

Yang ditunda: indexing berat untuk laporan jarang atau filter spekulatif. Tangkap kebutuhan itu di stories, validasi skema dulu, lalu optimalkan berdasarkan penggunaan nyata dan bukti slow-query.

Jaga Konsistensi Data: Checklist Normalisasi Praktis

Bangun dari cerita pengguna Anda
Ubah cerita pengguna menjadi aplikasi React, Go, dan PostgreSQL yang berfungsi dengan Koder.ai.

Normalisasi punya satu tujuan sederhana: mencegah duplikasi yang bertentangan. Jika fakta yang sama bisa disimpan di dua tempat, nanti akan berbeda (dua ejaan, dua harga, dua alamat “terkini”). Skema ternormal menyimpan setiap fakta sekali, lalu mereferensikannya.

Checklist cepat yang bisa Anda jalankan pada skema draf

1) Waspadai grup berulang

Jika Anda melihat pola seperti “Phone1, Phone2, Phone3” atau “ItemA, ItemB, ItemC”, itu sinyal untuk tabel terpisah (mis. CustomerPhones, OrderItems). Grup berulang menyulitkan pencarian, validasi, dan skala.

2) Jangan salin nama/detail yang sama ke banyak tabel

Jika CustomerName muncul di Orders, Invoices, dan Shipments, Anda punya banyak sumber kebenaran. Simpan detail customer di Customers, dan simpan hanya customer_id di tempat lain.

3) Hindari “banyak kolom untuk hal yang sama”

Kolom seperti billing_address, shipping_address, home_address bisa wajar jika memang konsep berbeda. Tapi jika sebenarnya Anda memodelkan “banyak alamat dengan tipe berbeda”, gunakan tabel Addresses dengan field type.

4) Pisahkan lookup dari teks bebas

Jika pengguna memilih dari set yang diketahui (status, kategori, role), modelkan secara konsisten: enum terbatas atau tabel lookup. Ini mencegah perbedaan seperti “Pending” vs “pending” vs “PENDING.”

5) Periksa bahwa setiap kolom non-ID bergantung pada hal yang tepat

Pengecekan intuitif: dalam sebuah tabel, jika sebuah kolom menjelaskan sesuatu selain entitas utama tabel, kemungkinan besar kolom itu harus berada di tempat lain. Contoh: Orders tidak seharusnya menyimpan product_price kecuali maksudnya “harga saat order” (snapshot historis).

Kapan denormalisasi boleh (sebagai pilihan nanti)

Kadang Anda memang menyimpan duplikat dengan sengaja:

  • Reporting/performansi: total pra-agregasi atau tabel ringkasan.
  • Caching: nilai terhitung disimpan untuk menghindari perhitungan berat.
  • Audit/riwayat: menyalin “nama saat pembelian” untuk mempertahankan realitas masa lalu.

Intinya membuatnya disengaja: dokumentasikan field mana sumber kebenaran dan bagaimana salinan diperbarui.

Di mana AI membantu—dan di mana manusia yang memutuskan

AI bisa menandai duplikasi mencurigakan (kolom berulang, nama kolom mirip, field status yang tidak konsisten) dan menyarankan pemisahan menjadi tabel. Manusia tetap memilih trade-off—kesederhanaan vs fleksibilitas vs performa—berdasarkan bagaimana produk benar-benar digunakan.

Disimpan vs Dihitung: Apa yang Layak di Database

Aturan berguna: simpan fakta yang tidak bisa Anda buat ulang dengan andal nanti; hitung sisanya.

Disimpan vs dihitung (derived)

Data tersimpan adalah sumber kebenaran: line items, timestamp event, perubahan status, siapa melakukan apa. Data dihitung dihasilkan dari fakta itu: total, counter, flag seperti “is overdue”, dan rollup seperti “inventory saat ini”.

Jika dua nilai bisa dihitung dari fakta yang sama, sebaiknya simpan faktanya dan hitung sisanya untuk menghindari kontradiksi.

Kenapa menyimpan nilai turunan menyebabkan ketidakcocokan

Nilai turunan berubah saat inputnya berubah. Jika Anda menyimpan input dan hasil turunan, Anda harus menjaga keduanya sinkron di seluruh workflow dan edge case (edit, refund, partial shipment, perubahan bertanggal mundur). Satu pembaruan yang terlewatkan, dan database mulai menceritakan dua kisah berbeda.

Contoh: menyimpan order_total sekaligus menyimpan order_items. Jika seseorang mengubah quantity atau memberikan diskon dan total tidak diperbarui dengan sempurna, finance melihat angka satu sementara keranjang menunjukkan angka lain.

Gunakan workflow untuk memutuskan apa yang harus disimpan (history dan snapshot)

Workflow memperlihatkan kapan Anda butuh kebenaran historis, bukan hanya “kebenaran sekarang”. Jika pengguna perlu tahu nilai pada saat itu, simpan snapshot.

Untuk sebuah order, Anda mungkin menyimpan:

  • Line items dan harga (fakta)
  • order_total yang di-capture saat checkout (snapshot), karena pajak, diskon, dan aturan harga bisa berubah nanti

Untuk inventory, “level inventory” sering dihitung dari pergerakan (penerimaan, penjualan, penyesuaian). Tetapi jika Anda butuh jejak audit, simpan pergerakan dan opsional simpan snapshot periodik untuk kecepatan laporan.

Untuk tracking login, simpan last_login_at sebagai fakta (timestamp event). “Aktif dalam 30 hari terakhir?” tetap dihitung.

Contoh Kerja: Dari 5 User Stories ke Model ER

Mari gunakan aplikasi support ticket yang familiar. Kita akan mulai dari lima user stories ke model ER sederhana (entitas + kolom + relasi), lalu memeriksanya terhadap satu workflow.

5 user stories → kata benda → entitas

  1. Sebagai customer, saya bisa membuat support ticket dengan subject, deskripsi, dan kategori.
  2. Sebagai agent, saya bisa menugaskan ticket ke diri sendiri atau agent lain.
  3. Sebagai agent, saya bisa menambahkan catatan internal dan balasan publik ke ticket.
  4. Sebagai customer, saya bisa melihat ketika ticket saya diperbarui dan ketika ditutup.
  5. Sebagai manager, saya bisa melacak berapa lama ticket terbuka dan siapa yang menutupnya.

Dari kata benda itu, kita dapat entitas inti:

  • User (customer, agent, manager)
  • Ticket
  • Message (balasan publik + catatan internal)
  • Category
  • TicketEvent (audit/riwayat)

Kolom dan relasi (model ER ringkas)

  • User: id, name, email, role
  • Category: id, name
  • Ticket: id, subject, description, status, created_at, updated_at, closed_at
    • relasi: Ticket.category_id → Category.id
    • relasi: Ticket.requester_id → User.id (customer)
    • relasi: Ticket.assignee_id → User.id (agent, nullable)
  • Message: id, ticket_id, author_id, body, is_internal, created_at
    • relasi: Message.ticket_id → Ticket.id
    • relasi: Message.author_id → User.id
  • TicketEvent: id, ticket_id, actor_id, type, from_status, to_status, created_at

Pemetaan workflow: buat → update → tutup

  • Buat: insert Ticket (status = “open”, created_at), insert TicketEvent(type = “created”).
  • Update (assign, reply): insert Message atau update Ticket.assignee_id, lalu insert TicketEvent(type = “assigned”/“replied”, updated_at).
  • Tutup: update Ticket.status = “closed”, set closed_at, insert TicketEvent(type = “closed”, actor_id = closer).

“Sebelum dan sesudah”: AI menangkap constraint yang hilang

Sebelum (keliru umum): Ticket punya assignee_id, tapi kita lupa memastikan hanya agent yang bisa jadi assignee.

Sesudah: AI menandai dan Anda menambahkan aturan praktis: assignee harus User dengan role = “agent” (diimplementasikan lewat validasi aplikasi atau constraint/policy database, tergantung stack Anda). Ini mencegah “ditugaskan ke customer” yang merusak laporan nanti.

Validasi Skema: Lacak Kembali ke Setiap Story

Tutup celah lebih awal
Tangkap field yang hilang seperti approved_by dan approved_at dengan memodelkan alur kerja lewat chat.

Skema dianggap “selesai” ketika setiap user story bisa dijawab dengan data yang benar-benar bisa Anda simpan dan query. Langkah validasi paling sederhana adalah ambil tiap story dan tanyakan: “Bisakah kita menjawab pertanyaan ini dari database, andal, untuk setiap kasus?” Jika jawabannya “mungkin”, model Anda punya celah.

Ubah tiap story menjadi pertanyaan database

Tulis ulang tiap user story menjadi satu atau lebih pertanyaan uji—hal yang Anda harapkan laporan, layar, atau API tanyakan. Contoh:

  • Laporan: “Tampilkan semua order terbuka per customer, dengan total untuk 30 hari terakhir.”
  • Permisi: “User mana yang boleh menyetujui refund untuk toko ini?”
  • Edge case: “Apakah sebuah order bisa ada tanpa shipping address? Bagaimana dengan item digital?”
  • Penghapusan: “Jika kita hapus customer, apa yang terjadi pada orders, invoices, dan notes?”

Jika Anda tidak bisa mengekspresikan story sebagai pertanyaan jelas, story itu tidak jelas. Jika Anda bisa mengekspresikannya—tapi tidak bisa menjawabnya dengan skema—maka Anda kekurangan kolom, relasi, status/event, atau constraint.

Gunakan data contoh sebagai cek cepat

Buat dataset kecil (5–20 baris per tabel kunci) yang mencakup kasus normal dan yang canggung (duplikat, nilai hilang, pembatalan). Kemudian “mainkan” stories menggunakan data itu. Anda akan cepat menemukan masalah seperti “kita tidak bisa tahu alamat mana yang dipakai saat pembelian” atau “tidak ada tempat untuk menyimpan siapa yang menyetujui perubahan.”

Biarkan AI membantu menemukan kasus yang tidak ditangani

Minta AI menghasilkan pertanyaan validasi per story (termasuk edge case dan skenario penghapusan), dan mencantumkan data apa yang diperlukan untuk menjawabnya. Bandingkan daftar itu dengan skema Anda: setiap mismatch menjadi item tindakan konkret, bukan perasaan samar bahwa “ada yang salah.”

Menggunakan AI dengan Aman dan Menjaga Skema Terawat

AI bisa mempercepat pemodelan data, tapi juga meningkatkan risiko bocornya data sensitif atau hard-coding asumsi buruk. Perlakukan sebagai asisten cepat: berguna, tapi perlu pembatasan.

Apa yang boleh dibagikan ke AI (dan apa yang dihindari)

Bagikan input yang realistis untuk dimodelkan, tapi disanitasi cukup untuk aman:

  • User stories yang disanitasi (ubah nama customer, produk, lokasi)
  • Acceptance criteria dan edge case (“refund dalam 14 hari”, “satu langganan aktif per akun”)
  • Contoh field dengan data palsu (mis. invoice_total: 129.50, status: "paid")
  • Header CSV / tabel yang ada (struktur biasanya aman; isi sering sensitif)

Hindari apa pun yang bisa mengidentifikasi orang atau mengungkap operasi rahasia:

  • Nama nyata, email, nomor telepon, alamat
  • Riwayat order nyata, tiket support, catatan internal
  • API key, credential DB, screenshot dengan data pribadi

Jika perlu realisme, buat sampel sintetis yang sesuai format dan rentang—jangan menyalin baris produksi.

Taruh asumsi di sebelah skema

Skema sering gagal karena “semua orang mengasumsikan” hal berbeda. Di samping model ER (atau di repo yang sama), simpan log keputusan singkat:

  • Definisi (“Apa yang dihitung sebagai ‘aktif’?”)
  • Constraint (“Seorang user bisa tergabung ke beberapa organisasi”)
  • Trade-off (“Kita simpan kode mata uang di tiap invoice untuk audit”)

Ini mengubah output AI menjadi pengetahuan tim alih-alih artefak satu kali.

Rencanakan perubahan: versioning dan migrasi

Skema Anda akan berkembang dengan stories baru. Jaga aman dengan:

  • Versioning perubahan skema (file migrasi di Git)
  • Menulis migrasi yang reversible bila memungkinkan
  • Memperbarui seed dan query contoh agar perubahan bisa dites
  • Review migrasi yang dihasilkan AI seperti kode biasa

Jika Anda menggunakan platform seperti Koder.ai, manfaatkan guardrail seperti snapshot dan rollback ketika iterasi skema, dan ekspor kode sumber saat perlu kustomisasi lebih dalam atau review tradisional.

Alur kerja sederhana yang bisa diulang

  1. Sanitasi stories + buat 5–10 contoh sintetis.
  2. Minta AI mengusulkan entitas, kolom, relasi, dan constraint.
  3. Review dengan tim; catat asumsi.
  4. Implementasikan migrasi; jalankan tes “trace story” kecil (setiap story bisa dipenuhi oleh model).
  5. Ulangi saat stories berubah; sinkronkan skema dan catatan.

Pertanyaan umum

Bagaimana cara mengekstrak entitas database dari user stories?

Mulailah dari stories dan tandai kata benda yang mewakili hal-hal yang sistem harus ingat (mis. Ticket, User, Category).

Kenaikkan sebuah kata benda menjadi entitas ketika:

  • perlu ID sendiri
  • berubah seiring waktu (memiliki lifecycle/status)
  • muncul di banyak stories

Simpan daftar singkat yang bisa Anda jelaskan dengan menunjuk kalimat spesifik dari story.

Kapan sesuatu harus jadi field vs. tabel terpisah?

Gunakan tes “atribut vs entitas”:

  • Buat menjadi kolom jika itu nilai tunggal yang menggambarkan satu record (mis. customer.phone_number).
  • Buat menjadi tabel terpisah jika itu dapat berulang, dibagikan, terstruktur, atau butuh riwayat (mis. banyak alamat, tag, lampiran).

Petunjuk cepat: jika Anda perlu “banyak dari ini”, besar kemungkinan butuh tabel lain.

Bagaimana acceptance criteria diterjemahkan menjadi kolom dan constraint?

Perlakukan acceptance criteria sebagai daftar cek penyimpanan. Jika sebuah persyaratan mengatakan Anda harus memfilter/menampilkan/mencatat sesuatu, Anda harus menyimpannya (atau bisa menurunkannya dengan andal).

Contoh:

  • “Tunjukkan siapa yang menyetujui dan kapan” → approved_by, approved_at
  • “Filter berdasarkan tanggal pengiriman” → delivery_date
  • “Email harus unik” → constraint/index unik pada email
Bagaimana cara mengubah teks story menjadi relasi tabel (1:1, 1:N, M:N)?

Ubah kalimat story menjadi kalimat relasi:

  • “Seorang customer bisa memiliki banyak order” → 1:N (letakkan customer_id pada orders)
  • “Sebuah order berisi banyak produk” → M:N (tambahkan tabel join seperti order_items)

Jika relasi itu sendiri punya data (quantity, price, role), data itu harus ada di tabel join.

Apa cara yang benar untuk memodelkan hubungan many-to-many?

Modelkan M:N dengan tabel join yang menyimpan kedua foreign key plus kolom spesifik relasi.

Pola umum:

  • orders
  • products
  • order_items dengan order_id, product_id, quantity, unit_price

Hindari menyimpan “daftar ID” dalam satu kolom — querying, update, dan integritas jadi sulit.

Bagaimana alur kerja membantu menemukan tabel atau kolom yang hilang?

Jalani alur kerja langkah demi langkah dan tanyakan: “Apa yang perlu kita buktikan nanti?”

Tambahan umum:

  • timestamp: submitted_at, closed_at
  • pelaku: created_by, assigned_to, closed_by
  • alasan/catatan: rejection_reason

Jika Anda perlu tahu “siapa mengubah apa kapan”, tambahkan tabel event/audit daripada menimpa satu kolom.

Constraint mana yang harus ditambahkan pertama (kunci, unik, index)?

Mulai dengan:

  • primary key stabil per tabel (id)
  • foreign key untuk relasi (orders.customer_id → customers.id)
  • aturan unik dari persyaratan (email, nomor invoice)

Lalu tambahkan index untuk lookup yang paling sering (mis. email, customer_id, status + created_at). Tunda indexing spekulatif sampai Anda lihat pola query nyata.

Bagaimana saya tahu skema saya cukup ternormalisasi tanpa berlebihan?

Lakukan pemeriksaan konsistensi cepat:

  • Jika Anda melihat grup berulang seperti Phone1/Phone2, pecah jadi tabel anak.
  • Jika fakta yang sama muncul di banyak tabel, tentukan satu sumber kebenaran dan referensikan itu.
  • Jika sebuah kolom menggambarkan sesuatu selain entitas utama tabel, pindahkan ke tempat yang benar.

Denormalisasi boleh dilakukan nanti dengan alasan jelas (performansi, reporting, snapshot audit) dan dokumentasikan sumber kebenaran.

Apa yang sebaiknya disimpan vs dihitung di database?

Simpan fakta yang tidak bisa dibuat ulang dengan andal nanti; hitung sisanya.

Baik disimpan:

  • event dan timestamp
  • line items dan harga historis
  • "siapa melakukan apa" untuk audit

Baik dihitung:

  • total (dari line items)
  • flag seperti “is overdue” (dari tanggal)

Jika Anda menyimpan nilai terderived (mis. order_total), tentukan bagaimana sinkronisasinya dan uji kasus tepi (refund, edit, pengiriman parsial).

Bagaimana saya bisa menggunakan AI dengan aman untuk mempercepat desain skema tanpa membuat asumsi buruk?

Gunakan AI untuk draf, lalu verifikasi terhadap artefak Anda.

Prompt praktis:

  • “Ekstrak kandidat entitas dan sinonim dari stories ini.”
  • “Daftar kolom yang diimplikasikan oleh acceptance criteria (timestamp, pelaku, status).”
  • “Berdasarkan workflow ini, data apa yang diperlukan pada setiap langkah?”

Pembatasan:

  • sanitasi input (jangan pakai PII, kredensial, atau baris produksi)
  • simpan log keputusan di samping skema
  • perlakukan migration yang dihasilkan AI seperti kode lain dan versi di Git

Related posts