İçeriğe geç
TankDev

Modern Bir Kurumsal Yazılım Mimarisi Nasıl Tasarlanır?

Tekliften ERP’ye gerçek bir sistem: frontend/backend, API, PostgreSQL, RBAC, işler, yedekler ve ölçekleme. C++/Python ve kütüphane seçimlerini somut örneklerle inceleyin.

· TankDev Mühendislik

Modern bir kurumsal yazılım mimarisi; ekranları, iş kurallarını, veriyi ve operasyonu açık sorumluluklarla bir araya getirir. İyi tasarım yalnızca bir işlemin başarılı olmasını sağlamaz. Aynı kayıt iki kişi tarafından değiştirildiğinde, ERP yanıt vermediğinde veya yeni sürüm sorun çıkardığında sistemin nasıl davranacağını da belirler.

Next.js, FastAPI ve PostgreSQL bu yapıyı kurmak için kullanılabilir. Benzer işlevler başka framework'lerle, Python veya C++ ile de geliştirilebilir. Seçimi anlamlı kılan; işlevin yanında hangi performans, teslim süresi, bakım ve işletim koşullarının karşılandığıdır.

Bu yazıda satış temsilcisinin teklif hazırladığı, yöneticinin onayladığı ve onaylanan teklifin ERP'ye sipariş olarak aktarıldığı temsili bir sistemi tasarlayacağız. Örnekler mimari kararları açıklamak içindir; ölçülmüş müşteri sonuçları değildir.

1. Ekranlardan önce korunacak kuralları belirleyin

İlk soru “Hangi framework?” değil, sistemin hangi durumları kesinlikle önlemesi gerektiğidir. Örneğimizde bir kullanıcı başka şirkete ait teklifi görememeli, onaylanmış teklifin tutarı sessizce değişmemeli ve aynı aktarım isteği ERP'de iki sipariş oluşturmamalıdır.

Bunlara operasyon hedeflerini ekleyin: Kaç eşzamanlı kullanıcı bekleniyor? En yoğun saatte kaç işlem geliyor? Kritik ekranın hedef yanıt süresi nedir? Ne kadar veri kaybı ve kesinti kabul edilebilir? Her ek modülün aynı erişilebilirlik hedefini taşıması şart değildir; sipariş onayı ile geçmiş yıl raporu farklı önceliklere sahip olabilir.

İlk sürüm için müşteri, teklif, onay ve entegrasyon modülleri olan bir modüler monolit makul bir başlangıçtır: Aynı uygulama içinde sınırları belli modüller bulunur. Ayrı bir worker süreci çalıştırmak mümkündür; bunun için her modülü bağımsız mikroservise dönüştürmek gerekmez. Ayrıştırmayı ekiplerin bağımsız teslim veya farklı ölçekleme ihtiyacı haklı çıkardığında değerlendirin.

Tarayıcı HTTPS üzerinden Next.js arayüzüne ve REST API'ye erişir. FastAPI içindeki iş modülleri PostgreSQL ile çalışır; outbox ve kuyruk üzerinden worker ERP'ye bağlanır. Kimlik, dosyalar, gözlemlenebilirlik ve yedekleme ayrı sorumluluklardır.

Şema 1. Örnek teknoloji yerleşimi. Oklar iletişimi gösterir; bütün adımların tek istekte çalışması gerekmez.

2. Frontend ve backend ayrımı bir sorumluluk sınırıdır

Frontend; kullanıcının bilgiyi görmesini, veri girmesini ve işin durumunu anlamasını sağlar. Backend; fiyatı, erişim hakkını, onay koşullarını ve durum geçişlerini doğrular. Tarayıcıdan gelen toplam tutar veya “onaylandı” alanı doğrudan gerçek kabul edilmez.

Next.js hem sunucuda hem tarayıcıda çalışan parçalar içerebilir. Dolayısıyla “frontend tamamen kullanıcının bilgisayarındadır” varsayımı doğru değildir. Next.js sunucu ve istemci bileşenleri rehberi bu ayrımı açıklar. Bu örnekte Next.js sunucusu arayüz için veri birleştirebilir; teklif onay kuralının sahibi yine backend'dir.

Aynı indirim kuralını hem arayüzde hem iki farklı sunucu katmanında bağımsız uygulamak zamanla farklı sonuçlar üretir. Arayüz kullanıcıya erken uyarı verebilir, ancak yetkili kontrol tek bir iş katmanında yapılır. Veri tabanı erişim bilgileri tarayıcıya gönderilmez; API ve veri tabanı erişimleri de gerekli ağ ve kullanıcı izinleriyle sınırlandırılır.

3. REST API: Ekranla sunucu arasında açık bir sözleşme kurun

REST API, kaynakları ve bu kaynaklar üzerindeki işlemleri HTTP üzerinden sunar. Örneğin GET /quotes/417 teklifi getirir; POST /quotes/417/approvals onay talebini işler. İstek şeması, hata davranışı, sayfalama ve uyumluluk politikası sözleşmenin parçasıdır.

Onay isteği teklifin kullanıcının gördüğü sürümünü de taşıyabilir:

json
{
  "expected_version": 7,
  "note": "Teslim koşulları kontrol edildi."
}

Sunucu, oturumdaki kullanıcının yetkisini ve teklifin hâlâ 7. sürümde olduğunu kontrol eder. Başka biri miktarı değiştirmişse eski ekrandan gelen onay reddedilir; örneğin 409 Conflict ile güncel kaydın incelenmesi istenir. İstemcinin gönderdiği kullanıcı veya şirket kimliği yetki kaynağı değildir.

İç onayın kaydedilmesi ile ERP aktarımının bitmesi farklı sonuçlardır. Entegrasyon bekliyorsa yanıt ve ekran bunu açıkça göstermelidir. Bir HTTP isteğinin başarılı olması bütün iş zincirinin tamamlandığı anlamına gelmez.

4. PostgreSQL: Veri bütünlüğünü uygulamayla birlikte koruyun

Müşteri, teklif, teklif satırı, onay ve aktarım kaydı arasında açık ilişkiler kurun. Para alanında gereken hassasiyeti koruyan sayısal türleri, miktarda birimi, zaman damgalarında ortak bir standardı kullanın. Benzersiz anahtarlar ve foreign key'ler, ilişkilerin yalnızca geliştiricinin dikkatine bağlı kalmasını önler.

Onay sırasında sürüm kontrolü ve güncelleme aynı atomik işlemde yapılmalıdır. Önce sürümü okuyup daha sonra koşulsuz yazmak yarış durumunu çözmez. Uygun kilitleme veya version = 7 koşullu güncelleme kullanılır; etkilenen satır sayısı kontrol edilir. Onay, durum değişikliği, audit olayı ve aktarılacak outbox kaydı tek transaction içinde saklanabilir.

Bu transaction uzak ERP'yi kapsamaz. Ayrıca ORM kullanmak indeks, sorgu planı veya transaction tasarımını gereksiz kılmaz. Teklif listesi her satır için ayrı müşteri sorgusu çalıştırıyorsa yüz satırlık ekran yüz ek sorgu üretebilir. Böyle bir sorunda dili değiştirmeden önce sorgu sayısını, indeksleri ve dönen veri hacmini inceleyin.

5. Authentication, authorization ve RBAC farklı soruları cevaplar

Authentication, kullanıcının kim olduğunu doğrular. Kurumsal kimlik sağlayıcısıyla giriş ve gerektiğinde çok faktörlü doğrulama kullanılabilir. Authorization, bu kullanıcının hangi kayıt üzerinde hangi işlemi yapabileceğini belirler. Giriş yapmış olmak bütün teklifleri görme hakkı vermez.

RBAC, izinleri satış, yönetici ve finans gibi roller üzerinden gruplar. Fakat rol tek başına yeterli olmayabilir: Bir yönetici yalnızca kendi şirketinin tekliflerini onaylayabilir; bazı tutarlarda ikinci onay gerekebilir. Rol, kayıt kapsamı ve iş kuralı birlikte değerlendirilir. Sunucu her istekte yetkiyi kontrol eder; OWASP yetkilendirme rehberi bu ilkeyi ayrıntılandırır.

İzinler ekran butonlarıyla sınırlı değildir. API, dosya indirme, rapor ve background job aynı kapsam kurallarını korumalıdır. Görevden ayrılan kullanıcının oturumu ve yetkileri için yaşam döngüsü tanımlanır. Cookie tabanlı oturumlarda güvenli cookie ayarları ve CSRF savunması; token kullanılıyorsa imza, süre, issuer ve audience kontrolleri tasarlanır. CORS bir yetkilendirme mekanizması değildir.

6. Audit logs, entegrasyonlar ve background jobs

Audit log, “Teklifi kim, hangi sürümde ve ne zaman onayladı?” sorusuna cevap verir. Kritik değişikliklerde önceki ve sonraki değerler veya değişiklik özeti tutulabilir. Bu geçmişin erişimi ve saklama süresi tanımlanır; sıradan kullanıcılar geçmişi değiştirememelidir. Audit kaydı, hata ayıklama için tutulan teknik logdan farklı bir amaca hizmet eder.

ERP aktarımı, büyük rapor üretimi veya belge dönüştürme gibi işler background job olarak yürütülebilir. Kullanıcı iş kimliği ve durumunu görür; web isteği uzun süre açık kalmaz. Kaybolmaması gereken bir iş yalnızca web sürecinin belleğinde başlatılmaz. Kalıcı kuyruk, deneme sayısı, zaman aşımı ve hata sonrası devam etme davranışı gerekir.

Outbox kaydını okuyan süreç aktarımı kuyruğa gönderir; worker ERP çağrısını yapar. Aynı mesaj tekrar gelebileceği için yazma işlemi idempotent tasarlanır. ERP siparişi kaydedip yanıt vermezse yeni sipariş açmadan önce aynı işlem anahtarıyla güvenli tekrar veya durum sorgusu yapılır. Bu akışı LLM, API ve otonom iş akışları yazısında daha ayrıntılı ele aldık; aynı dayanıklılık ilkeleri yapay zekâ içermeyen sistemlerde de geçerlidir.

7. Aynı sistemi C++ ile de Python ile de yapabiliyorsak fark nerede?

İki uygulama aynı teklif ekranını ve API sözleşmesini sunabilir. Ancak aynı işlev; aynı kaynak tüketimi, gecikme, geliştirme süresi veya bakım yükü anlamına gelmez. Dil seçimi bu özellikleri, kullanılan kütüphaneler ve ekibin deneyimiyle birlikte etkiler.

Python, sık değişen iş kurallarını ve hazır entegrasyonları uygulamak için elverişli olabilir. C++, yoğun hesaplama, yerel sistemlerle yakın etkileşim ve bellek düzeni üzerinde ayrıntılı kontrol gereken bileşenlerde avantaj sağlayabilir. Bu bir hız garantisi değildir: algoritma, veri erişimi, derleme seçenekleri ve gerçek iş yükü sonucu belirler. C++ tarafında bellek yaşam döngüsü ve derleme/dağıtım ayrıntıları; Python tarafında çalışma zamanı, bağımlılıklar ve uygun eşzamanlılık modeli ayrıca yönetilir.

Somut bir süre hesabı yapalım. Tamamen varsayımsal bir isteğin 450 ms'si veri tabanında, 500 ms'si ERP yanıtında, 50 ms'si uygulama hesaplamasında geçsin. Hesaplama bölümünü on kat hızlandırmak toplamı 1.000 ms'den 955 ms'ye indirir: yalnızca %4,5 azalma. Bu dağılımda sorguyu düzeltmek veya ERP işini arka plana taşımak, bütün backend'i yeniden yazmaktan daha etkili olabilir. Arka plana taşımak ERP'yi hızlandırmaz; kullanıcının beklediği süreyle işin tamamlanma süresini ayırır.

Tersine, bir üretim planlama algoritması sürenin çoğunu CPU'da harcıyorsa algoritma iyileştirme, optimize yerel kütüphane veya C++ bileşeni anlamlı olabilir. Bütün sistemi tek dilde yazmak zorunlu değildir. Python API ile C/C++ uzantısı veya ayrı hesaplama worker'ı birlikte kullanılabilir; Python'un C/C++ uzantı belgeleri bu birlikte çalışabilirliği açıklar. Karşılığında veri aktarımı, derleme ve hata ayıklama maliyeti doğar. Önce profilleyin, sonra sınırı seçin.

Teknoloji seçimi önce iş yükünün ölçülmesiyle başlar. Bekleme ağırlıklı sorunlarda sorgu, bağlantı ve entegrasyon; CPU ağırlıklı sorunlarda algoritma ve yerel hesaplama incelenir. Her çözüm aynı kabul ölçütleri ve toplam bakım maliyetiyle değerlendirilir.

Şema 2. Aynı işlevi sağlayan iki çözümün farkını gerçek iş yükü ve işletim maliyeti ortaya çıkarır.

8. Python içinde aynı işi yapan kütüphaneler arasından neden seçim yaparız?

Bir HTTP isteği birçok kütüphaneyle gönderilebilir. Ancak async çalışan bir API içinden doğrudan bloklayan ağ çağrısı yapmak, o event loop üzerinde diğer işlerin ilerlemesini engelleyebilir. Async uyumlu istemci, timeout ve bağlantı havuzu yönetimi bu bağlamda önemlidir. HTTPX async rehberi, istemci yaşam döngüsü ve bağlantıların yeniden kullanımını açıklar. Async, CPU'da yapılan hesabı kendiliğinden hızlandırmaz; FastAPI eşzamanlılık açıklaması bekleme ve paralel hesaplama ayrımını ele alır.

Veri erişiminde SQLAlchemy ORM, nesneler ve ilişkiler üzerinden çalışmayı kolaylaştırırken doğrudan sürücüyle SQL yazmak sorgu üzerinde daha açık kontrol sunabilir. ORM ile gerektiğinde doğrudan SQL de kullanılabilir. Her iki yaklaşımda bağlantı havuzu, parametreli sorgular, transaction sınırı ve migration süreci gerekir. SQLAlchemy Session açıklaması, oturum ve transaction yaşam döngüsünü anlamak için yararlıdır.

Framework seçimi de hazır gelen parçalarla ekibin birleştireceği parçaların dengesidir. Django'nun sunduğu ORM, yönetim ekranı ve kimlik altyapısı bir iç operasyon uygulamasının başlangıç maliyetini azaltabilir. FastAPI, tip tanımlı API sözleşmesi etrafında bir servis kurarken uygun olabilir; yönetim ekranı ve kullanıcı yaşam döngüsü gibi ihtiyaçların nasıl karşılanacağı ayrıca seçilir. İkisi de doğru tasarımla kurumsal sistemlerde kullanılabilir.

Seçimi aynı küçük senaryoda deneyin: teklif oluşturma, transaction geri alma, yetkisiz erişimi reddetme, zaman aşımını yönetme ve metriğe bağlama. Dokümantasyon, bakım etkinliği, lisans, güvenlik güncellemeleri ve ekibin hata ayıklama becerisi değerlendirmeye dahil olsun. Kararı ve hangi koşulda yeniden değerlendirileceğini kısa bir mimari karar kaydına yazın.

9. Backups ve observability ilk sürümün parçasıdır

RPO, kabul edilen veri kaybı aralığını; RTO, hizmeti geri getirme hedef süresini tanımlar. Örneğin 15 dakikalık RPO ile 2 saatlik RTO birer tasarım hedefidir, otomatik garanti değildir. Yalnızca gece alınan yedek, gün içinde 15 dakikalık veri kaybı hedefini tek başına karşılamaz.

PostgreSQL'de uygun bir temel yedek ve kesintisiz WAL arşiviyle point-in-time recovery, yani belirli bir zamana dönüş kurulabilir. PostgreSQL PITR belgeleri gereksinimleri açıklar. Yedeği sunucudan ayrı hata alanında saklayın; erişim ve şifreleme kontrollerini uygulayın. Replika, hatalı silmeyi de çoğaltabileceği için tek başına yedek değildir.

Geri dönüş provasında veri tabanı kadar ekli belgeler, gerekli yapılandırma ve güvenli anahtar erişimi de düşünülür. ERP'ye daha önce aktarılmış işlemlerle geri yüklenen kayıtlar uzlaştırılmalıdır; restore sonrası tekrar çalışan işler çift sipariş oluşturmamalıdır. Ölçülen kurtarma süresi, dokümandaki tahminden daha değerlidir.

Observability, sistemin iç davranışını ürettiği sinyallerden anlayabilmektir. Metrikler hata oranını ve gecikmeyi; loglar olay ayrıntılarını; trace'ler bir isteğin API, veri tabanı ve ERP arasında nerede zaman harcadığını gösterir. OpenTelemetry sinyalleri bu ayrımı açıklar. İşlem kimliğiyle ilişkilendirin; parolaları ve gereksiz kişisel verileri kaydetmeyin. Her alarmın sorumlusu ve uygulanabilir bir müdahale adımı olsun.

10. Deployment ve ölçeklenebilirlik: Değişimi de yük kadar tasarlayın

Deployment; kodu kopyalamanın yanında bağımlılıkların sabitlenmesini, doğrulanmış build'in ortamlar arasında taşınmasını, sırların güvenli sağlanmasını ve migration sırasını kapsar. Test ortamında kritik yetki, eşzamanlı onay ve entegrasyon hatası senaryolarını deneyin. Yeni sürüm trafiği almadan readiness kontrolünden geçsin; kapanan süreç yeni iş almayı bırakıp devam eden işi güvenli biçimde tamamlasın veya devretsin.

Veri tabanı değişikliklerinde eski ve yeni uygulamanın bir süre birlikte çalışabileceği geçişler planlayın: önce uyumlu alan ekleme, gerekirse veri doldurma, sonra yeni kod ve en son eski alanı kaldırma. Uygulamayı önceki sürüme almak, veri tabanındaki silinmiş veriyi geri getirmez. Geri dönüş planı bu ayrımı açıkça kapsamalıdır.

Ölçeklenebilirlik daha çok sunucu eklemekle başlamaz. Önce gerçek veri ve eşzamanlılıkla ölçün; sorguları, indeksleri ve bağlantı havuzunu inceleyin. Altı API süreci on beşer bağlantı açabiliyorsa potansiyel toplam 90 bağlantıdır; worker'lar ayrıca eklenir. Uygulama kopyalarını artırmak, veri tabanına taşıyabileceğinden fazla bağlantı gönderebilir.

Sonra yükün gerektirdiği parçayı büyütün: durumu süreç belleğine bağlamayan API kopyaları, ayrı worker kapasitesi, uygun önbellek veya raporlar için okuma replikası. Replika gecikmesi nedeniyle onay gibi güncel veri gerektiren işlemlerde eski sonuçlara dayanmayın. Önbellek anahtarları şirket ve yetki kapsamını korumalıdır. Tek sunucu işletimi kolaylaştırabilir; kabul edilen kesinti hedefi tek hata noktasına izin vermiyorsa yedeklilik ayrıca tasarlanır.

Mimari seçimin çıktısı ne olmalı?

İyi bir tasarımın sonunda yalnızca teknoloji listesi bulunmaz. İş kurallarının sahibi, veri ve API sözleşmeleri, yetki matrisi, hata durumları, yedekten dönüş yöntemi ve yayın planı bellidir. Performans iddiaları ölçüme, teknoloji tercihleri ekibin sürdürebileceği somut gerekçelere dayanır.

Bir teklifin ekrandan ERP'ye kadar izlenebilmesi, yanlış onayın engellenmesi ve başarısız bir sürümden güvenle dönülebilmesi; kullanılan dilin adından daha güçlü mimari göstergelerdir. C++, Python veya farklı bir kütüphane seçimi, bu sonuçları hangi maliyetle ve ne kadar güvenilir ürettiği üzerinden değerlendirilmelidir.

İlgili notlar

WhatsAppDoğrudan iletişim