Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Functional Programming'in Sınırları: Performans, Okunabilirlik ve Ekipte Pragmatik Kullanım
Functional programming'in C#'taki bedeli çoğu zaman sanıldığı yerde değil: ölçümde LINQ küçük bir sepette döngüden nanosaniyeler düzeyinde yavaş, Option'ın maliyeti struct ya da class olmasından çok closure'lardan geliyor, beklenen hatayı exception ile taşımak ise Result'tan yüz kat pahalı. BenchmarkDotNet sonuçlarını, composition'da stack trace sorununu, ekipte kazandıran ve tartışmalı fikirleri, F#'ı ve Bookstore'un son hâlini gösteriyoruz.
C# 15 Union Types ve Closed Hierarchies: Gerçek Sum Type ve Exhaustive Pattern Matching
C# 15'in union type'ları birbirinden bağımsız tipleri kapalı bir küme olarak birleştirir, closed modifier'ı ise bir class hiyerarşisinin doğrudan alt tiplerini assembly ile sınırlar; ikisinde de derleyici eksik case'i adıyla söyler. Bookstore'un OrderStatus'unu closed hiyerarşiye, Result ve hata kodlarını union'a çeviriyor, System.Text.Json'un iki yapıyı nasıl serialize ettiğini, TypeScript ile farkları ve public API'de binary breaking change riskini gerçek çıktılarla gösteriyoruz.
Result ve Railway-Oriented Programming: Hatayı Değer Olarak Taşımak ve Validation Biriktirmek
Railway-oriented programming, başarısız olabilen adımları Bind ile iki raylı bir akışa bağlar: bir adım hata verirse sonrakiler çalışmaz ve hata sonuna kadar değer olarak taşınır; birbirinden bağımsız form alanlarında ise hatalar biriktirilir. Bookstore'un sipariş akışını Map, Bind, Ensure, Tap ve Match ile kuruyor, Task<Result<T>> zincirlerini, TypedResults ve ValidationProblem eşlemesini, Angular tarafındaki UI state'ini ve exception ile Result sınırını gerçek çıktılarla gösteriyoruz.
Option ve Null'dan Kaçış: Maybe Tipi, Map, Bind ve LINQ Query Syntax'ın Sırrı
Option, "değer yok" durumunu bir tip olarak ifade eder ve değere ulaşmadan önce "yoksa ne olacak?" sorusunu cevaplamaya zorlar; nullable reference types çoğu yerde yeterliyken Option zincirleme hesaplamada ve iç içe "yok" anlamlarında fark yaratır. Bookstore'un kupon hesabını kendi Option<T>'imizle Map, Bind ve Match üzerinden kuruyor, Select/SelectMany ekleyince LINQ query syntax'ın neden çalıştığını ve monad'ın map + flatten sezgisini gösteriyoruz.
Algebraic Data Types: Product ve Sum Type, Discriminated Union ve "Illegal State'i Temsil Edilemez Yap"
Algebraic data type, tipleri "ve" ile (product type) ya da "veya" ile (sum type) birleştirerek modeldeki kombinasyon sayısını iş kuralındaki durum sayısına eşitler; böylece imkânsız durum oluşturulamaz. Bookstore'un bayraklı sipariş durumunu abstract record ile sum type'a çeviriyor, geçişleri tiplerle yazıyor, C# 14'ün neden _ kolu istediğini, TypeScript discriminated union'ı, JSON polymorphism'i ve C# 15 union type'larını gerçek derleyici çıktılarıyla gösteriyoruz.
Higher-Order Function ve Composition: map/filter/reduce, Currying ve Pipeline Kurmak
Higher-order function fonksiyon alan ya da döndüren fonksiyondur; composition ise bunları birbirine bağlayıp yeni fonksiyon üretmektir ve sırası bir iş kuralıdır. Bookstore'un kupon ve üye indirimini Func<decimal, decimal> kuralları olarak Then, Compose ve Pipe ile birleştiriyor, sıranın sonucu 1,50 TL değiştirdiğini test ediyor; fold'u, currying'i, TypeScript pipe'ını ve closure allocation maliyetini gerçek çıktılarla gösteriyoruz.
Pure Function ve Side Effect: Referential Transparency, Gizli Girdiler ve Test Edilebilirlik
Pure function aynı girdiye her zaman aynı sonucu veren ve dışarıda iz bırakmayan fonksiyondur; böyle bir çağrı döndürdüğü değerle yer değiştirebilir. Türkçe culture'da 189.50'yi 18950 okuyan decimal.Parse'tan başlayıp Bookstore'un indirim hesabını saat, console ve static state'ten ayırıyor, xUnit Theory ile fake'siz test ediyor, memoization'ı ve Angular computed() ile pure pipe'ın purity varsayımını gerçek çıktılarla gösteriyoruz.
Immutability: Neden Değişmeyen Veri? C# record, readonly ve TypeScript Readonly ile Pratikte
Immutability, bir değerin oluşturulduktan sonra değiştirilememesi ve her değişiklikte yeni değer üretilmesidir; aliasing, kaybolan cache key ve race condition sorunlarını aynı yerden çözer. Bookstore'un sepetini record, with ve ImmutableList ile yeniden yazıyor; shallow immutability'yi, kopyalama maliyetini, TypeScript readonly ve Object.freeze sınırlarını ve yerinde push edilen array'in Angular signal'ini neden güncellemediğini gerçek çıktılarla gösteriyoruz.
Functional Programming Nedir? C# ve TypeScript Geliştiricisi İçin Declarative Düşünce
Functional programming, hesaplamayı değerleri adım adım değiştiren komutlar yerine değer alıp değer döndüren fonksiyonların birleşimi olarak kurmaktır. Bookstore'un sepeti sessizce değiştiren ödeme kodu üzerinden imperative ile declarative farkını, first-class function'ı, kısa tarihçeyi ve LINQ, RxJS ile Angular signal'lerinde zaten kullandığın functional fikirleri gerçek çıktılarla gösteriyoruz.
Refactoring Kataloğu 7: Inheritance ile Çalışmak — Pull Up/Push Down, Extract Superclass, Replace Type Code with Subclasses ve Replace Subclass with Delegate
Inheritance refactoring'leri ortak kodu base class'a çıkarır, yanlış yere çıkanı geri indirir ve inheritance'ın sınırına çarpıldığında onu delegation ile değiştirir. Yazıda Bookstore'un kitap ve istek listesi class'ları on bir refactoring'le dönüştürülüyor; List'ten türeyen bir class'ın gizlediği Add'i atlayan çağrılar, Push Down'da derleyicinin gösterdiği yer ve TPH tablosundaki discriminator gerçek çıktılarla gösteriliyor ve seri 66 refactoring'in tamamıyla kapanıyor.
Refactoring Kataloğu 6: API'yi Refactor Etmek — Separate Query from Modifier, Remove Flag Argument, Parameterize Function, Factory Function ve Command
API refactoring'leri bir class'ın dışarıya açtığı method'ları daha açık, daha güvenli ve daha kolay test edilir hâle getirir; ama paket olarak dağıtılan bir API'de varsayılan değerli bir parametre eklemek bile yeniden derlenmeyen kodu kırar. Yazıda Bookstore'un Notifications module'ü on iki refactoring'le dönüştürülüyor; [Obsolete] ile korunan eski sözleşme, CS0200 ve CS0618 çıktıları ve yeni DLL ile çalışan eski uygulamanın MissingMethodException'ı gerçek çıktılarla gösteriliyor.
Refactoring Kataloğu 5: Koşulları Sadeleştirmek — Decompose/Consolidate Conditional, Guard Clauses, Replace Conditional with Polymorphism ve Introduce Special Case
Koşul refactoring'leri karmaşık if'leri adı olan fonksiyonlara, guard clause'lara, switch expression'a ya da polymorphism'e çevirir; null kontrollerini kaldıran bir special case ise kontrolün sessizce koruduğu yan etkiyi de kaldırabilir. Yazıda Bookstore'un CheckoutPolicy class'ı yedi refactoring'le dönüştürülüyor; dotnet format'ın IDE0066 çıktısı, testler yeşilken misafire 12 puan gösteren special case ve Release build'de kaybolan Debug.Assert gerçek çıktılarla gösteriliyor.