Method Dispatching: Giris

0 1.666

Class, struct objesine ait bir metot çağrıldığında acaba runtime’da neler yaşanıyor?

İlk olarak, neden böyle bir yazı yazmaya karar verdiğimden bahsetmek istiyorum. Apple’ın Swift diline ait her gelişmeyi bildirdiği proposal listesinden Enum cases as protocol witnesses başlıklı değişimi incelerken “witness table” adında ve daha önce duymadığım bir kavram ile karşılaştım. Bu kavramı öğrenmeden proposal’a dair aklımda fikir oluşmayacağını anlayınca araştırmaya başladım ve method dispatching kavramı ile karşılaştım.

Bu kavramı araştırmak, (Xcode) kod yazma sürecinde kullandığım; final, @objc, private vb. keywordlerin kullanım amaçlarını, extension’da yarattığım fonksiyonları neden override edemiyor olduğumu ve dahası yazılım geliştirirken kullandığım ama çalışma mantığını tam olarak öğrenmemiş olduğum birçok konuyu anlamamı sağladı. Bunların yanında Object Oriented Programming’e çok yüzeysel yaklaştığımı, inheritence kavramının arka planı konusunda deneyimsiz olduğumu gördüm ve eksiklerimi gidermeye başladım.

Bu noktada; bir dilin gelişimini takip ederek güncel kalmanın yanında, eskiye yönelik bilgilerin temelini sonradan da olsa öğrenmek önemlidir/mümkündür diyebilirim. Bir yazılım dili ya da herhangi bir projenin gelişimini takip edebilmek için repoyu fork ederek, belirli aralıklarla repoları eşitleyip, farkları inceleyebilinir.

Dispatch

Öncelikle “dispatch” kelimesini anlayarak başlayalım. Dispatch, bir şeyi bir amaç uğruna bir yere gönderme anlamında kullanılır. Bilgisayar bilimlerinde, bir çağrının fonksiyona gönderilmesi, bir event’in listener’a gönderilmesi, bir process’in CPU’ya gönderilmesi gibi terimler olarak karşımıza çıkmaktadır.

Konumuz özelinde dispatch; bir nesne üzerinden nesnenin ait olduğu class veya super class’ının herhangibir fonksiyonunun çağırılma sürecinde, memory’deki hangi adrese gidilip executable-code’un çalıştırılacağına karar verme işlemidir. Executable-code’un adresinin CPU’ya verilmesi, dispatching işleminin amacıdır. Bu işlem her metot çağırımında gerçekleşir.

Metotlar yalnızca küçük kod parçaları gibi görülmemelidir. Metotlar, sınıflar arası iletişim, durum değişiklikleri, iş logicleri gibi durumları düzenlerler. Alt sınıf üst sınıftan miras aldığı metotları override ederek logicleri değiştirebilir ve bunu bir kapsül gibi gizler(Encapsulation). Bu şekilde hem benzer özellikleri tekrar tekrar yazmadığımız gibi hem de farklılıkları diğerlerinden gizleyebiliriz. CPU bir işlemi çalıştırabilmek için öncelikle onun adresine sahip olmayı bekler. Ardından bu adrese zıplayarak işlemi gerçekler. CPU’ya çalıştırması gereken metot dispatch edilerek bildirilir.

Günlük hayattan bir örnek ile beslemeye çalışalım. Bir yazılım şirketini düşünelim. Yapılması gereken bir iş ve bu işe ait ekran tasarımları mevcut. Ancak 3 farklı tasarım olduğunu hayal edelim. İşe başlayan yazılımcıya da sprint başında hangi tasarımın uygun olduğu birkaç gün içerisinde iletileceği söylenmiş olsun. Yazılımcının geliştirme sürecini “runtime” olarak düşünebiliriz. Yazılımcı geliştirme sürecinde servis fonksiyonları entegre etmiş, testleri sonucunda düzgün çalıştığını görmüştür ve sıra ön yüzü giydirmeye gelmiştir. Burada elindeki çeşitli tasarımlar da “metot” olarak düşünülebilir. Yazılımcı hangi tasarımı geliştirmesi gerektiğini ürün sahibine sorar ve cevabını alır. Bu işlemi de method dispatching olarak düşünebiliriz. Örneğimizdeki rolleri tekrar terimler ile eşleştirecek olursak, yazılımcı = CPU, tasarımlar = metotlar, hangi tasarımın kullanılacağı = metot dispatching şeklinde eşleştirebiliriz. Kararın ise tabiri caizse “yolda” verildiği için runtime olarak düşünebiliriz.

Senaryoyu biraz değiştirelim. Yazılımı yapılacak tasarım sprint başlamadan önce, ürün sahibi tarafından “budur” diye tek seçeneğe indirgenmiş olsun. Bu durumda tasarım seçimi statik hale gelmiş olur ve işe başlamadan karar verilmiştir. Bunu da compile time olarak düşünebiliriz.

Dispatching, Static(direct) ve dynamic(table) dispatching olmak üzere 2 tipe ayrılabileceği gibi Objective-C buraya Message Dispatching’i de ekler ve Swift dilinden Objective-C runtime’a geçebildiğimiz için Swift dili 3 dispatch tipini de destekler hale gelir.

Java

Default olarak dynamic dispatch kullanır. “final” keyword’ünü kullanarak static dispatch’i kullanmak mümkündür.

C++

default olarak direct dispatch kullanır. “virtual” keyword’ünü kullanarak dynamic dispatch’e geçmek mümkündür.

Swift

Yukarıda belirttiğimiz gibi üç dispatch tipini destekler.

Method Dispatching bir yazı dizisi olarak hayatına devam edecektir. İlerleyen makalelerde static, dinamik ve message dispatching konusuna değineceğim.

Mutlu kodlamalar 🙂

Email adresiniz yayınlanmayacaktır.