Bir programın evrenini küçük bir laboratuvar gibi düşünün. Masanın üzerinde girdiler var: sayılar, metinler, listeler, belki biraz kullanıcı verisi. İşlevsel programlama bu laboratuvara beyaz önlükle girer ve şöyle der: Bana ne verdiysen, ona karşılık ne üreteceğimi söyleyeyim; ama deney tüplerini gizlice değiştirmem, rafları karıştırmam, geçmişi yeniden yazmam, geleceğe mayın döşemem. Kulağa ahlaki bir manifesto gibi geliyor, fakat aslında son derece pratik bir mühendislik tavrıdır.
İşlevsel programlamanın merkezinde saf fonksiyon fikri durur. Saf fonksiyon, aynı girdiye her zaman aynı çıktıyı verir ve bunu yaparken dış dünyada hiçbir şeyi değiştirmez. Matematikteki f(x) gibi: f(2) her çağrıldığında başka bir ruh hâline bürünüp bazen 4, bazen 7, bazen de veritabanındaki kullanıcıları silmez. Bu sadelik, kodun tahmin edilebilir olmasını sağlar. Tahmin edilebilir kod ise gecenin üçünde kahveyle hata ayıklayan geliştiricinin sinir sistemine yapılmış bir iyiliktir.
Yan etki: Kodun kelebek etkisi
Yan etki, bir fonksiyonun çıktı üretmenin dışında bir şey yapmasıdır: global değişkeni değiştirmek, dosyaya yazmak, ekrana basmak, ağ isteği göndermek, veritabanına kayıt atmak. Bunların hepsi kötü müdür? Elbette hayır. Programlar sonuçta dünya ile konuşmak zorundadır. Bir e-ticaret sistemi sipariş oluşturacak, bir oyun ekrana karakter çizecek, bir mesajlaşma uygulaması bildirim gönderecektir. Sorun yan etkinin varlığı değil, kontrolsüzlüğüdür. Yan etki evin içindeki kedi gibidir: sevimlidir, gereklidir, ama nerede ne devireceğini bilmezseniz sabah vazo kırıklarıyla uyanırsınız.
İşlevsel yaklaşım, yan etkileri yok saymaz; onları sınırlar, görünür kılar ve mümkün olduğunca kenarlara iter. Çekirdekte saf dönüşümler vardır: veri gelir, veri gider. Dış dünya ile temas eden kısımlar ise kabuğa alınır. Böylece sistemin kalbi deterministik kalır. Bu mimari, özellikle büyük yazılımlarda zihinsel yükü azaltır. Çünkü bir hatayı ararken bin farklı yerde değişmiş olabilecek gizli bir durum labirentine girmek yerine, girdiden çıktıya uzanan açık bir yol izlersiniz.
Durumu dondurmak, düşünceyi özgürleştirmek
İşlevsel programlamanın güçlü araçlarından biri değişmezliktir. Değişmez veri yapıları, bir değerin oluşturulduktan sonra yerinde değiştirilmemesi anlamına gelir. İlk bakışta garip gelebilir: Bir listeye eleman eklemek istiyorsam neden aynı listeyi güncellemeyeyim? Çünkü güncellenen şey yalnızca liste değildir; onu okuyan herkesin varsayımı da güncellenir. Paylaşılan durum, yazılım dünyasının dedikodu kazanıdır. Kim ne zaman neyi değiştirdi, belli değildir.
Değişmezlik, geçmişin sabit kalmasını sağlar. Bir fonksiyon eski listeyi alır, yeni liste üretir. Eski liste hâlâ oradadır, geleceğe dair suç ortaklığı yapmaz. Bu, özellikle eşzamanlı ve paralel programlamada büyük avantajdır. Birden fazla işlem aynı veriyi okuyabilir; çünkü kimse onu gizlice değiştirmeyecektir. Kilitler, yarış durumları, beklenmedik çakışmalar azalır. Kod, kavga eden iş parçacıkları pazarı olmaktan çıkıp düzenli bir orkestraya yaklaşır.
Saflık dogma değil, tasarım pusulasıdır
Elbette gerçek dünyada tamamen saf program yazmak neredeyse imkânsızdır. Kullanıcıdan veri almak, zamanı okumak, rastgele sayı üretmek, dosya kaydetmek: bunlar doğası gereği yan etkilidir. İşlevsel programlamanın olgun yorumu, saflığı bir din kuralı gibi değil, tasarım pusulası gibi kullanır. Amaç şudur: Saf kalabilecek yerleri saf tut, kirli işleri açıkça işaretle, karmaşayı merkezden uzaklaştır.
Bu yüzden Haskell gibi diller yan etkileri tip sistemiyle kontrol altına alırken, JavaScript, Python, Scala, F# veya Elixir gibi diller de işlevsel fikirleri farklı ölçülerde benimser. map, filter, reduce gibi fonksiyonlar yalnızca şık oyuncaklar değildir; veriyi dönüştürmeyi ifade etmenin berrak yollarıdır. Döngü içinde değişkenleri itip kakmak yerine, ne yapılmak istendiğini daha doğrudan anlatırlar.
Sonuçta işlevsel programlama bize yalnızca kod yazma tekniği öğretmez; düşünme disiplini öğretir. Bir şeyi değiştirmen gerçekten gerekiyor mu? Bu fonksiyonun görünmeyen bir bedeli var mı? Aynı girdiye aynı cevabı verebiliyor musun? Geçmişi kurcalamadan, geleceği ipotek etmeden, yalnızca mevcut veriye dürüstçe tepki verebiliyor musun?
İyi yazılmış saf bir fonksiyon, küçük bir bilgelik nesnesidir. Ne dram çıkarır, ne dedikodu yapar, ne de arkasında dumanlı bir yan etki bırakır. Girdi gelir, çıktı gider. Evren biraz daha anlaşılır olur.