Tasarım Kalıpları: Proxy (Vekil) – I

Tasarım kalıpları üzerine olan ilk yazıda şöyle demiştik: “Tasarım kalıpları, temel nesne-merkezli prensipleri kullanarak doğru sorumlulukları bulmamıza (finding responsibilities), değişimi göz önüne alarak bu sorumlulukları nesnelere dağıtmamıza (highly-cohesive objects) ve nesneleri, aralarında az bağımlılık olacak şekilde (lowly-coupled objects) kurgulamamıza yardımcı olur. Bir başka deyişle tasarım kalıpları, yüksek birliktelikli ve düşük bağımlılıklı yapıları nasıl kurgulayacağımızı, sıklıkla karşılaşılan problemler bağlamında, model olarak ortaya koyar.”

Şimdi de bu cümleyi daha iyi hazmetmek için, Proxy ya da Vekil kalıbımızı ele alalım. Malum “proxy” İngilizce’de vekil demek. Burada da vekalet kavramı üzerine kurgulanan bir yapı söz konusu. Vekil kalıbı ile yapmak istediğimiz şey, “herhangi bir sebepten dolayı bir nesneye olan erişimi kontrol etmektir”. Nitekim GoF’da da bu kalıbın amacı şöyle ifade ediliyor:

“Provide a surrogate or placeholder for another object to control access to it.”

Yani

“Kendisine erişimi kontrol etmek için bir nesneye geçiş sağla”.

Burada elimizde, kendisine erişimi, herhangi bir sebepten dolayı kontrol etmek istediğimiz bir nesne söz konusudur. Bu nesne çok değerli ya da çok tehlikeli olduğu için kendisine ulaşımı kontrol etmek isteyebiliriz. Yani kimse bu nesneye doğrudan ulaşmasın, arada ulaşımı sağlayan bir elçi, geçiş sağlayan nesne olsun isteriz. Ya da GoF’da anlatıldığı gibi bellek ve CPU açısından pahalı olan bir nesnenin oluşturulmasını, gerçekten o nesneye ihtiyaç duyuncaya kadar geciktirmek ama aynı zamanda sistemin sanki bu nesne zaten varmış gibi davranmasını isteyebiliriz. Örneğin, uygulamalarınızın “Help” dokümanlarını düşünün. Sistem ayağa kalkarken bu dokümanın da yüklenmesini istemezsiniz ama sistemin bundan haberdar olmamasını ve sanki bu doküman varmış yani yüklenmiş gibi davranmasını istersiniz. Tüm bu gibi durumlar, esas nesneye erişimi kontrol etmek için farklı sebepler demektir.

Şimdi bu kalıbı daha iyi anlayabilmek için, ihtiyacımızın ortaya çıktığı bir durumu anlatalım:

Malum, demokrasilerde halklar kendilerini, seçtikleri vekiller yardımıyla yönetirler. Dolayısıyla vatandaşın, kendisini yönetenlere erişme hakkı vardır. Erişilecek en tepe seçilmiş yönetici ise başbakandır. Yani vatandaşların başbakana erişimleri olmalıdır, bu onların hakkı, başbakanın ise sorumluluğudur. Buraya kadar tamam ama her önüne gelenin doğrudan başbakana erişebilir durumda olması çok da arzu edilen bir durum değildir. Örneğin böyle bir durum başbakan açısından güvenlik problemi oluşturduğu gibi, örneğin ülkemizde milyonlarca vatandaşın olduğu göz önüne, alınırsa pratik de değildir. Bu durumda başbakana erişimi kontrol etmemiz gereklidir fakat bunu yaparken vatandaşların rahatsız olmasını da engellememiz önemlidir.

Yukarıdaki problemde başbakan nesnesine erişimi, bu nesnenin hem değerli olmasından hem de erişecek nesnelerin sayıca çok olmasından dolayı, kontrol etmek istiyoruz. Dolayısıyla bu problemi vekil kalıbı yardımıyla çözmek için sorumluluklardan başlayarak ilerleyelim. Sorumluluklar nelerdir?

  • Başbakan, vatandaşın derdini dinlemek ve ona iş bulmak (:) ) gibi iki sorumluluğa sahip olsun.
  • Vatandaş da başbakana derdini anlatmak ve ondan iş istemek gibi iki sorumluluğa sahip olsun.

Buraya kadar kolay. Yukarıdaki sorumluluklardan Başbakan ve Vatandaş isimli iki nesneye ihtiyacımız olduğunu çıkarabiliriz. Yani şöyle bir sınıf diyagramına sahibiz:

Proxy0

Bu yapıdaki problem, Başbakan‘ın korunmuyor olmasıdır. Bu “korunmama” durumundan dolayı, Vatandaş, örneğin pek çok Başbakan nesnesi oluşturabilir. Başbakan‘ı singleton yaparak bunun önüne geçebiliriz ama aynı anda binlerce, milyonlarca Vatandaş nesnesinin Başbakan‘a gelişi güzel erişmesini engelleyemeyiz. Burada bir engelleyici, daha doğru ifadeyle kontrol edici, filtreleyici bir yapıya ihtiyaç vardır öyle ki Başbakan‘ın kimle hangi şartlar altında konuşacağı belirlenebilsin. Örneğin, Başbakan nesnesinin, her gün aksam saat 10:00 ile 12:00 arasında Vatandaş‘ların derdini dinlemek istemesi ama herhangi bir iş isteğini dinlemek istememesini nasıl bu yapıyla halledebiliriz? Eğer düzgün bir nesne kültürümüz yok ise, bu tür kontrolleri ya Vatandaş ya da Başbakan nesnesine, muhtemelen Başbakan‘a koyma eğiliminde oluruz. Bu ise problemli bir durumdur çünkü bu sorumluluk ikisinin de sorumluluğu değildir. Aşağıda resmedilen bu durumda Başbakan’ın koduna sıklıkla müdahele edilmesi gerekecektir. Her halükarda bu yapı, ne sorumlulukları ayırmakta ne de değişimi yönetmektedir.

Proxy1

Bu durumla ilgili bir başka problem hem Başbakan‘ın hem de kontrol yapısının zaman zaman değişeceği gerçeğidir. Yani örneğin Başbakan bir yurt dışı gezi yapacağı hafta rahatlıkla, “bu hafta dert dinleyemeyeceğim” diyebilir. Dolayısıyla bu yapıda en sık değişecek kısım bu kontrol mekanizmasıdır. Bu durumda kontrol sorumluluklarını arada bir nesneye yükleyip, bu nesnenin Vatandaş ile Başbakan arasında bir tampon oluşturması makul görünebilir. Bu durumda şöyle bir yapıya ulaşırız:

Proxy2

Bu yapının en büyük problemi ise, bu kalıbın amacına tamamen ters düzen bir durum: Vatandaş, Başbakan ile konuşmuyor, Vekil ile konuşuyor ve bu durum problemde bahsettiğimiz demokrasinin en temel şartını ihlal ediyor.

Açıkçası olması gereken durumda, Vatandaş, Başbakan ile konuştuğunu düşünmeli ama biz hala Başbakan‘ı korumalıyız. Bu duruma ancak Başbakan ile Vekil‘in aynı görünmelerini sağlayarak ulaşabiliriz. İki nesnenin aynı görünmesi ise arayüzlerinin aynı olması ve polymorphism sayesinde birbirleri yerine geçebilmeleriyle mümkün olur. Yani Vekil ve Başbakan, aynı arayüzü devralmalıdırlar. Yani, aşağıdaki gibi bir yapıya sahip olmalıyız.

Proxy3

Bu sınıf diyagramına göre, Vatandaş, Başbakan arayüzünü bilmekte ve onun bir nesnesiyle konuşmaktadır. Lakin, BaşbakanlıkVekili, Vatandaş‘a konuşması için GerçekBaşbakan‘ın bir nesnesini değil, VekilBaşbakan‘ın nesnesini geçmektedir. Bu durum, bize hem Vatandaş‘ın Başbakan‘la konuşmuş olmasını sağlayacak hem de GerçekBaşbakan‘ı korumamıza imkan verecektir çünkü Vatandaş, gerçekte VekilBaşbakan‘la konuşmaktadır. Bu yapıda VekilBaşbakan da yukarıda bahsettiğimiz, kontrol sorumluluklarını yerine getirecektir. Yani aslında GerçekBaşbakan‘ın neyi ne zaman dinleyeceğini belirleyen nesne VekilBaşbakan‘dır. Bu yüzden VekilBaşbakan, GerçekBaşbakan’ın nesnesine sahiptir ve kontrol kuralları çerçevesinde Vatandaş‘tan kendisine gelen istekleri, GerçekBaşbakan‘a iletecektir.

Bir sonraki yazıda bu çözümün kodlarına bakalım.

 

Bu yazı toplam 1247 defa görüntülenmiştir.