Kullanıcı hikayelerini, varlıkları ve iş akışlarını net bir veritabanı şemasına dönüştürmenin pratik yöntemini öğrenin ve AI muhakemesinin boşlukları ve kuralları nasıl tespit edebileceğini keşfedin.

Bir veritabanı şeması, uygulamanızın bilgileri nasıl hatırlayacağını planlayan taslaktır. Pratik anlamda bu şunlardır:
Şema gerçek işle eşleştiğinde, insanların gerçekten yaptığı işleri yansıtır—oluşturma, inceleme, onaylama, programlama, atama, iptal etme—beyaz tahtada hoş görünen şeyler yerine.
Kullanıcı hikayeleri ve kabul kriterleri gerçek ihtiyaçları düz bir dille açıklar: kim ne yapıyor ve “tamam” ne demek. Bunları kaynak olarak kullanırsanız, şema kritik ayrıntıları kaçırma olasılığı daha düşüktür (ör. “iadeyi kim onayladı”yı takip etmeliyiz veya “bir rezervasyon birden fazla kez yeniden planlanabilir”).
Hikayelerden başlamak ayrıca kapsam konusunda dürüst olmanızı sağlar. Eğer hikayelerde (veya iş akışında) yoksa, bunu isteğe bağlı olarak değerlendirin; “ya olur diye” karmaşık modeller kurmayın.
AI hızlandırmada yardımcı olabilir:
AI güvenilir şekilde yapamaz:
AI'ı güçlü bir yardımcı, karar verici değil destekçi olarak görün.
Eğer bu yardımcıyı ilerlemeye dönüştürmek isterseniz, Koder.ai gibi bir vibe-coding platformu şema kararlarından çalışan bir React + Go + PostgreSQL uygulamasına daha hızlı geçmenize yardımcı olabilir—aynı zamanda modeli, kısıtları ve migrationları sizin kontrolünüzde tutar.
Şema tasarımı bir döngüdür: taslak → hikayelere karşı test → eksik veriyi bul → iyileştir. Amaç mükemmel ilk çıktı değil; her kullanıcı hikayesine kadar izlenebilen ve “Evet, bu iş akışının ihtiyaç duyduğu her şeyi saklayabiliriz—and her tablonun neden var olduğunu açıklayabiliriz.” diyebileceğiniz bir modeldir.
Gereksinimleri tablolara dönüştürmeden önce neyi modelleyeceğiniz konusunda net olun. İyi bir şema nadiren boş bir sayfadan başlar—insanların yaptığı somut işlerden ve sonra ihtiyaç duyacağınız kanıtlardan (ekranlar, çıktılar ve kenar durumlar) başlar.
Kullanıcı hikayeleri başlıktır, ama tek başına yeterli değildir. Şunları toplayın:
AI kullanıyorsanız, bu girdiler modeli ayakları üzerinde tutar. AI hızlıca varlıklar ve alanlar önerebilir, ama ürününüzle örtüşmeyen bir yapı icat etmemesi için gerçek artefaktlara ihtiyacı vardır.
Kabul kriterleri genellikle veritabanı kurallarının en önemli kısmını içerir, veri açıkça belirtilmemiş olsa bile. Şuna dikkat edin:
Belirsiz hikayeler (“Bir kullanıcı olarak projeleri yönetebilirim”) birden fazla varlık ve iş akışını gizleyebilir. Diğer sık eksiklikler iptaller, yeniden denemeler, kısmi iadeler veya yeniden atama gibi kenar durumların unutulmasıdır.
Tablolar veya diyagramlardan önce kullanıcı hikayelerini okuyun ve isimleri vurgulayın. Gereksinim yazımında, isimler genellikle sistemin hatırlaması gereken “şeyleri” gösterir—bunlar genellikle şemada varlıklar olur.
Kısa zihinsel model: isimler varlık olur, fiiller eylem veya iş akışları olur. Eğer bir hikaye “Bir yönetici bir teknisyeni bir işe atar” diyorsa, olası varlıklar manager, technician ve job’tır—ve “atanır” daha sonra modele edeceğiniz bir ilişkiye işaret eder.
Her isim kendi tablosuna layık değildir. Bir isim iyi bir varlık adayıdır when:
Bir isim yalnızca bir kez geçiyorsa veya başka bir şeyi tarif ediyorsa (“kırmızı buton”, “Cuma”), muhtemelen varlık değildir.
Her detayı tabloya dönüştürmek yaygın bir hatadır. Kural şu:
İki klasik örnek:
AI, hikayeleri tarayıp temalara göre gruplanmış aday isimler döndürebilir ve böylece varlık keşfini hızlandırabilir. Faydalı bir prompt: “Hikayelerden saklanması gereken isimleri çıkar ve eşanlamlıları/grupları birleştir.”
Çıktıyı başlangıç noktası olarak görün, cevap değil. Sonraki sorular:
Adım 1’in hedefi, gerçek hikayelere dayanarak savunabileceğiniz kısa, temiz bir varlık listesi oluşturmaktır.
Varlıkları adlandırdıktan sonra (ör. Order, Customer, Ticket), sonraki iş saklamanız gereken detayları yakalamaktır. Veritabanında bu detaylar alanlardır (özellikler)—sistemin unutmaması gereken hatırlatmalardır.
Kullanıcı hikayesiyle başlayın, sonra kabul kriterlerini kontrol listesi gibi okuyun.\n
Eğer bir gereksinim “Kullanıcılar siparişleri teslim tarihine göre filtreleyebilir” diyorsa, delivery_date bir alandır (veya diğer saklanan verilerden güvenilir şekilde türetilmelidir). “İsteği kim onayladı ve ne zaman gösterilsin” diyorsa muhtemelen approved_by ve approved_at gerekir.
Pratik test: Birisi bunu görüntülemek, aramak, sıralamak, denetlemek veya hesaplamak isteyecek mi? Eğer evet ise, muhtemelen bir alan olmalıdır.
Birçok hikaye “statü”, “tip” veya “öncelik” gibi kelimeler içerir. Bunları kontrollü sözlükler olarak ele alın—izin verilen değerlerin sınırlı seti.
Set küçük ve sabitse basit bir enum alanı işe yarar. Büyüyorsa, etiketlenmesi veya izin yönetimi gerektirecekse ayrı bir lookup tablosu kullanın (örn. status_codes) ve referans saklayın.
Böylece hikayeler, güvenilir arama, raporlama ve yanlış girişleri zorlaştıran alanlara dönüşür.
Varlıkları (User, Order, Invoice, Comment vb.) ve alanlarını listeledikten sonra, onları bağlama zamanı. İlişkiler, hikayeler tarafından ima edilen “bu şeyler nasıl etkileşir” katmanıdır.
Birebir (1:1): “bir şey tam olarak bir diğerine sahip.”\n
User ↔ Profile (Neden yoksa birleştirilebilir).Bire-çok (1:N): “bir şey birçok diğer şeye sahip olabilir.” Bu en yaygın olanıdır.\n
User → Order (Order üzerinde user_id saklayın).Çoktan-çoğa (M:N): “birçok şey birçok şeyle ilişkili olabilir.” Bu ek bir tablo gerektirir.\n
Veritabanları Order içinde “ürün ID’leri listesi” gibi yapılarla düzgün çalışmaz. Bunun yerine ilişkinin kendisini temsil eden bir join tablosu oluşturun.
Örnek:
Order\n- Product\n- OrderItem (join tablosu)OrderItem genellikle şunları içerir:
order_id\n- product_id\n- hikâyeden gelen ekstra detaylar: quantity, unit_price, discountDikkat edin: hikâyedeki detaylar (miktar gibi) çoğunlukla ilişkinin kendisine aittir, iki varlıktan hiçbirinin üzerine değil.
Hikâyeler ayrıca bir bağlantının zorunlu mu yoksa bazen eksik mi olduğunu söyler.
Order için user_id gereklidir (boş olmasına izin vermeyin).\n- “Bir kullanıcının telefon numarası olabilir” → phone boş olabilir.\n- “Bir sipariş göndermeye (fiziksel ürünler) sahip olabilir” → shipping_address_id dijital siparişler için boş olabilir.Hızlı kontrol: hikâye kaydı olmadan yaratamayacağınız şeyleri zorunlu kabul edin; “yapabilir”, “izin verilir” veya istisna varsa isteğe bağlı kabul edin.
Her hikâyeyi şu şekilde yeniden yazın:
User 1:N Comment\n- “Bir yorum bir kullanıcıya ait” → Comment N:1 UserBunu hikayelerdeki her etkileşim için yapın. Sonunda ER diyagramı aracını açmadan önce işin nasıl yürüdüğünü gösteren bağlı bir model elde edeceksiniz.
Kullanıcı hikayeleri size ne istendiğini söyler. İş akışları işi nasıl ilerlediğini adım adım gösterir. Bir iş akışını veriye çevirme, “bunu saklamayı unuttuk” problemlerini inşa etmeden önce yakalamanın en hızlı yollarından biridir.
İş akışını eylemler ve durum değişimleri dizisi olarak yazın. Örneğin:
Bu kalın kelimeler genellikle bir status alanı (veya küçük bir “state” tablosu) olur, açıkça izin verilen değerlerle.
Her adımı yürürken sorun: “Sonra ne bilmemiz gerekir?” İş akışları şu alanları sıkça ortaya çıkarır:
submitted_at, approved_at, completed_at\n- sahiplik: created_by, assigned_to, approved_by\n- sebep/bağlam: rejection_reason, approval_note\n- sıralama: çok adımlı süreçler için sequenceBekleme, yükseltme veya devredilmeler varsa genellikle en az bir zaman damgası ve şu anda “kimin kullandığı” bilgisini tutan bir alan gerekir.
Bazı iş akışı adımları sadece alan değildir—ayrı veri yapılarıdır:
AI'a hem (1) kullanıcı hikayelerini ve kabul kriterlerini, hem de (2) iş akışı adımlarını verin. AI'dan her adımı listelemesini ve her biri için gerekli veriyi (durum, aktör, zaman damgası, çıktı) belirtmesini ve mevcut alanlar/tablolar tarafından karşılanmayan gereksinimleri vurgulamasını isteyin.
Koder.ai gibi platformlarda bu “boşluk kontrolü” özellikle pratiktir çünkü hızlıca yineleyebilir, şema varsayımlarını düzeltebilir, iskelet kodu yeniden oluşturabilir ve uzun bir manuel boilerplate yolculuğu yaşamadan ilerleyebilirsiniz.
Kullanıcı hikayelerinden tablolara geçerken sadece alanları listelemiyorsunuz—aynı zamanda verilerin zaman içinde tanımlanabilir ve tutarlı kalmasını nasıl sağlayacağınızı da belirliyorsunuz.
Bir primary key bir kaydı benzersiz tanımlar—satırın kalıcı kimlik kartı gibidir.
Neden her satırın birine ihtiyacı var: hikayeler güncellemeleri, referansları ve geçmişi ima eder. Örneğin “Destek bir siparişi görüntüleyip iade verebilir” derken, müşteri e-postasını değiştirse bile siparişi işaret edecek sabit bir yol gerekir.
Genellikle bu içsel bir iddir (sayı veya UUID) ve değişmez.
Bir foreign key, bir tablonun diğerine güvenli şekilde işaret etme yoludur. Eğer orders.customer_id customers.id'i işaret ediyorsa, veritabanı her siparişin gerçek bir müşteriye ait olmasını sağlayabilir.
Bu, “Bir kullanıcı faturalarını görebilir” gibi hikayelere karşılık gelir: fatura herhangi bir yerde yüzüyorsa değil, bir müşteriye bağlanmış olmalıdır.
Kullanıcı hikayeleri gizli benzersizlik gereksinimleri içerir:\n
Bu kurallar ileride kafa karıştıran tekrarları (veri hatalarını) önler.
İndeksler “customer by email bulun” veya “orders by customer listele” gibi sorguları hızlandırır. Önce en sık yapılan sorgular ve benzersizlik kurallarıyla uyumlu indekslerden başlayın.
Ertelenmesi gereken: nadir raporlar veya spekülatif filtreler için yoğun indeksleme. Bu ihtiyaçları hikayelerde yakalayın, önce şemayı doğrulayın, sonra gerçek kullanım ve yavaş sorgu verisiyle optimize edin.
Normalizasyonun basit hedefi: çakışan kopyaları önlemek. Aynı gerçek iki yerde saklanabiliyorsa, er ya da geç uyuşmazlık çıkar (iki farklı yazım, iki fiyat, iki “güncel” adres).
1) Tekrarlayan gruplara dikkat edin\n
“Phone1, Phone2, Phone3” veya “ItemA, ItemB, ItemC” gibi kalıplar görürseniz, bu ayrı bir tablo sinyalidir (örn. CustomerPhones, OrderItems). Tekrarlayan gruplar aramayı, doğrulamayı ve ölçeklemeyi zorlaştırır.
2) Aynı ismi birden fazla tabloda çoğaltmayın\n
Eğer CustomerName Orders, Invoices ve Shipments içinde görünüyorsa, birden fazla gerçek kaynağı yarattınız. Müşteri detaylarını Customers içinde tutun ve başka yerde sadece customer_id saklayın.
3) Aynı şey için birden fazla sütun kullanmaktan kaçının\n
billing_address, shipping_address, home_address gibi sütunlar gerçekten farklı kavramlarsa uygundur. Ancak eğer aslında “farklı tiplerde birçok adres” modelliyorsanız, Addresses tablosu ve type alanı kullanın.
4) Lookupları serbest metinden ayırın\n Kullanıcılar bilinen bir setten seçiyorsa (status, category, role), bunu ya sınırlı bir enum ya da lookup tablosuyla tutarlı biçimde modelleyin. Bu “Pending” vs “pending” vs “PENDING” sorunlarını önler.
5) Her ID olmayan alanın doğru şeye bağlı olduğunu kontrol edin\n
Bir sezgi kontrolü: bir tabloda bir sütun tablonun ana varlığını değilse, muhtemelen başka yerde olmalı. Örnek: Orders tablosunda product_price yalnızca “sipariş zamanındaki fiyat” anlamına geliyorsa (tarihsel snapshot), orada olabilir.
Bazen kasten çoğaltma yapılır:\n
Önemli olan kasıtlı olmasıdır: hangi alanın gerçek kaynak olduğu ve kopyaların nasıl güncellendiği belgelenmelidir.
AI kuşkulu çoğaltmaları (tekrarlayan sütunlar, benzer alan adları, tutarsız “status” alanları) işaretleyebilir ve tablo ayırma önerileri sunabilir. İnsanlar yine de basitlik vs esneklik vs performans arasında ürün kullanımı doğrultusunda karar verir.
Kullanışlı kural: daha sonra güvenilir şekilde yeniden oluşturamayacağınız gerçekleri saklayın; diğer her şeyi hesaplayın.
Saklanan veri gerçek kaynaktır: tekil satır öğeleri, zaman damgaları, durum değişiklikleri, kim ne yaptı. Hesaplanan (türev) veri bu gerçeklerden üretilir: toplamlar, sayaçlar, “gecikmiş mi” gibi bayraklar ve rollup’lar.
Aynı girdilerden türetilebilecek iki değerin her ikisini de saklarsanız, uyumsuzluk riski doğar.
Türetilmiş değerler girdiler değiştikçe değişir. Hem girdileri hem sonucu saklarsanız, her iş akışı ve kenar durumunda bunları senkronize etmek zorunda kalırsınız (düzenlemeler, iadeler, kısmi gönderimler, tarih gerilemesi). Bir güncelleme kaçarsa veritabanı çelişkili bilgiler verir.
Örnek: order_total saklarken order_items de saklıyorsanız; biri güncellendiğinde toplam güncellenmezse finans ile sepet farklı rakam görür.
İş akışları geçmiş gerçeğe ihtiyaç duyduğunda, sadece “güncel” bilgi değil, o andaki değerler saklanmalıdır.
Bir sipariş için saklayabilecekleriniz:
order_total (snapshot), çünkü vergiler, indirimler ve fiyatlama kuralları sonra değişebilirEnvanter için “stok seviyesi” genellikle hareketlerden hesaplanır. Ancak denetim izi istiyorsanız hareketleri saklayın ve raporlama hızı için periyodik snapshot’lar da tutabilirsiniz.
Giriş izleme için last_login_at gibi bir olay zaman damgası tutun. “Son 30 günde aktif mi?” sorgusu hesaplanmış kalır.
Bir destek ticket uygulaması üzerinden gidelim. Beş kullanıcı hikayesinden basit bir ER modele (varlıklar + alanlar + ilişkiler) geçelim, sonra bir iş akışı ile kontrol edelim.
Bu isimlerden temel varlıkları çıkarıyoruz:
Önce (yaygın eksik): Ticket assignee_id içerir, ama sadece agent rolündeki kullanıcıların atama alabileceğini sağlamıyoruz.\n
Sonra: AI bunu işaretler ve pratik bir kural eklersiniz: assignee, role = “agent” olan bir User olmalıdır (uygulama doğrulaması veya veritabanı kısıtı/policy ile uygulanır). Bu, “müşteriye atandı” gibi raporları bozan veriyi önler.
Bir şema her kullanıcı hikayesinin güvenilir şekilde yanıtlanabileceği zaman “tamamlanmış” sayılır. En basit doğrulama adımı her hikayeyi alıp: "Bu soruyu veritabanından, her durum için güvenilir şekilde cevaplayabilir miyiz?" diye sormaktır. Cevap “belki” ise modelde bir eksik var demektir.
Her kullanıcı hikayesini rapor, ekran veya API'nin soracağı net sorulara dönüştürün. Örnekler:
Eğer bir hikayeyi net bir soruya çeviremiyorsanız, hikaye belirsizdir. Eğer soruya çevirebiliyorsanız ama şema ile cevap veremiyorsanız, eksik bir alan, ilişki, statü/olay veya kısıt var demektir.
Küçük bir veri seti (ana tablolar için 5–20 satır) oluşturun; normal ve garip durumları (çoğaltmalar, eksik değerler, iptaller) dahil edin. Sonra hikayeleri bu veriyi kullanarak “oynayın”. Hızla şu tür sorunları fark edersiniz: “hangi adresin satın alma zamanında kullanıldığını söyleyecek yerimiz yok” veya “değişikliği kim onayladı saklanmıyor”.
AI'dan her hikaye için doğrulama soruları (kenar durumlar ve silme senaryoları dahil) üretmesini ve bu soruları cevaplamak için hangi veriye ihtiyaç duyulduğunu listelemesini isteyin. Bu listeyi şemanızla karşılaştırın: herhangi bir uyuşmazlık somut bir aksiyon maddesidir.
AI veri modellemeyi hızlandırsa da hassas bilgi sızma riskini veya kötü varsayımlar sabitleme riskini artırır. Onu çok hızlı bir yardımcı olarak görün: faydalı, ama gözetim gerektirir.
Modellemeye yeterli ama güvenli girdiler paylaşın:
invoice_total: 129.50, status: "paid")\n- Mevcut CSV başlıkları / var olan tabloların yapısı (yapı genellikle güvenlidir; içerik genellikle değil)Kaçının:
Gerçekçilik gerekiyorsa, üretim satırlarını asla kopyalamayın—formatlara ve aralıklara uyan sentetik örnekler üretin.
Şemalar genellikle “herkes varsaydığı” şeyler yüzünden başarısız olur. ER modelinin yanında kısa bir karar kaydı tutun:
Bu, AI çıktılarını ekibin bilgisine dönüştürür.
Şemanız hikayelerle evrilecek. Güvende tutmak için:
Koder.ai gibi platformlar kullanıyorsanız, yineleme sırasında snapshot ve rollback gibi koruyuculardan faydalanın ve gerektiğinde kaynak kodu dışa aktarın.
Öykülere bakın ve sistemin hatırlaması gereken şeyleri temsil eden isimleri (isimler, nesneler) vurgulayın (ör. Ticket, User, Category).
Bir ismi varlık olarak yükseltin cuando:
Kısa, her cümle ile gerekçelendirilebilecek bir liste tutun.
“Attribute vs. entity” testini kullanın:
customer.phone_number).Kısa ipucu: “bunlardan birden fazlasına ihtiyaç duyuluyorsa” muhtemelen başka bir tablo gereklidir.
Kabul kriterlerini bir saklama kontrol listesi olarak ele alın. Bir gereksinim bir şeyin filtrelenmesi/sıralanması/gösterilmesi/günlüklenmesi gerekiyorsa, onu depolamalısınız (veya güvenilir şekilde türetilebilmelidir).
Örnekler:
approved_by, approved_atHikâye cümlelerini ilişki cümlelerine çevirin:
customer_idi orders tablosuna koyun)order_items gibi join tablosu ekleyin)Eğer ilişkinin kendisinin de verisi varsa (miktar, fiyat, rol), bu veriler join tablosunda tutulmalıdır.
M:N ilişkileri, her iki yabancı anahtarı ve ilişkiye özgü alanları tutan bir join tablosuyla modelleyin.
Tipik desen:
ordersproductsİş akışını adım adım yürütün ve: “Bunu daha sonra kanıtlamak için ne bilmemiz gerekir?” diye sorun.
Sık eklemeler:
submitted_at, closed_atÖncelikle şunları ekleyin:
id)orders.customer_id → customers.id)Sonra en sık yapılan sorgular için indeksler ekleyin (örn. , , ). Spekülatif indekslemeyi, gerçek sorgu desenlerini görene kadar erteleyin.
Hızlı bir tutarlılık kontrolü çalıştırın:
Phone1/Phone2 gibi tekrar eden gruplar görürseniz, bunları alt tabloya ayırın.Denormalizasyonu yalnızca açık bir gerekçe (performans, raporlama, audit snapshot) varsa ve belgelenmişse kabul edin.
Tekrar oluşturulamayacak gerçekleri depolayın; geri kalan her şeyi hesaplayın.
Depolanması iyi olanlar:
Hesaplanması iyi olanlar:
Eğer türetilmiş değerleri saklıyorsanız ( gibi), bunların nasıl senkronize edileceğini kararlaştırın ve sınır durumlarını test edin.
AI'ı taslaklar için kullanın, sonra bunları kanıtlarınızla doğrulayın.
Pratik prompt örnekleri:
Güvenlik önlemleri:
delivery_dateemail üzerinde benzersizlik kısıtı/indeksiorder_items içinde order_id, product_id, quantity, unit_priceTek bir sütunda "ID listesi" saklamaktan kaçının—sorgulama, güncelleme ve bütünlük sağlama zorlaşır.
created_by, assigned_to, closed_byrejection_reason“Kim ne zaman değiştirdi” gibi ihtiyaçlar varsa, tek bir alanı ezmek yerine event/audit tablosu ekleyin.
emailcustomer_idstatus + created_atorder_total