AOP – Aspect Oriented Programming hemen hemen her yazılımıcnın defalarca işittiği ve üzerinde en az bir kere konuştuğu bir konudur . Ancak ya hiç kullanılmamıştır ya da kullanılırken farkına varılmamıştır. Örneğin bir çoğumuz Spring Framework bileşenlerini kullanırız. Ancak Spring’te temel özellik olarak kullanılan AOP mekanizmasını ve/veya paradigmasından haberdar değilizdir.
Peşinen söyleyeyim, uzun bir yazı olacak. Aslında Enterprise Java kitabımın Spirng AOP konusundaki AOP paradigmasının anlatıldığı bölümdür.
AOP paradigma olarak OOP için çok önemli bir yere sahip olsa da ülkemizde gerek çeviri, gerek anlatım olarak biraz eksik kalındığından meraklı gözlerden hep uzak kalmıştır. Gelin sizlerle 10-15 dakikalık bir AOP yolculuğu yapalım.
Modül, uygulamaya ait benzer davranışları taşıyan bileşenleri bir araya getiren küçük alt parçacıklar olarak düşünülebilir. Projelerde, proje paketlerini oluştururken model, dao, util, test gibi paketler oluşturarak içlerinde benzer davranışları taşıyan sınıflar geliştirilmektedir.
Örneğin dao paketi içerisinde veri tabanı işlemlerini yapan sınıflar yerleştirilmektedir. Bu paket büyüdükçe davranış olarak benzer operasyonlarla yani veri tabanı işlemleri ile ilgilenen dao katmanları karşımıza çıkmaktadır. Burada asıl amaç benzer davranışlarla ilgilenen uygulama parçalarını ayrı modüller olarak ele almaktır. Böylece okuma, yönetim kolaylaşacak ve uygulama esneklik kazanacaktır.
Burada dikkat çekici nokta ilgi’dir. Benzer davranışlar benzer ilgilerden doğar. Şöyle ki veri tabanı işlemlerini yapan sınıfların hepsi veri yönetme işlemi ile ilgilenirler. Yani benzer davranış sergilerler. Bu benzer davranış ilgi alanlarının aynı veya ortak olmasından kaynaklanmaktadır. Veri yönetimi ile ilgilenmeyen bir sınıfın veri tabanı işlemlerine ait bir metod taşıması beklenemez. (en azından ortalama güzellikteki bir tasarım içerisinde)
Separation of Concerns, dilimize genelde ilgilerin ayrışması olarak çevrilir, bence davranışların ayrıştırılması olarak çevrilmelidir. Uygulamanın belirli davranışlar baz alınarak paketlere ya da modüllere ayrılması yöntemine genel olarak davranışların ayrıştırılması denilebilir. Bu ayrışma atomik düzeyde metod tasarımından başlayarak ele alınmalıdır.
Proje paketlerinin model, dao, util gibi kavramlar etrafında ayrıştırılması davranış, ayrıştırma yönteminin en temel düzeydeki kullanımıdır. Böylece az çok yazılımdan anlayan biri proje paketlerini incelediğinde kabaca hangi pakette neler bulabileceğini kestirebilecektir. Bu ayrıştırmayı gerçek ve ciddi büyüklükte bir projede üzerinde hayal edersek.
Proje bileşenleri yani modülleri,
olarak sıralanabilir.
Bunlar da makro düzeydeki ayrıştırmadır. 1000’lerce sınıftan oluşan bir projede 50-100 tane log sınıfı, 150-200 tane dao, 100-150 tane service bileşenine ait sınıfa sahip projeler yukarıdaki birçok özelliğe sahip olacaktır. Bu katmanlardan bir kaçını inceleyelim.
DAO katmanı Transactiona sahip olmalıdır. Transaction, veri yönetiminden sorumlu değildir. Transaction verilerin güvenli şekilde kaydedilip, silinmesinden sorumludur. Veri yönetimi işlemlerinin doğruluğunu garanti etmek için kurulan yapılardır. Veri yönetiminden aslında, esasında DAO katmanı sorumludur. Ancak yönetimde hata olmaması için Transcation mekanizmasına sahip olması gerekmektedir.
O zaman elimizde iki davranış var bir tanesi veri yönetimi diğeri veri yönetim güvenliğidir. İşin ilginçleştiği nokta ise bu iki davranışın birbirleri ile sıkı etkileşim içerisinde olmalarıdır. Transaction veri güvenliğinden emin değilse DAO katmanındaki yapılan işlemler veri tabanına kaydedilmeyebilir. Transaction mekanizması bunu engeller. Burada yolların kesişmesi durumu söz konusudur. Bazen de bir modül diğerinin yolunu keser.
Loglama, örneklerden biliyorsunuz log4j2 apisini kullanılabilir. Loglama davranışı genelde bu api yardımı ile çözülmektedir. Uygulamaların birçok yerinde metodların loglanma ihtiyacı olduğunda bu apiye ait metodlar ile loglama yapılmaktadır. O zaman loglama modülleri ile uygulamanın da yollarının kesişmesi söz konusudur.
Hata yönetimi, birçok projede exception handlig mekanizması kurulmaktadır. Hata yönetimi ile uygulamanın yolları sadece kesişmiyor bazen hata yönetimi uygulamanın yolunu bile kesecek duruma gelebiliyor. Bunlara benzer örneklemeleri yukarıdaki tüm proje bileşenleri için yapabiliriz.
Görüntüde sol tarafta JDBC ile sağ tarafta ise JPA ile veri tabanı işlemi yapılan iki örnek yan yana yer almaktadır. Her ikisinde de DAO katmanında belirli aralıklarla; Transaction Managment, Logging ve Exception Handling yapılmış olmasıdır. Bu yapılar bir şekilde metodların asıl operasyonlarının arasına girerek operasyonların davranışlarına etki etmektedirler.
Buradaki dikkat edilecek nokta tüm bu davranışlar Java nesne yaratma ve yönetme mantığı içerisinde sınıf ya da metod içerisinde doğrudan tanımlıdırlar ve çağrıldıkları sıra ile çalışırlar. Örneğin loglama mekanizmasının metodlarda kullanılması için sınıf içerisinde bir log nesnesi yaratılmış durumdadır ve sırası gelince çalışacaktır. Normal Java akış mantığında metodlar yukarıdan aşağıya satır satır çalıştırılacak ve sonuç döndürülecektir.
Görüntüdeki metodlar yüklendikleri operasyonların yani asıl amaçlarının dışına çıkarak,
akışına giriyorlar.
Böyle bir akış içerisinde metodtan beklenen asıl işlev veriyi sadece ve sadece veri tabanına kaydetmesidir. Bu akışta metod odak noktasından uzaklaşmış birçok işlevi yapmak zorunda bırakılmıştır. Burada fazla olan her bir davranış o metoda yüklenen ilgi – endişe kaynaklıdır. Metod transaction, loglama ve hata ayıklama gibi birçok farklı operasyonla ilgilenmek ya da onlar hakkında endişelenmek zorunda kalmıştır. OOP paradigması burada çözüm üretmekte güdük kalmaktadır.
Kod Saçılması, bir davranışın birden çok metodta, sınıfta veya modülde kullanılması durumudur.
Kod Dağılması, birden çok davranışın aynı metod sınıf veya modül kullanılması durumudur.
Yukarıdaki görüntü baz alınarak Jpa ve Jdbc yapıları kabaca incelendiğinde, Metodlarda Kod Dağılması durumu söz konusudur. Yani neredeyse tüm metodlarda görüntüdeki akışa benzer bir yapı uygulanmaktadır. Bu yapıda metodlara “ilgilerine – endişelerine” göre davranışlar eklenmiştir.
İlgi veya endişeden kasıt metodların operasyonlarını tamamlarken garanti etmek zorunda oldukları yan etkiler veya operasyon aşamalarının bir geçmişidir. Bunlar ile metodun operasyonu başarı ile tamamlayıp tamamlamadığından emin olabilmekteyiz.
Metodlar
OOP içerisinde bu akış tüm JDBC ve JPA modülleri boyunca uygulanabilir. Projeler büyüdükçe bu kurgunun getireceği yük de artacaktır. Kötü senaryoda kaosa doğru bile gidebilir. OOP içerisinde Separation of Concerns, “davranışları ayrıştıran” modüler yapılar kurularak bile bu işi çözmek mümkün görünmüyor
Crosscutting Concerns
Enine Kesen İlgiler diye dilimize çevrilmektedir. Ben kesişen davranışlar olarak yorumlamayı tercih ediyorum. Concerns kelimesi çevrisi bire bir olarak endişe ve türevleri şeklinde olmaktadır. Bu çeviriden yola çıkarak birkaç tanımlama yapalım.
Şeklindeki ilgi odaklı anlatımlar yaygın iken.
Şeklindeki iki tanımlamadan hangisi programatik iş akışını daha net ifade etmektedir?
Crosscutting Concerns kesişen ilgiler olarak çevrilebilir. Ancak bu konu anlatılırken her yerde ilgi kelimesinin kullanılmasını özellikle metodların ihtiyaç duydukları davranışlardan ilgi diye bahsedilmesi bana çok doğru gelmiyor.
Evet metodlarda bir ilgi oluşuyor. Bu o metodun ihtiyaç duyduğu davranışa olan ilgisidir. Davranışa vurgu yapmadan yapılan her enine kesen, kesişen ilgiler tanımlaması eksik gibi geliyor.
Örneğin loglama bir ilgi değil, bir davranıştır. Metod ya da sınıfın bu davranışa ihtiyacı varsa loglamaya ilgi duyduğu söylenebilir. Ancak ilgi, metod içerisinde loglamanın yaptığı işi ve önemini açıklamada yetersiz kalacaktır. Tanımı toparlarsak…
Kesişen Davranışlar, Modüler tasarlanarak geliştirilmiş birimler veya metodlar farklı davranışlara ilgi duyabilirler. Bu davranışlar, yapısal olarak ilgili birimlerin operasyonlarında değişime neden olabilirler.
Örneğin veri kaydetme başarısız olduğunda transaction mekanizması devreye girerek tüm değişikliklerin geri alınmasını sağlayabilir. Bu sonucu değiştiren bir müdahaledir.
Ya da veri kaydetme işlemi başarılı olduğu anda metodtan çıkılmaz yani metod sonlanmaz. Metod veri kaydetme işleminin başarılı olduğunu log olarak yazar ve öyle sonlanır. Bu da sonucu değiştirir. Etkisi az da olsa metod veri kaydetme yanında bir de log üretmek zorunda kalmaktadır.
Her iki senaryoda da metodun işlevi sona erdi. Ancak tüm davranışlar beklenildiği gibi yerine getirilmeden metodtan çıkamıyoruz. (hadi bu son cümlede davranış yerine ilgi diyelim, cuk oturur mu?)
Bu fazla davranışların doğrudan ilgili metod tarafından çalıştırılması gerekmektedir. Bu kesişim davranışları OOP altında modüler tasarlanıp geliştirilen projelerde bile net olarak çözülememektedir. Kesişme çözülemediği gibi metodlar veya sınıflar karmaşıklaşarak okuma kalitesi azalmaktadır. Kod kalitesi azaldığında ise uygulama kalitesi için zorunlu olması gereken her türlü esnek yaklaşım stratejisi geçersiz olacaktır. Bu nokta da farklı bir programlama paradigması olan AOP, Aspect Oriented Programming devreye girmektedir.
Aspect Oriented Programming, ilgiye yönelik programlama olarak dilimize çevrilmektedir. Aspect kelimesini birde google‘a soralım.
Bu çevirideki Türkçe anlamları beri kenara bırakalım ingilizce tanımlayıcı olarak verilen kelimelerde bile bir tane ingilizce ilgi var mı? Eskiden cephe yönelimli programlama diyenler de vardı. Cephenin, ilgiye yönelik programlamadan daha iyi durduğu kesin. Hatta biraz böyle OOP’a yeni bir paradigma getirdiğinden cephe açmış, cepheden yaklaşıyor gibi bile düşünülürse ilginden çok çok daha iyi ifade ediyor. Concern’e yeniden bakalım.
Burada ilgi geçiyor. Ancak ilgi en yaygın olanı değil. Tüm anlamlar toparlandığında bir kaygı veya endişe durumu hakimdir.
Tercüme sana ilgilerim var demiyor. Bu kelimelere daha üst pencereden bakılarak incelendiğinde. Çevirilerin toplamında davranışsal bir durum ortaya çıkar. Ve bu Türkçe’ye doğrudan çevrilecekse bence ilgilerin ayrışması değil endişelerin ayrışması olmalıdır.
Çünkü uygulama veya metod kendisine verilen işlevi yerine getirebilecek mi getiremeyecek midir? Bu işlevi tamamlamak için sahip olduğu bileşenlerin doğru çalışıp çalışmadığından ya da bu bileşenlerin kendi çalışmasını etkileyip etkilemeyeceğinden endişe mi duyar ilgi mi duyar?
Aspect Oriented Programming, bence cephe yönelimli programlama olarak düşünmek daha güzeldir. Çünkü AOP paradigmasında modüllere eklenecek bileşenler modüllerin doğrudan parçaları olmayacaklar. Kendilerine verilen görevi yapıp çıkacaklar. Bakıp çıkacağım abi durumu…
Neden bu konuya takıldım? Kavramlara yüklenen anlamlar yaptıkları işi tam karşılamadığında konu güdük kalıyor. Programcı bir uygulamayı geliştirirken herhangi bir paradigmadan yararlanmak istiyor. Ancak paradigma kafasında bir türlü oturmuyor. Oturmayınca en yol bildiğin yol deyip eski usul devam ediyor. O zaman yine yeniden voltron voltron … diyelim ve toparlayalım.
Birbirinden farklı işlevler yürüten ancak kesişen davranışların birbirlerinden ayrışması metodolojisine AOP denilmektedir.
AOP, yukarıda sıralanan birçok işlevin ayrı ayrı tasarlanarak sadece gerektiğinde uygulama ile ahenk içinde çalıştırılabilmesi yöntemidir. Burada her uygulama birimi, Aspect olarak tasarlanmış herhangi bir modülü istediği zaman edinip kullanabilir.
Bu sıralanan işlevlerin ilginç bir yönleri daha var, dikkatiniz çekti mi? Bu işlevler herhangi bir uygulamadaki en genel yani en generic özellikleri ifade ediyorlar. Yani hemen hemen her uygulamanın ihtiyaç duyabileceği bileşenlerdir. Herhangi bir uygulamanın birden çok yerinde, defalarca kullanılmaları gerekebilir.
Bu özellikler için güzel bir tasarım ile yapılacak her geliştirme bizleri büyük iş kaybından kurtaracaktır. Örneğin öyle bir tasarım yapmalıyız ki, uygulamadaki metodlar loglama işlevini sürekli çağırarak kullanmak zorunda kalmasın.
Bu durumda Loglama ve operasyon modülleri kardeş kardeş çalışsınlar. Olabilir mi? Göreceğiz…
10 Comments
İngilizce seviyesi beginner olan benim için, programlama öğrenmeye çalışırken karşılaştığım her şeye özet geçmiş yaramın tam ortasına dokunmuşsunuz.Şu an ağlıyorum…
Ben sizleri sevindirmek için yazmıştım ama. Sanırım seninkiler de sevinç göz yaşları 🙂
Başarılar dilerim, umarım faydalı olmuştur.
Hocam en keyifli yerinde bitirmişsiniz makaleyi 😀 Umarım devam vardır veya gelir 🙂
Emeğinize sağlık.
Teşekkürler, bu bölüm Enterprise Java kitabımızın AOP konusundan alıntılanmıştı. Yani devamı onun içerisindeydi. Güncellediğimizde inşaallah yenisinin içerisinde de bulabilirsiniz.
Konuyu güzel özetlemişsiniz, tebrikler
Teşekkürler
her cümleyi tekrar tekrar okudum gerçekten çok teşekkürler. kodlamaya başlamadan önce soru işaretlerini ortadan kaldırmış oldum
ilginize ben teşekkür ederim, başarılar
Her kelimeyi teker teker okudum hocam. Bizler için ilham kaynağısınız yazılazırınıznz devamını bekliyorum. Dört gözle
nazik düşünceleriniz için çok teşekkürler