8 dk

Martin Fowler’ın Yorumu: Modaya Dayalı Yığınlardan Daha Uzun Süren Mimari

Martin Fowler’ın pratik bakışını keşfedin: kalıplar, refaktoring ve değişimi öngören evrimsel mimariyle modaya dayalı yığınların ötesine geçen, uzun vadeli riski azaltan yaklaşımlar.

Martin Fowler’ın Yorumu: Modaya Dayalı Yığınlardan Daha Uzun Süren Mimari

Neden Trendy Teknoloji Yığınları İyi Mimariyi Garantilemez

Yeni bir framework, parlak bir bulut servisi veya popüler bir şirketteki “standart yığın” kaliteye kısa yol gibi gelebilir. Ancak yığın-öncelikli düşünce sıklıkla araçları ile yapıyı karıştırır. En modern teknolojilerle de zor değişen, dağınık bir sistem kurabilirsiniz—ya da sıkıcı, iyi bilinen tercihlerle temiz, uyarlanabilir bir sistem.

“Yığın-öncelikli” düşüncenin problemi

Yığını önce seçmek, takımı slaytta etkileyici görünen ama gerçek soruları yanıtlamayan kararlara iter:

  • Sınırlar nerede?
  • Neler sık sık değişmeli?
  • Neler sabit kalmalı?

Teknoloji seçimi başa geçtiğinde, mimari tesadüfi bir yan ürün hâline gelir—sıkı bağlılık, tekrarlanan mantık ve basit değişiklikleri pahalı yapan bağımlılıklar ortaya çıkar.

Bu yüzden “biz microservices kullanıyoruz” (ya da “artık serverless’ız”) bir mimari değildir. Bu bir dağıtım ve araç yönüdür. Mimari, sistem parçalarının nasıl iş birliği yaptığı, kararların gelecekteki işi nasıl kısıtladığı ve ürünün ne kadar kolay evrilebileceği ile ilgilidir.

Pratik çıkarım: araçlar teslimatı hızlandırabilir ama mimari düşüncenin yerini tutmaz. Hızlı üretim-yaklaşımlarında (örneğin chat ile hızlı üretip yineleme yapan) bile aynı sorular geçerlidir. Koder.ai gibi platformlar web, backend ve mobil uygulamaları kurmayı dramatik biçimde hızlandırabilir, ama en iyi sonuçları alan takımlar hâlâ sınırları, sahipliği ve değiştirilebilirliği birinci sınıf kaygılar olarak ele alırlar (framework'ün sihirli şekilde çözeceğini düşünmek yerine).

Fowler’ın etkisi: açıklık, pragmatizm ve zaman içinde değişim

Martin Fowler’ın yazıları sürekli olarak önemli olana odaklanmayı hatırlatır: moda bileşenlerden ziyade net tasarım, ideolojiden çok pratik ödünleşmeler ve öğrendikçe sistemi evriltme yeteneği. Onun çalışması, mimariyi tek seferlik bir “büyük tasarım” dönemi değil, sürekli iyileştirdiğiniz bir şey olarak ele alır.

Bu makale neye odaklanacak

Üç tekrar eden tema bekleyin: kalıpları kurallar değil araçlar olarak kullanmak, refaktoringi bir alışkanlık hâline getirmek ve evrimsel mimari—kesinlik için değil değişim için inşa etmek.

Kimler için

Eğer bir mühendislik lideri, tech lead ya da kalite çökerken daha hızlı teslim etmeye çalışan bir ürün ekimiyseniz, bu yazı sizin için. Amaç “mükemmel” yığını seçmek değil—yol haritası kaçınılmaz olarak değiştiğinde yazılımı kolay değiştirebilir tutacak kararlar almaktır.

“Yazılım Mimarisi” Gerçekte Ne Anlamına Geliyor (Jargonsuz)

Yazılım mimarisi, daha sonra değiştirilmesi zor (ve maliyetli) olan kararlar kümesidir.

Bu tanım kasıtlı olarak sade. Özel diyagramlar veya “mimar” gibi bir unvan gerektirmez. Yazılımın nasıl büyüyebileceğini, ekiplerin nasıl çalışabileceğini ve işletme maliyetlerinin ne olacağını belirleyen tercihlerle ilgilidir.

Mimari, tech stack’iniz değildir

Frameworkler, araçlar ve kodlama stili önemlidir—ama çoğu gerçek mimari kararlara kıyasla kolayca değiştirilebilirdir.

  • React vs Vue seçimi genellikle geri döndürülebilir.
  • “Tüm yazmalar tek bir servisten geçmeli” gibi kararları geri almak çok daha zordur.

Mimari, parçaların nasıl iletişim kurduğu, verinin nerede yaşadığı, hataların nasıl ele alındığı ve hangi değişikliklerin ekipler arası koordinasyon gerektirdiği gibi yapı ve sınırlarla daha yakından ilgilidir.

Mimari çoğunlukla ödünleşmelerdir

Evrensel bir “en iyi” mimari yoktur. Her büyük karar bazı amaçları optimize eder ve diğerlerini feda eder:

  • Performans vs. basitlik: önbellekleme katmanları hızı artırır ama karmaşıklık ve ince kenar durumlar getirir.
  • Ekip hızı vs. güvenilirlik: hızlı sürümler öğrenmeyi hızlandırır ama daha güçlü test ve rollout uygulamaları gerektirebilir.
  • Maliyet vs. dayanıklılık: yedeklilik çalışma süresini artırır ama altyapı ve bakım maliyetini yükseltir.

İyi mimari bu ödünleşmeleri kasıtlı hâle getirir, tesadüfi değil.

Kısa bir örnek: mimari karar vs. kütüphane seçimi

  • Mimari karar: “Müşteri faturalarını kendi deploy edilebilir servisine ve kendi veritabanına ayıralım; sistemin geri kalanı asenkron eventlerle entegre olacak.”

    Bu karar dağıtımı, veri sahipliğini, hata modlarını, izlemeyi ve takım koordinasyonunu etkiler.

  • Kütüphane seçimi: “PDF üretmek için Kütüphane X kullanacağız.”

    Faydalı ama genellikle sınırlı etki alanı ile değiştirilebilir.

Eğer bir kararı tersine çevirmek haftalarca koordineli çalışma gerektirecekse, büyük olasılıkla mimaridir.

Kalıplar Araçlardır: Faydalı, İsteğe Bağlı ve Bazen Yanlış Kullanılır

Tasarım kalıpları en iyi şekilde tekrarlayan problemlere yeniden kullanılabilir çözümler olarak anlaşılmalıdır, emirler olarak değil. Fowler’ın genel duruşu pragmatiktir: kalıplar tasarımı netleştirdiğinde faydalıdır, düşünmenin yerini aldığında zararlı olur.

Kalıplar işe yaradığı zaman

İyi kullanıldığında kalıplar takıma ortak bir söz dağarcığı verir. “Strategy” veya “repository” demek uzun bir açıklamayı tek terime sıkıştırabilir, bu da incelemeleri hızlandırır ve yanlış anlamaları azaltır.

Kalıplar ayrıca sistem davranışını daha öngörülebilir kılar. Tanıdık bir kalıp, mantığın nerede olduğunu, nesnelerin nasıl iş birliği yaptığını ve hangi değişikliklerin etkisinin yayılacağını konuşur. Bu öngörülebilirlik prodüksiyonda daha az sürpriz ve yeni ekip üyeleri için daha az “bu nasıl çalışıyor?” anı demektir.

Kalıplar zarar verdiğinde

Başarısızlık modu cargo-cult uygulamasıdır: bir kalıbı popüler olduğu, bir kitapta listelendiği veya “bizim burada böyle yapılıyor” olduğu için uygulamak. Bu çoğunlukla aşırı mühendisliğe yol açar—ek katmanlar, dolaylılık ve kira ödemeyen soyutlamalar.

Diğer yaygın tuzak “her şeye bir kalıp”tür. Her küçük probleme isimlendirilmiş bir çözüm uygulandığında, kod tabanı bir taşıma müzesi gibi olur; yazılımcı zekâsını sergileyen ama yazılmayan bir araç yerine, yazılım göndermeyi ve sürdürmeyi zorlaştırır.

Seçim için pratik yol

Sorunla başlayın, kalıpla değil.

Şu soruları sorun:

  • Hangi değişikliği kolaylaştırmaya çalışıyoruz?
  • Hangi riski azaltıyoruz?
  • Hangi karmaşıklığı getiriyoruz?

Sonra bugüne uygun en basit kalıbı seçin ve seçenekleri açık tutun. Daha sonra ihtiyaç olursa tasarımı kademeli olarak daha fazla yapısal hâle getirebilirsiniz—çoğunlukla gerçek acı ve refaktoringle yönlendirilir, önceden tahminle değil.

Refaktoring: Mimarinin Sağlıklı Kalmasını Sağlayan Alışkanlık

Refaktoring, yazılımın iç tasarımını ne yaptığını değiştirmeden iyileştirme uygulamasıdır. Kullanıcılar refaktoring sonrası fark etmemelidir—sadece gelecekteki değişikliklerin daha kolay, daha güvenli ve daha hızlı olduğunu fark etmelidirler.

Martin Fowler’ın noktası “kodunuzu güzel tutun” demek değil. Mimari, sistemin ne kadar kolay değiştirilebileceğini belirleyen kararlar kümesidir. Refaktoring bu kararların sertleşip kısıtlamaya dönüşmesini engelleyen yöntemdir.

Refaktoring neden mimari bir faaliyettir

Zamanla, iyi tasarlanmış sistemler bile sürüklenir. Yeni özellikler zaman baskısı altında eklenir, hızlı çözümler kalıcı hâle gelir ve sınırlar bulanıklaşır. Refaktoring, net ayrımı geri getirir ve kazara karmaşıklığı azaltır, böylece sistem değiştirilebilir kalır.

Sağlıklı bir mimari şunlara sahip olur:

  • önemli iş kuralları UI detaylarıyla karışmaz
  • modüllerin net sorumlulukları vardır
  • bağımlılıklar anlamlı yönlere işaret eder

Refaktoring bu nitelikleri koruyan günlük iştir.

“Zamanı geldi” sinyalleri

Refaktoringi genelde takvim hatırlatıcısıyla planlamazsınız. Bunu yaparsınız çünkü kod size itiraz etmeye başlar:

  • Tekrarlama: aynı kural üç yerde uygulanmış ve yavaşça farklılaşıyor
  • Belirsiz sınırlar: “her şey her şeye dokunuyor”, değişiklikleri riskli kılıyor
  • Yavaş teslim: basit istekler günler sürüyor çünkü her değişiklik sürprizler yaratıyor

Bunlar göründüğünde, mimari zaten etkileniyor—refaktoring tamirdir.

Güvenli refaktoring nasıl yapılır (kırmadan)

Güvenli refaktoring birkaç alışkanlığa dayanır:

  • Testler beklenmedik davranış değişikliklerini yakalar (özellikle temel iş mantığı etrafında)
  • Küçük adımlar: birçok küçük, geri alınabilir düzenleme yerine tek büyük yeniden yazım
  • Kod incelemeleri: başka bir göz kaçan yan etkileri ve kapsam genişlemesini görsün

Böyle yapıldığında refaktoring rutin bakıma dönüşür—sistemi bir sonraki değişiklik için hazır tutar, sonuncusunun ardından kırılgan hâle getirmez.

Teknik Borç: Nasıl Birikir ve Nasıl Ödenir

Teknik borç, bugünün kısa yollarının yarattığı gelecekteki maliyettir. “Kötü kod” ahlaki bir kusur değildir; bazen bilinçli yapılan ve gelecekte değişim maliyetini artıran bir tercihtir. Fowler’ın çerçevesi burada işe yarar: borç sadece takip edilmediğinde ve yokmuş gibi davranıldığında sorun olur.

Bilinçli vs. kazara borç

Bilinçli borç gözler açık alınır: “Şimdi daha basit bir sürümü yayınlayacağız, sonra sprint başına sertleştireceğiz.” Bu mantıklı olabilir—eğer geri ödeme de planlanmışsa.

Kazara borç ekip borç aldığını fark etmediğinde oluşur: dağınık bağımlılıklar, belirsiz bir domain modeli veya hızlı çözümün varsayılan hâle gelmesi. Kazara borç genelde daha pahalıdır çünkü kimse ona sahip çıkmaz.

Borç nasıl sessizce birikir

Borç normal baskılarla birikir:

  • Acelemiz olan teslim tarihleri “çalışsın yeter” kararlarını zorlar.
  • Belirsiz sahiplik, hiçbirinin bir modülün sağlığından sorumlu hissetmemesi.
  • Eksik veya kırılgan testler, değişiklikleri korkutucu kılar ve daha fazla kısa yol alınmasına sebep olur.

Sonuç tahmin edilebilir: özellikler yavaşlar, hatalar artar ve refaktoring rutin değil riskli hale gelir.

Hafif yollarla yönetmek ve ödemek

Büyük bir program başlatmanız gerekmez:

  • Sürekli zaman ayırın (örneğin her yinelemede küçük bir pay)
  • Her şeyi değil, sıcak noktaları takip edin: sık dokunulan ve en çok korkulan kodu
  • Küçük parçalar hâlinde ödeyin: refaktoringi özellik işiyle birleştirerek “faiz”in bileşmesini durdurun

Ayrıca borçla ilgili kararları görünür kılarsanız (ör. /blog/architecture-decision-records), gizli maliyetleri yönetilebilir işe dönüştürürsünüz.

Evrimsel Mimari: Kesinlik İçin Değil Değişim İçin İnşa Et

Güvenli sürümler pratiği yapın
Bir özel alan kullanarak yayın akışını doğrulayın; değişiklikleri küçük ve geri alınabilir tutun.

Yazılım mimarisi bir kez “doğru” yapılan bir plan değildir. Fowler’ın bakışı daha pratiktir: gereksinimlerin, trafiklerin, ekiplerin ve kısıtların değişeceğini varsayın—sonra sistemi acısızca adapte edilebilecek şekilde tasarlayın.

“Evrimsel mimari” ne demek

Evrimsel mimari değişim için tasarlamaktır, mükemmeliyet için değil. Uzun vadeli bir tahmine ("microservices'e ihtiyaç duyacağız", "100x ölçekleneceğiz") bahis yapmak yerine, net sınırlar, otomatik testler ve sık, düşük riskli ayarlara izin veren dağıtım uygulamaları ile güvenle evrilebilen bir mimari inşa edersiniz.

Küçük sürümler, gerçek geri bildirim

Planlar tahmindir; üretim gerçekliktir. Küçük artımlarla yayınlamak kullanıcıların gerçekte ne yaptığını, sistemin işletme maliyetini ve performans/güvenilirliğin nerede gerçekten önemli olduğunu öğrenmenizi sağlar.

Küçük sürümler ayrıca karar tarzını değiştirir: tek bir modülü ayırmak veya yeni bir API versiyonu denemek gibi mütevazı bir iyileştirme deneyebilir ve bunun işe yarayıp yaramadığını ölçebilirsiniz—büyük bir göç taahhüdünde bulunmak yerine.

Hızlı yineleme araçları burada yardımcı olabilir—ama mimari korumalara bağlı kaldığınız sürece. Örneğin, Koder.ai gibi bir platformla özellikleri hızla üretip yineliyorsanız, bu hızın yanında stabil modül sınırları, iyi testler ve sık dağıtımlar olması “kendinizi köşeye hızla göndermekten” kaçınmanıza yardımcı olur.

Fitness fonksiyonları (basitçe)

Evrimsel bir fikrin önemli öğesi “fitness fonksiyonu”dur: bir mimari hedefi koruyan ölçülebilir bir kontrol. Bunu bir koruma bariyeri gibi düşünün. Bariyer otomatikse ve sürekli çalışıyorsa, sistemi değiştirirken hafi güven duyabilirsiniz çünkü bariyer saptadığında sizi uyarır.

Fitness fonksiyonları karmaşık olmak zorunda değildir. Önem verdiğiniz şeyi yansıtan basit metrikler, testler veya eşikler olabilir.

Pratik fitness kontrollerine örnekler

  • Derleme süresi: build/test döngüsü bir bütçeyi (ör. 10 dakika) aşarsa pipeline'ı başarısız sayın. Yavaş buildler refaktoringi ve güvenli değişimi caydırır.
  • Hata oranı: prodüksiyonda hata oranı tanımlı bir değerin üstüne çıkarsa alarm verin veya rollout'u engelleyin.
  • Güvenlik taramaları: bağımlılıkları ve containerları otomatik tarayın; bilinen kritik açıklar için buildleri başarısız sayın.
  • API uyumluluğu: yeni sürümlerin mevcut istemcileri veya dahili tüketicileri bozmamasını sağlamak için kontrat testleri.

Amaç her şeyi ölçmek değil; değişim hızı, güvenilirlik, güvenlik ve birlikte çalışabilirlik gibi mimari vaatlerinizi yansıtan birkaç kontrol seçip bunların günlük kararları yönlendirmesine izin vermektir.

Microservices vs Monolitler: Moda Değil Kısıtlarla Seçin

Microservices mühendislik olgunluğunun rozeti değildir. Fowler’ın noktası daha basittir: sistemi servislere bölmek teknik olduğu kadar organizasyonel bir harekettir. Ekipler servisleri uçtan uca sahiplenemiyorsa (build, deploy, operate, evolve), fayda yerine karmaşıklık elde edersiniz.

Üç şekil, üç ödünleşme

Bir monolit tek deploy edilebilir birimdir. Bu bir avantaj olabilir: daha az hareketli parça, daha basit hata ayıklama ve düz veri tutarlılığı. Dezavantajı kod tabanı dolduğunda küçük değişikliklerin büyük koordinasyon gerektirmesidir.

Bir modular monolith hâlâ tek deploy birimidir fakat kod kasıtlı olarak net modüllere bölünmüştür ve sınırlar uygulanır. Operasyonel sadeliği korurken içsel coupling'i azaltırsınız. Birçok ekip için bu en iyi varsayılan seçimdir.

Microservices her servise kendi dağıtım ve yaşam döngüsünü verir. Bu bağımsız sürümlere ve net sahipliğe izin verebilir—eğer organizasyon buna hazırsa. Aksi hâlde genellikle “bir zor problemi” on zor probleme çevirir.

İnsanların unutmayı sevdiği gizli maliyetler

Microservices mimari diyagramlarda görünmeyen yükler ekler:

  • Dağıtımlar: daha fazla pipeline, versionlama, rollback ve koordinasyon
  • Gözlemlenebilirlik: dağıtık tracing, log korelasyonu ve anlamlı metrikler
  • On-call yükü: daha fazla hata modu, daha fazla alarm, daha fazla olay playbook'u
  • Veri tutarlılığı: zor işlemler, eventual consistency ve karmaşık raporlama

Pratik bir kestirim

Bir modular monolith ile başlayın. Bölmeden önce gerçek baskıyı ölçün: sürüm darboğazları, modül etrafında takım çekişmesi, ölçeklenme darboğazları veya güvenilirlik izolasyonu ihtiyaçları. Bu baskılar kalıcı ve nicelenmişse, net bir sınır, atanmış sahiplik ve operasyon planı ile servisi çıkarın—sadece kod değil.

Sınırlar, Coupling ve Bağımlılıkların Gerçek Maliyeti

Üretim geri bildirimini daha erken alın
Geri bildirimi, hata oranlarını ve gerçek kullanım verilerini yönlendirmek için erken dağıtın ve host edin.

İyi mimari kaç servisin olduğuyla ilgili değil; bir parçayı değiştirmenin diğer üçünü kazara kırmadan ne kadar iyi yapılabildiği ile ilgilidir. Martin Fowler bunu sıkı bağlılık (coupling) ve birliktelik (cohesion) yönetimi olarak çerçevelendirir.

Coupling ve cohesion, jargonsuz

Bir restoran mutfağını düşünün. “Salatalar” istasyonu tutarlıysa—içindekiler, araçlar ve net bir sorumluluk varsa—uyumlu çalışır. Çok bağlı bir mutfakta salata yapmak için ızgaracı durmalı, pastacı sosu onaylamalı ve yönetici buzdolabını açmalıdır.

Yazılım da aynı şekilde çalışır: uyumlu modüller net bir işi sahiplenir; gevşek bağlı modüller basit, stabil anlaşmalarla etkileşir.

Sağlıksız coupling nasıl görülür

Sağlıksız coupling genellikle koddan önce takvime yansır. Yaygın sinyaller:

  • Koordine sürümler: “Takım B yayınlayana kadar biz yayınlayamıyoruz.”
  • Sık çapraz takım engelleri: başka bir takımın önce ‘onların’ parçasını değiştirmesi gerektiği için iş duruyor.
  • Dalga etkisiyle değişimler: küçük bir özellik birçok repo ya da serviste düzenleme gerektiriyor.

Eğer teslim süreciniz düzenli olarak grup koreografisi gerektiriyorsa, bağımlılık maliyeti zaten ödeniyor—sadece toplantılar ve gecikmeler şeklinde.

Bağlantıyı azaltan tasarım hamleleri

Bağlantıyı azaltmak bir yeniden yazımı gerektirmez. Pratik hamleler:

  • Net API'ler ve kontratlar: arayüzü bir ürün gibi ele alın; stabil ve iyi adlandırılmış olsun.
  • Bounded contexts: her alanın neyi sahiplenip neyi sahiplenmediğini ve jargonunu belirleyin.
  • Modülerizasyon: tek bir monolitte bile açık sınırlar olan modüller “mini-servis” gibi davranabilir ama operasyonel yükü artırmaz.

Kararlar önemli olduğunda, bunları küçük notlarla (ör. /blog/architecture-decision-records) yakalayın ki sınırlar kasıtlı kalsın.

Veri: en zor sınır

Paylaşılan veritabanları “gizli” coupling yaratır: herhangi bir takım bir tabloyu değiştirip herkesi kazara bozabilir. Paylaşılan DB genellikle servislermiş gibi görünen yapıları bile koordine sürümlere zorlar.

Daha sağlıklı yaklaşım veri sahipliğidir: bir sistem veri setinin sahibi olur ve bunu bir API veya eventlerle açığa çıkarır. Bu bağımlılıkları görünür kılar—dolayısıyla yönetilebilir hâle getirir.

Mimari Sosyaldir: Takımlar Sistemleri Şekillendirir

Yazılım mimarisi sadece kutular ve oklar değildir. Aynı zamanda insanlarla ilgilidir: işin nasıl bölündüğü, kararların nasıl alındığı ve gerçeklikle tasarım uyuşmazsa bir ekibin ne kadar hızlı tepki verebildiği. Bu sosyo-teknik mimaridir—sistem yapınızın genellikle takım yapınızı yansıtma eğiliminde olduğu fikri.

Organizasyon şeması tasarımla savaşınca

Yaygın başarısızlık modu kâğıt üzerinde “temiz” sınırlar çizmek ama günlük iş akışının bunları çiğnemesidir. Sistem teknik olarak derlenip deploy edilebilir ama değiştirmek pahalı hissedilir.

Uyumsuzluğun işaretleri:

  • Sık el değiştirmeler (“Takım A onaylamalı, sonra Takım B deploy eder, sonra Takım C izler”)
  • Belirsiz sahiplik (“Bu endpointin sahibi kim?” “Biz değiliz.”)
  • Uyarılar, loglar ve düzeltmeler birçok takımı kapsadığı için yavaş olay yanıtı
  • Yol haritalarının birçok grubu senkronize sürümlere bağımlı kılması

Sürtünmeyi azaltmak için pratik yollar

Sahiplikle başlayın, mükemmellikle değil. Takımların gerçekçi olarak nasıl çalışabileceğiyle uyuşan sınırlar belirleyin.

  • Modülleri/servisleri takımlarla hizalayın: bir takım beş başkasına koordinasyon gerektirmeden anlamlı bir değişiklik yapabilmeli.
  • Sorumluluğu netleştirin: her bileşeni kimin inşa ettiği, çalıştırdığı ve iyileştirdiğini tanımlayın (on-call ve operasyon bütçeleri dahil).
  • Handoff'ları sınırlayın: takımların bağımsız hareket etmesini sağlayan stabil kontratları, iyi tanımlanmış API'leri ve gerektiğinde ortak standartları tercih edin.

Kısıtlar hakkında gerçekçi kalmak

Bazen takımları yeniden düzenleyemezsiniz, legacy modülü bölemezsiniz veya darboğazları işe alarak çözemezsiniz. Bu durumlarda mimariyi bir pazarlık olarak değerlendirin: en maliyetli koordinasyonu azaltan sınırları seçin, özerkliği açığa çıkaracak refaktoringe yatırım yapın ve teknik/organizasyonel borcu öderken geçici tavizleri kabul edin.

Kararları Görünür Kılın: Basit Mimari Karar Kayıtları

Yazılım mimarisi sadece inşa ettikleriniz değildir—yolda verdiğiniz kararlardır. Mimari Karar Kayıtları (ADRs), bu kararları bağlam hâlindeyken yakalayan kısa notlardır.

ADR nedir (ve ne değildir)

ADR, “Ne karar verdik ve neden?” sorusunu cevaplayan tek sayfalık bir nottur. Uzun bir tasarım dokümanı değildir ve bir izin belgesi değildir. Takım için kalıcı bir hafıza olarak düşünün.

Neler dahil edilmeli

İnsanların hızlıca tarayabilmesi için yapı tutarlı olsun. Hafif bir ADR genellikle şunları içerir:

  • Karar: ne seçildi (ör. “v1 için modular monolith kullan”)\n- Bağlam: çözülmesi gereken problem ve kısıtlar\n- Alternatifler: tartışılan 2–3 gerçekçi seçenek\n- Sonuçlar: ödünleşmeler—ne kolaylaşıyor, ne zorlaşıyor\n- Tarih ve durum: önerildi/kabul edildi/yerine geçti\n- Sahipler: kararı yönetenler (suçlayacak kişi değil)

Neden buna değer

ADRs, yeni ekip üyelerinin sadece sonuca değil mantığa da ulaşmasını sağlar ve aynı sorunun tekrar tekrar tartışılmasını önler: aynı soru aylar sonra tekrar geldiğinde ADR'i güncelleyip yeniden değerlendirebilirsiniz. En önemlisi ADR'ler ödünleşmeleri açık hâle getirir—gerçeklik değiştiğinde planı revize etmek daha kolay olur.

Hafif tutun

Basit bir şablon kullanın, ADR'leri kodun yanında saklayın (örneğin, /docs/adr/) ve bir tane yazmak için 10–20 dakika hedefleyin.

# ADR 012: API versioning strategy
Date: 2025-12-26
Status: Accepted
Owners: Platform team

Context:
We need to evolve public APIs without breaking partners.

Decision:
Adopt URL-based versioning (/v1/, /v2/).

Alternatives:
- Header-based versioning
- No versioning; rely on backward compatibility

Consequences:
+ Clear routing and documentation
- More endpoints to support over time

Eğer bir ADR evrak işi gibi geliyorsa, kısaltın—alışkanlığı bırakmayın.

Sürekli Teslim ve Geri Bildirim: Evrimin Motoru

Monolit varsayılanını test et
Bir modular monolith prototipi oluşturun ve her şeyi microservices'e oynamadan güvenle yineleyin.

Mimari bir kez çizildi diye “iyi” kalmaz. Sistem küçük adımlarla, gerçek dünya baskısı altında güvenle değişebildiğinde iyi kalır. Bu yüzden continuous delivery (CD) ve hızlı geri bildirim döngüleri önemlidir: bunlar evrimi riskli bir olaydan normal bir alışkanlığa çevirir.

CI/CD refaktoringi pratik kılar

Refaktoring en kolay küçük ve geri alınabilir değişikliklerle yapılır. Sağlam bir CI/CD pipeline'ı her değişikliği kullanıcıya ulaşmadan önce otomatik olarak build, test ve doğrulayarak bunu destekler. Pipeline güvenilir olduğunda ekipler sürekli tasarımı iyileştirebilir; asla “büyük yeniden yazım” beklemezler.

Değişimi engelleyen değil destekleyen kalite kapıları

Kalite kapıları hızlı, tutarlı ve önem verdiğiniz sonuçlarla bağlantılı olmalı. Yaygın kapılar şunlardır:

  • Otomatik testler (unit + integration) iç değişikliklerken davranışı sabit tutmak için
  • Riskli desenleri erken yakalamak için statik analiz (karmaşıklık, güvensiz çağrılar, bağımlılık sorunları)
  • Beklenmedik açıklıkları önlemek için güvenlik kontrolleri (bağımlılık taraması, temel SAST)

Amaç mükemmellik değil; kırıcı değişikliklerin maliyetini yükseltirken güvenli iyileştirmelerin maliyetini düşürmektir.

Gözlemlenebilirlik mimari geri bildirimi

İyi mimari kısmen üretimde sistemin ne yaptığını bilmekle ilgilidir. Geri bildirim olmadan tahminlerle optimize edersiniz.

  • Loglar olaylar sırasında ne olduğunu söyler.
  • Metrikler eğilimleri gösterir: hata oranları, gecikme, kuyruk derinliği, doygunluk.
  • Traceler servis sınırları boyunca zamanın nereye gittiğini ortaya çıkarır.

Bu sinyaller olduğunda, mimari kararları görüş yerine kanıtla doğrulayabilirsiniz.

Güvenli sürüm: korkmadan gönderin

Evrim sık yayınlama gerektirir; bu yüzden kaçış kapıları olmalı. Feature flag'ler deploy ile release'i ayırmanızı sağlar. Canary release'ler küçük bir kitleye açarak etkisizlik alanını sınırlar. Açık bir rollback stratejisi (veritabanı dikkate alınarak) hataları kurtarılabilir hâle getirir.

Koder.ai gibi snapshot ve rollback destekleyen bir uygulama platformu kullanıyorsanız, aynı ilkeyi ürün dağıtım katmanında pekiştirebilirsiniz: hızlı hareket edin, ama tersine alınabilirlik ve operasyonel güvenliği varsayılan yapın.

Bir araya geldiğinde, CI/CD artı geri bildirim, sürekli evrilebilen bir sistem yaratır—tam da trendlerin ötesinde kalan mimari türü.

Martin Fowler’ın Fikirlerini Bu Çeyrekte Uygulamak İçin Pratik Kontrol Listesi

Bir yeniden yazıma ihtiyacınız yok; tekrarlanabilir birkaç alışkanlığa ihtiyacınız var ki tasarım sorunları görünür, geri alınabilir ve sürekli iyileştirilebilir olsun.

Hızlı kontrol listesi (planlamada kullanın)

  • Açıklık: Yeni biri sistemin ana sorumluluklarını bir sayfada açıklayabiliyor mu? Değilse, her ana alan için kısa bir README ekleyin ve sistemin “şeklini” yazın.
  • Sınırlar: Modüller/servisler net sahiplik ve amaç sahibi mi, yoksa paylaşılan veritabanları, yardımcı bucketlar ve “tanrı” paketleri mi var? Güçlendirmek için bir sınır seçin.
  • Testler güvenlik için: Refaktoringi korkusuz yapacak hızlı testler var mı? En çok değişen kod etrafında ince ama yüksek değerli kapsamı önceliklendirin.
  • Dağıtım: Küçük değişiklikleri sık deploy edebiliyor musunuz? Yayınlar acı vericiyse, yeni mimari karmaşıklık eklemeden önce deploy'u sıkıcı hâle getirmeye odaklanın.
  • Sahiplik: Kimin neyi bakım yaptığı net mi? Mümkünse kod sınırlarını takım sınırlarıyla hizalayın ve bu eşlemeyi açık yapın.

30/60/90 günlük iyileştirme planı

İlk 30 gün: Bir “sıcak nokta” seçin (yüksek değişim, sık olay). Bir karakterizasyon test paketi ekleyin, bir bağımlılık zincirini sadeleştirin ve yeni değişiklikler için hafif karar notları yazmaya başlayın.

60 gün içinde: Sorunlu bir dikişi refactor edin: bir modül çıkarın, bir arayüz tanımlayın veya kalıcılık/mesajlaşma gibi altyapı kaygılarını bir sınırın arkasına izole edin. Değişikliklerin “patlama yarıçapını” azaltın.

90 gün içinde: Teslim döngünüzü iyileştirin. Daha küçük pull request'ler, daha hızlı buildler ve öngörülebilir bir yayın takvimi hedefleyin. Microservices düşünüyorsanız, bir sınırın mevcut kod tabanı içinde yönetilemeyeceğini göstererek ihtiyacı kanıtlayın.

(Eğer hedefiniz daha az el değiştirerek daha fazla ürün göndermekse, otomasyonun nerede yardımcı olacağını değerlendirin. Bazı takımlar için chat-tabanlı bir build iş akışı sağlayan Koder.ai—planning mode, kaynak dışa aktarma, dağıtım/hosting, özel alanlar ve ücretsizden enterprise'a kademeli fiyatlandırma—mekanik yükü azaltıp mimari dikkatini sınırlar, testler ve operasyonel geri bildirime odaklamanıza yardımcı olabilir.)

Çabayı değil sonuçları ölçün

Aylık birkaç sinyali takip edin:

  • Lead time: commit'ten üretime kadar geçen süre
  • Değişiklik başarısızlık oranı: rollbackler, hotfixler
  • Olay hacmi ve tekrarlayan nedenler

Bunlar iyileşmiyorsa planı ayarlayın—mimari ancak değişimi daha güvenli ve ucuz hâle getirdiğinde “daha iyi” olur.

Yığınlar değişmeye devam edecek. Temeller—net sınırlar, refaktoring disiplini ve hızlı geri bildirim—kalıcıdır.

SSS

Bir teknoloji yığını ile yazılım mimarisi arasındaki fark nedir?

Mimari, daha sonradan değiştirmesi zor ve maliyetli olan kararlar bütünüdür: sınırlar, veri sahipliği, entegrasyon tarzı ve hata yönetimi.

Bir tech stack ise bu kararları uygulamak için kullandığınız araçlardır (frameworkler, kütüphaneler, bulut hizmetleri). Birçok aracı sınırlı etkiyle değiştirebilirsiniz; ancak sınırları veya veri akışını değiştirmek çoğu zaman haftalar süren koordineli bir çalışmayı gerektirir.

Bir kararın “mimari” mi yoksa sadece uygulama detayı mı olduğunu nasıl anlarız?

Geri alınabilirlik iyi bir testtir: bir kararı geri almanın haftalar sürecek ve birden çok takımın koordinasyonunu gerektirecek olması, bunun mimari bir karar olduğunu gösterir.

Örnekler:

  • Mimari: “Faturalama kendi verisine sahip olacak ve asenkron eventler üzerinden entegre olacak.”
  • Uygulama detayı: “PDF oluşturmak için Kütüphane X kullanacağız.”
Tasarım kalıplarını ne zaman kullanmalı, ne zaman aşırı mühendislik oluyor?

Kalıpları, belirli tekrar eden bir problemi çözüyorlarsa kullanın; tasarımı “profesyonel” göstermek için değil.

Hızlı seçim kontrol listesi:

  • Kolaylaştırmaya çalıştığınız değişiklik nedir?
  • Hangi yeni karmaşıklığı (ek katmanlar, dolaylılık) getiriyorsunuz?
  • Bugün için en basit uygun kalıp hangisi ve seçenekleri açık tutuyor mu?

Sorunu net tanımlayamıyorsanız, kalıbı eklemeyin.

Refactor yapmanın vakti geldiğini gösteren en güvenilir işaretler nelerdir?

Refaktoringi, gerçek sürtünle ilişkilendirilmiş rutin bakım olarak ele alın; nadiren yapılan “temizlik projeleri” olarak değil.

Yaygın tetikleyiciler:

  • Farklılaşmaya başlayan çoğaltmalar
  • “Her şey her şeye dokunuyor” bağımlılık zincirleri
  • Basit değişikliklerin beklenmedik kırılmalara yol açması

Güvenli yapmak için testler, küçük adımlar ve sıkı kod incelemeleri kullanın.

Tesnis teknik borcu yönetirken teslimatı durdurmadan nasıl ilerleriz?

Borcu bir maliyet olarak takip edin; utanç verici bir sır gibi değil.

Pratik yönetim yolları:

  • Her yinelemede küçük, sabit bir zaman ayırın
  • Tüm kod tabanı yerine sıcak noktalar üzerinde odaklanın (yüksek değişim, yüksek olay alanları)
  • Borcu özellik işiyle birlikte geri ödeyin, böylece “faiz” bileşmez

Kararları görünür yapın (örneğin hafif ADR’lerle).

Pratikte “evrimsel mimari” ne anlama gelir?

Pratikte, gereksinimler doğrulanana kadar yön değiştirebileceğiniz şekilde tasarlamaktır; uzun vadeli tahminlere tam olarak yatırım yapmak yerine değişimi kabul etmek.

Tipik bileşenler:

  • Açık sınırlar ve sahiplik
  • Değişikliği düşük riskli kılan otomatik testler
  • Küçük, sık sürümleri destekleyen teslimat uygulamaları

Amaç uyum sağlayabilmek, önceden mükemmel bir plan yapmak değil.

“Fitness functions” nedir ve hangi fonksiyonlarla başlamalıyız?

Fitness fonksiyonu, bir mimari hedefi koruyan otomatik bir korumadır.

Yararlı örnekler:

  • Build/test süresi bir bütçeyi aşıyorsa CI'da başarısız say
  • Hata oranı belirlenen eşik üzerinde ise dağıtımı engelle
  • Kritik güvenlik açıkları için bağımlılık taraması zorunlu kıl
  • İç/dış istemcileri kırmamak için sözleşme testleri uygula

Taahhütlerinizi (değişim hızı, güvenilirlik, güvenlik) yansıtan birkaçını seçip sürekli çalıştırın.

Monolit, modular monolit ve microservices arasında nasıl seçim yapmalıyız?

Varsayılan olarak bir modular monolith ile başlayın; bağımsız deploy gereksiniminin ölçülmüş, kalıcı baskısı olmadan microservices'e geçmeyin.

Microservices genelde işe yarar hale gelirken şunlara ihtiyaç vardır:

  • Net, kararlı sınırlar ve veri sahipliği
  • Hizmetleri uçtan uca sahiplenebilen takımlar
  • Güçlü gözlemlenebilirlik ve sürüm uygulamaları

Eğer tek bir servisi üretimde rahatça çalıştıramıyorsanız, on tane yapmak genellikle acıyı katlayacaktır.

Bağımlılık ve coupling ağrısını en hızlı nasıl azaltırız?

Bağımlılıkları görünür ve kasıtlı hale getirmeye başlayın.

Etki yüksek hamleler:

  • Modüller arası stabil API'ler/kontratlar tanımlayın
  • Açık sahiplik atayın (bir takım bir sınırı ve evrimini sahiplenir)
  • Paylaşılan veritabanlarından kaçının; veri sahipliğini API veya eventlerle açığa çıkarın

Paylaşılan DB’ler “gizli coupling” yaratır ve sistemler ayrı görünse bile koordineli sürümleri zorunlu kılar.

ADRs yazmanın sebebi nedir ve ne kadar detaylı olmalılar?

Mimari Karar Kayıtları (ADRs), ne karar verildiğini ve nedenini bağlam hâlindeyken yakalar.

Hafif bir ADR şunları içerir:

  • Karar, bağlam, alternatifler, sonuçlar
  • Tarih/durum (kabul/yerine geçti)
  • Sahipler

Kodun yanında saklayın (örneğin, /docs/adr/) ve ilgili rehberliği /blog/architecture-decision-records gibi notlarla ilişkilendirin.

Related posts