Mert Özen Her Satırda Daha İleri

Blog

Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.

Seriler
122 yazı bulundu
Settings Tabloları: Global → Tenant → Kullanıcı Override Hiyerarşisi
Yazılım Tasarımı SERİ 14

Settings Tabloları: Global → Tenant → Kullanıcı Override Hiyerarşisi

Çalışırken değişen, tenant ve kullanıcıya göre ezilen ayarlar için en sağlam yol, her ayarın tip, varsayılan, aralık ve en alt override seviyesini taşıyan bir tanımı ile bu tanıma bağlı tipli key-value değerlerdir; öncelik kuralı tek bir service'te, yazma doğrulamalı ve audit'li olur. Yazı EAV, tipli kolonlar, JSON belge ve dış store ile karşılaştırıyor ve EF Core'un nullable unique index'e eklediği gizli IS NOT NULL filtresini gösteriyor.

7 Kas 2026 14 dk 35
Multi-Tenancy'de Veri İzolasyonu: Database-per-Tenant, Shared Schema ve Row-Level Security
Yazılım Tasarımı SERİ 13

Multi-Tenancy'de Veri İzolasyonu: Database-per-Tenant, Shared Schema ve Row-Level Security

Çoğu SaaS için en iyi denge, tenant kolonlu paylaşılan tablolar, EF Core'da named bir tenant query filter'ı ve onun arkasında SESSION_CONTEXT ile beslenen SQL Server row-level security'dir. Yazı database-per-tenant, schema-per-tenant ve shared table modellerini karşılaştırıyor; tenant çözümlemeyi, background job'ları ve izolasyonu otomatik test etmeyi gerçek çıktılarla gösteriyor.

7 Kas 2026 14 dk 40
Çok Dilli Veri: Ürün Adını TR ve EN Saklamak — Translation Table, JSON Kolon ve Fallback
Yazılım Tasarımı SERİ 12

Çok Dilli Veri: Ürün Adını TR ve EN Saklamak — Translation Table, JSON Kolon ve Fallback

Kullanıcının yönettiği çok dilli veri için en esnek seçenek, (EntityId, Culture, Name) key'li bir translation tablosu ve en-GB → en → tr gibi tek yerde kurulan bir fallback zinciridir. Yazı dil başına kolon, translation tablosu, SQL Server 2025 json kolonu ve ayrı bir translation service'i karşılaştırıyor; EF Core 10 LeftJoin ile fallback'i ve Türkçe I için collation seçimini gerçek çıktılarla gösteriyor.

7 Kas 2026 14 dk 36
Polymorphic Association: Yorum ve Ek Dosyaları Birden Fazla Tabloya Bağlamak
Yazılım Tasarımı SERİ 11

Polymorphic Association: Yorum ve Ek Dosyaları Birden Fazla Tabloya Bağlamak

Ek dosyayı EntityType/EntityId çiftiyle birden çok tabloya bağlamak FK'yı, cascade delete'i ve güvenli yetkilendirmeyi kaybettirir; sahip tipleri az ve kararlıysa her sahip için nullable FK ve tam olarak birini zorunlu kılan check constraint'li exclusive arc kullan. Yetkiyi ekin kendisinden değil sahibinin policy'sinden türet.

7 Kas 2026 12 dk 35
SQL'de Hiyerarşik Veri: Adjacency List, Recursive CTE, Closure Table ve hierarchyid
Yazılım Tasarımı SERİ 10

SQL'de Hiyerarşik Veri: Adjacency List, Recursive CTE, Closure Table ve hierarchyid

Kurum birimi ağacında alt ağaç sorguları sık, taşımalar nadirse SQL Server'da hierarchyid (EF Core 8+ ile LINQ desteği) ve FK bütünlüğü için ParentId birlikte iyi bir seçimdir; veritabanı bağımsızlığı gerekiyorsa closure table kullan. Ağacı uygulamada düğüm düğüm gezmek N+1 üretir, döngüyü de taşıma anında IsDescendantOf ile engelle.

7 Kas 2026 14 dk 37
Status Field'ı Her Yerden Güncelleniyorsa: Transition Table, State Machine ve Status History
Yazılım Tasarımı SERİ 09

Status Field'ı Her Yerden Güncelleniyorsa: Transition Table, State Machine ve Status History

Status kolonunu her endpoint'in yazabildiği bir field olmaktan çıkar: istemci durum değil aksiyon göndersin, izinli geçişleri tek bir yerde (transition table, domain method veya Stateless) tut, her geçişi gerekçesiyle aynı transaction'da status history'ye yaz ve rowversion ile çift onayı engelle.

7 Kas 2026 12 dk 35
Temporal Data: Geçerlilik Tarihli Kayıtlar, Fiyat Geçmişi ve Bitemporal Model
Yazılım Tasarımı SERİ 08

Temporal Data: Geçerlilik Tarihli Kayıtlar, Fiyat Geçmişi ve Bitemporal Model

Geçmişe dönük düzeltme yapılan verilerde iki zaman ekseni gerekir: valid time (bilgi hangi tarih için doğru) ve transaction time (bilgi ne zaman girildi). SQL Server temporal table yalnız transaction time verir; yarı açık [ValidFrom, ValidTo) aralıklı bir tabloyu system-versioned yaparak EF Core 10 ile bitemporal sorgu yazabilirsin.

7 Kas 2026 12 dk 40
Audit Trail: Kim, Neyi, Ne Zaman, Neden Değiştirdi?
Yazılım Tasarımı SERİ 07

Audit Trail: Kim, Neyi, Ne Zaman, Neden Değiştirdi?

Güvenilir bir audit trail için değişiklikleri bir SaveChangesInterceptor ile property bazında eski/yeni değer, kullanıcı, correlation id ve gerekçeyle iş verisiyle aynı transaction'da yaz; kişisel veriyi maskele ve tabloyu append-only yap. ExecuteUpdate gibi interceptor'ı atlayan yollar için özet kayıt ve temporal table güvenlik ağı ekle.

7 Kas 2026 14 dk 41
Soft Delete'i Doğru Yapmak: IsDeleted, DeletedAt, Filtered Unique Index ve Archive Tablosu
Yazılım Tasarımı SERİ 06

Soft Delete'i Doğru Yapmak: IsDeleted, DeletedAt, Filtered Unique Index ve Archive Tablosu

Soft delete'i doğru yapmak için unique index'leri WHERE DeletedAt IS NULL ile filtrele, aynı işlemde silinen kayıtları bir DeletionId ile bağla ve KVKK silme talebini soft delete ile değil anonimleştirmeyle karşıla. Geri getirme gerçek bir ihtiyaç değilse archive tablosu veya hard delete + audit daha sade bir seçimdir.

7 Kas 2026 15 dk 36
Enum mı Lookup Tablosu mu? Reference Data'yı Kodda ve Veritabanında Tutmak
Yazılım Tasarımı SERİ 05

Enum mı Lookup Tablosu mu? Reference Data'yı Kodda ve Veritabanında Tutmak

Kodun davranışını belirleyen kapalı listeler (sipariş durumu) enum olarak kalmalı ve veritabanında HasData ile seed'lenen, FK ile bağlı bir aynası olmalı; iş biriminin yönettiği açık listeler (kurumsal siparişlerde bütçe kalemi) ise IsActive'li bir lookup tablosunda deploy'suz değişmeli. Yazı yeniden numaralandırma ve string enum rename tuzaklarını gerçek çıktılarla gösteriyor.

7 Kas 2026 13 dk 37
Id'yi Dışarıya Açmak: int Identity, GUID v7 ve Public Id Ayrımı
Yazılım Tasarımı SERİ 04

Id'yi Dışarıya Açmak: int Identity, GUID v7 ve Public Id Ayrımı

Dışarıya açılan id için en dengeli yol, içeride clustered key olarak bigint identity, dışarıda değişmez ve unique bir PublicId tutmak ve her sorguda sahiplik koşulu aramaktır. Ölçümde Guid.CreateVersion7 SQL Server'da v4 kadar parçalandı (yüzde 99, 3.496 sayfa), çünkü SQL Server uniqueidentifier'ı son 6 byte'a göre sıralıyor; EF Core'un sequential generator'ı ise identity'ye yakın kaldı.

7 Kas 2026 13 dk 36
Sentinel Value'lar: 0, -1, "1900-01-01" ve 9999-12-31'in Gizli Maliyeti
Yazılım Tasarımı SERİ 03

Sentinel Value'lar: 0, -1, "1900-01-01" ve 9999-12-31'in Gizli Maliyeti

Sentinel value'lar (harcama limitinde 0, bitişte 9999-12-31, tarihte 1900-01-01) aggregate'leri sessizce bozar: Bookstore'un kurumsal sipariş örneğinde ortalama limit 85.000 yerine 51.000 çıkıyor. Çözüm genelde nullable kolon, anlamı birden fazlaysa ayrı bir durum field'ı ve domain'de Special Case tipi; sentinel ancak tek bir üreticisi olduğunda (temporal table, persisted computed column) bilinçli bir standart olabilir.

7 Kas 2026 15 dk 35
Blog Haritası