Function Hooking (Hooking)
Hooking kavramı programlama dillerinde teknik bir terimdir tıpkı callback gibi. Amaç daha önce var olmuş bir methodun çalışma zamanlarının öncesinde ya da hemen sonrasında (bitiminde) bir işlem yaptırmaktır. Buna da hooking denir.
Callback'e benzer bir işlem değil mi bu ? Gibi aklınızda bir soru da oluşabilir. Benzer fakat aralarında bir takım farklılıklar vardır. Çalıştırmak istediğiniz metodun aldığı callback'in runtime'ını ayarlayabiliyor musunuz ? Sürekli olarak callback methodunu argüman olarak vermek ya da yazmak zorunda mısınız ? Gibi bir takım sorular ile farklılıkları görebilirsiniz.
Benim bildiğim hooking için pythonda 2 farklı yöntem var, biri sadece class metodları için çalışmakta diğeri ise her türlü metoda uyarlanabilir.
Örnek üzerinden gidelim daha anlaşılır olur hem neden böyle bir şeye ihtiyaç olduğunu konuya vakıf olmayan arkadaşlar da daha iyi anlamış olur.
Problem
SQL tabanlı bir veritabanı kullanan herhangi bir uygulamanın backend tarafında bir geliştirici olduğunuzu düşünün. ORM yapısında verileri veritabanına kayıt ettiriyorsunuz. Column ( fieldlarınız ) da null kabul etmiyor diyelim. Sürekli olarak gelen veri üzerinde null kontrolü yapıyor ve eğer null ise default bir değeri onun yerine koyup kayıt ettirmektesiniz. 1 tablo neyse, 2 tablo neyse ama çok daha fazla tablo var ve bazı tablolarda da çok fazla column yani doldurulması gereken fieldlar var. Bu yüzden kayıt ettirmeden önce yaptığınız bu veri kontrolü size hammallık olmakta. Çok fazla aynı işlemi yazmaktan tembelleşip hata yapacaksınız belki de...
Problemimiz daha fazla uzatılabilir ya da daha farklı bir problem üzerine de neden metod hooklamaya ihtiyacımız var olduğu da açıklanabilir. Veritabanına veri kayıt etmek herkesin sahip olabileceği türden bir problem gibi. Ayrıca eğer column null kabul etmiyorsa constraint ile null kabul etmesini sağlarım diyenler de olabiir. SQL veritabanında özellikle online sistemlerde çok büyük verilerin olduğu ve bu yüzden migrate maliyetinin çok yüksek olduğunu düşünün. Ya da takım lideriniz veya mimari yapıdan sorumlu kişinin böyle bir şart koymuş olabileceğini de düşünebilirsiniz. Problemimiz bu şekilde...
Çözüm hooking..
Method Overriding
ORM için kullandığınız kütüphanenizde save() methodunuz var. Ve bu metodu çalıştırdığınızda hangi tabloya aitse o tablonun verisi kayıt edilmekte..
Problem senaryomuzu da uyarladığımızda bu şekilde bir kod parçacığı ortaya çıkıyor. BaseModel classı aslında bizim kütüphanemize ait bir class ve onun da save adında verileri kayıt eden bir methodu var.
Person class'ı da bizim tablomuz BaseModel'dan türettik. İçerisinde de fieldlar var ve biz save metodunu override etmekteyiz. Hook olayı ise override ettiğimiz metodun içinde saklı. Parent class(BaseModel)'a ait save metodu en alt satırda çağırmaktayız ve tabi öncesinde null kontrolü yapmaktayız. Hatta işi biraz daha otomatikleştirip class'da bu fieldların tipi ne olarak saklı olup olmadığına bakıyoruz ve default değeri ona göre üretiyoruz.
Bundan sonraki kod parçacığı ise denemek için.
Sonuç:
Bütün fieldlarımı None olarak kayıt etmek istememe rağmen hookladığım ve aynı zamanda override method olan Person class'ımın içerisindeki save metodu, parent class'daki save metodunu çağırmadan önce bir takım işler yaptı ve null olayını ortadan kaldırdı. Artık hiç düşünmeden verilerimizi doldurup kayıt edebiliriz çünkü bu sorunu bir kere çözdük.
Decorators
Bu da decorator yöntemi ile aynı problemin çözümü:
on_save adındaki decoratorımız ile BaseModel.save metodunu sarmaladık aslında. BaseModel bir önceki örnekteki gibi yine kullandığımız kütüphaneye ait.
Basemodel yani kütüphanenin classındaki save metodunu mu kullanmalıyız yoksa Person gibi tablolarımızdaki metodları mı sarmalamalıyız kısmı da size kalmış oluyor. Sadece Person classı için çalışmasını istediğiniz bir hook ise sadece Person classındaki save metodunu sarmalayın gibi. Bu genel bir çözüm olduğu için en son çalışacak olan kütüphanenin metodunu sarmaladık.
İlk örnekte de genel bir çözüm yok mesela sadece Person classı içerisinde override yapılma işlemi var. Ama araya 1 class daha soksaydık o çözümü de genel bir çözüm haline getirebilirdik.
Bu da ilk çözümün genele uyarlanmış hali oldu.
Bu problem asıl metodumuz çalışmadan önce çalıştırmamız gereken işlemlerden oluşuyordu. Yine aynı şekilde asıl çalışacak metodu ilk çalıştırıp sonrasında da bir takım işlemler yaptırabilirsiniz orası size kalmış.
Esen kalın :+)
0 yorum:
Yorum Gönder