Bağımlılık yönetimi, aşağıdaki iki nedenden ötürü OOP'ta büyük bir sorundur:
- Veri ve kodun sıkı eşleşmesi.
- Ubiquitous yan etkilerin kullanılması.
Çoğu OO programcısı, veri ve kodun sıkı bir şekilde birleştirilmesinin tamamen faydalı olduğunu düşünür, ancak bunun bir bedeli vardır. Veri akışını katmanlar arasında yönetmek, herhangi bir paradigmada programlamanın kaçınılmaz bir parçasıdır. Verilerinizi ve kodunuzu birleştirmek, bir işlevi belirli bir noktada kullanmak istiyorsanız , nesnesini bu noktaya getirmenin bir yolunu bulmanız gerekecek ek sorunu da ekler .
Yan etkilerin kullanılması da benzer zorluklar yaratır. Bazı işlevler için bir yan etki kullanıyorsanız, ancak uygulanmasını değiştirebilmek istiyorsanız, bu bağımlılığı enjekte etmekten başka seçeneğiniz yok.
Örnek olarak, e-posta adresleri için web sayfalarını kazıyan ve ardından e-postayla gönderen bir spamcı program olarak düşünün. Eğer bir DI zihniyetiniz varsa, şu anda arayüzlerin arkasına yerleştireceğiniz hizmetleri ve hangi servislerin nereye enjekte edileceğini düşünüyorsunuz. Bu tasarımı okuyucu için bir alıştırma olarak bırakacağım. Bir FP zihniyetiniz varsa, şu anda en düşük fonksiyon katmanının giriş ve çıkışlarını düşünüyorsunuz:
- Bir web sayfası adresi girin, o sayfanın metnini verin.
- Bir sayfanın metnini girin, o sayfanın bağlantılarının bir listesini alın.
- Bir sayfanın metnini girin, o sayfaya bir e-posta adresi listesi verin.
- Bir e-posta adresi listesi girin, yinelenenleri kaldırılmış bir e-posta adresi listesi verin.
- Bir e-posta adresi girin, bu adres için bir spam e-posta gönderin.
- Bir spam e-posta girin, bu e-postayı göndermek için SMTP komutlarını verin.
Giriş ve çıkışlar açısından düşündüğünüz zaman, fonksiyon bağımlılığı yoktur, sadece veri bağımlılığı vardır. Onları ünite testi için bu kadar kolay kılan şey budur. Bir sonraki katmanınız, bir işlevin çıktısının diğerinin girişine beslenmesini düzenler ve gerektiğinde çeşitli uygulamaları kolayca değiştirebilir.
Çok gerçek anlamda, fonksiyonel programlama doğal olarak, fonksiyon bağımlılıklarınızı her zaman tersine çevirmenizi sağlar ve bu nedenle genellikle bundan sonra yapmak için özel bir önlem almak zorunda kalmazsınız. Bunu yaptığınızda, daha yüksek dereceli fonksiyonlar, kapaklar ve kısmi uygulama gibi araçlar daha az boylerle elde etmeyi kolaylaştırır.
Kendisinin sorunlu olan bağımlılıklar olmadığını unutmayın. Yanlış yöne işaret eden bağımlılıklar . Bir sonraki katman yukarı gibi bir işlevi olabilir:
processText = spamToSMTP . emailAddressToSpam . removeEmailDups . textToEmailAddresses
Bu katmanın, bunun gibi zor kodlanmış bağımlılıklara sahip olması tamamen iyidir, çünkü tek amacı alt kat fonksiyonlarını birbirine yapıştırmaktır. Bir uygulamayı değiştirmek, farklı bir kompozisyon oluşturmak kadar kolaydır:
processTextFancy = spamToSMTP . emailAddressToFancySpam . removeEmailDups . textToEmailAddresses
Bu kolay yeniden birleşme, yan etkilerin eksikliği ile mümkün olmaktadır. Alt katman fonksiyonları birbirinden tamamen bağımsızdır. Bir sonraki katman processText
, bazı kullanıcı yapılandırmalarına göre hangisinin gerçekten kullanılacağını seçebilir :
actuallyUsedProcessText = if (config == "Fancy") then processTextFancy else processText
Yine, bir sorun değil çünkü tüm bağımlılıklar bir yönden işaret ediyor. Hepsinin aynı şekilde işaret etmesini sağlamak için bazı bağımlılıkları tersine çevirmemize gerek yok, çünkü saf işlevler bizi zaten yapmaya zorladı.
config
Bunu en üstte kontrol etmek yerine en alt katmana geçerek daha çok birleştirebileceğinizi unutmayın . FP bunu yapmanıza engel olmaz, ancak denerseniz çok daha can sıkıcı hale gelme eğilimindedir.