Aspect Oriented Programming
Uygulamalarımızı geliştirirken kodun; okunabilirliği, bakımı (maintability), modülaritesi, tekrar kullanılabilirliği (reusability) gibi pek çok kavram üzerinde çalışmaktayız. Her ne kadar bunlara dikkat etmeye çalışsak da proje büyüdükçe, kod blokları uzadıkça da kodun okunması, bakımı vs. zorlaşabiliyor. Bu tarz durumlarda hızlı, temiz ve tekrar kullanılabilir çözümler üretmenin yolu Aspect Oriented Programming’den geçmektedir.
Aspect Oriented Programming (AOP) Nedir?
AOP, yazılımın karmaşıklığını azaltmaya, modülariteyi artırmaya yarayan bir yaklaşım biçimidir. Buradaki modülariteden kasıt uygulama süresince sistemin birçok bölümünde kullanılan, fonksiyonel olmayan kodun yani kesişen ilgilerin ufak ufak parçalara ayrılmasıdır (Seperation of Cross Cutting Concerns). Bu sayede uygulama genelinde kullanılacak olan yapıları, sistemden soyutlamış olup enkapsüle de ederek birçok yerde kullanılmasını sağlar. Genel olarak AOP bir sorunu çözmektense var olan sistemin daha güzel bir hale getirilmesini de sağlamaya yardımcı olur denilebilir.
Cross Cutting Concerns Nedir?
Cross Cutting Concerns’ün Türkçe anlamına bakacak olursak “Kesişen İlgiler” ya da “Çapraz Kesen İlgiler” diye geçmektedir. Yandaki fotoğrafa bakacak olursak da konunun anlaşılması ve devamlılığı için daha sağlıklı olacaktır. Yanda klasik bir monolitik yapı görünmektedir ve sağ kısımda Cross Cutting Concerns çatısı altında; security, caching, exception handling, logging gibi işlemler yer almaktadır. Bunların hepsi birer Concern yani ilgidir. Cross Cutting Concerns denmesinin sebebi projeyi dikine kesmesinden kaynaklı, dikine kesmesinin altında yatan anlam ise katman bağımsız, projenin istenilen yerinde kullanılması, kullanılan yerden soyutlanmış olmasından kaynaklıdır. Özetle yazılımın birden fazla yerinde kullanılan, fonksiyonel olmayan ihtiyaçlar denilebilir.
Buraya kadar olan bilgiler ile AOP’un çıkış noktasının Cross Cutting Concerns’ler olduğunu söylemek yeridir. Cross Cutting Concerns’ler olmasa idi AOP’a ihtiyaç yoktur denilebilir.
Konunun daha da anlaşılması için teorik anlatımın yanı sıra örnek üzerinden ilerlenmesinde de fayda var.
Yukarıda bir adet silme işlemini gerçekleştiren metot görünmektedir. Metot içeriğini incelediğimizde sürecin devamlılığı için exception handling (istisna işleme), gelen parametrenin doğrulaması daha sonra da doğrulama durumuna göre veri tabanından silme, cache (ön bellek) temizlenmesi gibi işlemler yapılmış. Bu işlemleri gerçekleştiren yapılar da DI (Dependency Injection) yardımı ile de tanımlanmış durumdalar.
Metot davranışını inceleyecek olursak yapması gereken asıl şey veri tabanından ilgili kaydın silinmesi yönündedir. Diğer işlemler:
- Log (Kayıt tutma): Olası bir hata sonucunda alınan kayıtlara bakılarak ilgili yerin tespit edilmesi ya da ilerleyen zamanda iyileştirilmelere gidildiğinde toplanan kayıtlar üzerinden inceleme yapılması vb. gibi işlemler için gereklidir.
- Validasyon (Doğrulama): Verinin doğrulanması için gerekli olan bir işlemdir.
- Exception Handling (İstisna işleme): Bir hata durumunda sistemin devamlılığını sağlamak için gerekli olan işlemdir.
Asıl işlemimizin veri tabanından kayıt silmesi olduğu halde bir sürü operasyonel işlemler gerçekleştiriyoruz. Bunların yanı sıra yetkilendirme kontrolü gibi diğer işlemler de işin içerisine girince kod blokları gittikçe uzuyor, okunması zorlaşır bir hale geliyor ve bu işlemler sadece bir metot içerisinde gerçekleştirildi. Diğer iş süreçlerinde de bu tür işlemler gerçekleşeceği için kodların tekrarı da artacaktır. Bu tür durumlarda yazının baş kısımlarında da dediğimiz gibi AOP’tan faydalanmaktayız. Kesişen ilgileri ufak ufak modüllere ayırarak gerek sistemden soyutluyoruz gerek de implementasyonundaki karmaşıklıkları enkapsüle ediyoruz. Bu sayede birden fazla yerde kullanılmak üzere ufak ufak modüller elde ediyoruz.
Yukarıdaki metot içerisindeki asıl işe odaklandığımızda metot aşağıdaki şekilde durmaktadır. Nasıl da sade ve kendini ifade ediyor. Diğer işlemler başka yerlerde de kullanılmak üzere ayrıldı.
Yukarıdaki tanımlamada metottan soyutlanan modüllere de bakıldığı zaman birer attribute (C# dili için attribute denilmektedir. Java, PHP gibi dillerde annotation olarak adlandırılmaktadır.) olarak tanımlandı. Bu modüllerin çalışması bir Interceptor sayesinde gerçekleşmektedir.
Interceptor Nedir, Nasıl Çalışır?
İş ihtiyaçlarına göre; metoda girmeden önce, işlem bittikten sonra, hata durumunda gibi durumlarda araya girerek istediğimiz müdahaleyi yapabilmemizi sağlar. Bu araya girme işlemleri Compile-Time (Derleme Zamanı) veya Run-Time (Çalışma Zamanı) olmak üzere iki farklı yönden gerçekleştirilebilir.
- Compile-Time (Derleme Zamanı): Yazdığımız modüllere ait kodlar, uygulama derlendiği zaman çalışılması istenilen kod bloğu içerisine yerleştirilir.
- Run-Time (Çalışma Zamanı): Burada ise işlemler çalışma zamanında gerçekleşmektedir.
Bu interceptor altyapısını sağlamak için yazılmış birçok kaynak kod da mevcuttur. Aşağıda bazı diller için yazılmış olan interceptor kütüphanelerini bulabilirsiniz:
- .NET:
- Java:
- PHP:
Yukarıdaki bilgilere ek olarak sağladığı faydalara tekrar değinecek olursak:
- Kod tekrarını önledik. Başka yerlerde kullanılacak modüler bir yapı elde ettik.
- Kod karmaşasını engelleyerek daha okunaklı kodlar elde ettik.
- Bakımı basitleştirdik.
Bu yazıda AOP’un ne olduğuna, faydalarına, hangi durumlarda kullanıldığına ve bazı dillerde AOP’u uygulamak için kullanılan araçlara değindik.