TEKNİK YAZI / NOTLAR

Functional Programming: Kod Yazmanın Matematiksel Sanatı

Functional Programming nedir? Neden önemli? Imperative programlamadan farkları ve modern yazılımdaki yeri.

Functional programming, hesaplamayı değişen durum ve komut dizileri yerine fonksiyon bileşimi ve veri dönüşümleri üzerinden modelleyen bir programlama yaklaşımıdır. Saf fonksiyonlar, değişmez veri ve yan etkilerin sınırlandırılması; özellikle test edilebilir iş kuralları kurarken yararlı araçlar sunar.

Functional Programming Nedir?

Functional Programming (FP), programlamayı matematiksel fonksiyonlar gibi düşünmemizi sağlayan bir paradigma. Klasik imperative programlamada “bilgisayara ne yapması gerektiğini adım adım söylüyoruz”. FP’de ise “ne istediğimizi tanımlıyoruz” ve nasıl yapılacağını sistem hallediyor.

Düşünün ki yemek tarifi yazıyorsunuz. Imperative yaklaşım: “Soğanı al, doğra, tavaya koy, kavur…” FP yaklaşımı: “Kavrulmuş soğan = soğan → doğrama → kavurma”. İkinci yaklaşımda sürecin kendisiyle değil, dönüşümlerle ilgileniyorsunuz.

Temel Prensipler

Immutability (Değişmezlik): FP’nin belki de en önemli prensibi. Bir kere oluşturduğunuz veriyi değiştirmezsiniz, yeni veri oluşturursunuz. Bu başta garip gelebilir ama düşünün - matematik’te x=5 dedikten sonra x’i değiştirmezsiniz değil mi? Aynı mantık.

Pure Functions: Saf fonksiyonlar, aynı input için her zaman aynı output’u veren ve hiçbir side effect’i olmayan fonksiyonlar. Mesela sin(30) her zaman 0.5’tir. Database’e yazmaz, global değişken değiştirmez, console’a print etmez. Sadece hesaplar ve döner.

First-Class Functions: Fonksiyonlar birinci sınıf vatandaş. Yani fonksiyonları değişkene atayabilir, parametre olarak geçebilir, return edebilirsiniz. JavaScript’te alışıksınız zaten - callback’ler, event handler’lar hep bu konsepti kullanıyor.

Higher-Order Functions: Fonksiyon alan veya fonksiyon dönen fonksiyonlar. map, filter, reduce bunların en bilinen örnekleri. Kendi abstraction’larınızı oluşturmanızı sağlıyor.

Neden Functional Programming?

Predictability: Pure function’lar test etmesi çok kolay. Input → Output, bu kadar. Mock’lama, spy’lama derdi yok. Unit test cennetine hoş geldiniz!

Concurrency: Immutable data ve pure function’lar sayesinde race condition, deadlock gibi sorunlar yok. Multi-core processor’ları efektif kullanmak için ideal.

Modularity: Küçük, composable fonksiyonlar yazarsınız. Lego gibi birleştirip complex sistemler oluşturursunuz. Reusability tavan yapıyor.

Debugging: Side effect yok, state mutation yok. Bir fonksiyon beklediğiniz gibi çalışmıyorsa, sadece o fonksiyona bakmanız yeterli. Başka yerleri etkilemiyor çünkü.

Imperative vs Functional: Farkı Görelim

Diyelim ki bir liste içindeki çift sayıların karesini almak istiyorsunuz.

Imperative yaklaşım düşüncesi: “Boş liste oluştur, döngü kur, her elemanı kontrol et, çiftse karesini al, listeye ekle…”

Functional yaklaşım düşüncesi: “Sayıları filtrele (çift olanları al) → Dönüştür (karesini al)”

İkinci yaklaşım çok daha declarative değil mi? Ne istediğinizi söylüyorsunuz, nasıl yapılacağıyla uğraşmıyorsunuz.

Basit Örnekler

// Pure function example
const add = (a, b) => a + b; // Always returns same result for same inputs

// Higher-order function
const twice = fn => x => fn(fn(x));
const addOne = x => x + 1;
const addTwo = twice(addOne); // Creates new function that adds 2

// Composition
const compose = (f, g) => x => f(g(x));
const addThenMultiply = compose(
  x => x * 2, // second operation
  x => x + 10 // first operation
);

Gerçek Dünyada Functional Programming

“Tamam güzel de, gerçek projede nasıl kullanacağım?” diye soruyorsunuz değil mi? İşte pratik kullanım alanları:

Data Transformation: API’den gelen veriyi UI için hazırlamak. map, filter, reduce chain’leri ile temiz ve okunabilir kod.

Event Handling: RxJS gibi kütüphaneler, event stream’lerini functional olarak işlemenizi sağlıyor. Observable pattern’i FP’nin güzel bir uygulaması.

State Management: Redux, Elm Architecture gibi pattern’ler pure function’lar üzerine kurulu. Predictable state updates!

Data Processing: Big data, stream processing. Apache Spark, Kafka Streams hep functional konseptler kullanıyor.

Common Patterns

Map-Filter-Reduce: FP’nin üç silahşörü. Neredeyse her data transformation problemi bunlarla çözülür.

Recursion: Loop yerine recursion. FP dillerinde tail call optimization sayesinde stack overflow riski yok.

Currying: Fonksiyonları parçalara bölmek. Partial application yapabilir, reusable fonksiyonlar oluşturabilirsiniz.

Monads: Karmaşık görünse de aslında basit - side effect’leri kontrollü şekilde handle etmenin yolu. Maybe monad null check’leri, IO monad input/output işlemlerini zarif hale getirir.

FP’nin Zorlukları

Her şey güllük gülistanlık değil tabii:

Learning Curve: Özellikle imperative background’dan geliyorsanız, düşünce yapınızı değiştirmek zaman alıyor.

Performance: Bazen immutability maliyetli olabiliyor. Her seferinde yeni array/object oluşturmak memory kullanımını artırabilir.

Debugging: Stack trace’ler karmaşık olabiliyor. Özellikle çok fazla higher-order function chain’i varsa.

Team Adoption: Takımın tamamını ikna etmek zor olabilir. “Niye böyle yapıyoruz?” sorusuna hazırlıklı olun.

Hangi Dilleri Öğrenmeli?

Pure FP Dilleri: Haskell (akademik ve finans), Elm (web frontend), Clojure (JVM üzerinde), F# (.NET ekosistemi)

Multi-Paradigm Diller: JavaScript (FP feature’ları güçlü), Python (functools ile), Scala (OOP + FP), Kotlin (modern FP desteği)

Tavsiyem: JavaScript’te başlayın. Zaten biliyorsunuzdur, FP konseptlerini öğrenmek için yeterli. Sonra Elm veya Clojure’a geçin.

FP vs OOP: Hangisi Daha İyi?

Klasik soru! Cevap: İkisi de. Farklı problemler için farklı paradigmalar uygun.

FP İyi Gelir: Data transformation, parallel processing, complex business logic, mathematical computation

OOP İyi Gelir: UI modeling, game development, simulation, enterprise systems with complex entity relationships

Modern trend: İkisini birleştirmek. React (FP component + hooks), Redux (FP state management), Domain Driven Design (OOP modeling + FP business logic).

Real World Success Stories

WhatsApp: Erlang kullanıyor (functional, concurrent). 50 engineer ile milyarlarca mesajı handle ediyor.

Facebook: React ve Flux/Redux. UI state management’ı FP ile çözdüler.

Twitter: Scala ile backend. FP sayesinde massive scale’de çalışıyor.

Jane Street: Trading firm, everything in OCaml. FP’nin correctness garantileri finansta kritik.

Başlamak İçin İpuçları

  1. Küçük başlayın: Her şeyi FP yapmaya çalışmayın. Önce utility function’larınızı pure yapın.

  2. Immutability alışkanlığı: Spread operator (…), Object.assign, array method’ları kullanın.

  3. Side effect’leri izole edin: Business logic’i pure tutun, I/O işlemlerini boundary’de yapın.

  4. Test yazın: Pure function’lar test etmesi çok kolay. TDD için ideal.

  5. Compose etmeyi öğrenin: Küçük fonksiyonları birleştirerek büyük çözümler oluşturun.

Sonuç

Functional programming bütün sistemi tek bir paradigmaya zorlamak zorunda değildir. Saf hesaplamaları I/O sınırlarından ayırmak, veriyi yerinde değiştirmemek ve küçük dönüşümleri birleştirmek; nesne yönelimli veya prosedürel bir kod tabanında da hata yüzeyini daraltabilir. Amaç belirli bir stile bağlılık değil, davranışı daha açık ve test edilebilir hâle getirmektir.