Aspect-Oriented Programming: Yazılım Geliştirmede AOP’nin Rolü ve Uygulamaları

Burak Yıldız
n11 Tech
Published in
8 min readJun 14, 2024

Aspect-Oriented Programming Nedir?

Aspect-Oriented Programming (AOP), yazılım geliştirme süreçlerinde çapraz kesilen ilgiler (cross-cutting concerns) yönetmek amacıyla ortaya çıkan bir programlama paradigmasıdır. Geleneksel programlama dillerinde, özellikle nesne yönelimli programlama (OOP) ile, belirli işlevler(metotlar vb.) birden fazla sınıf veya modülde tekrar edilebilir. Bu tür tekrarlanan kod parçaları genellikle günlük kaydı (logging), hata yönetimi, güvenlik ve performans izleme gibi işlevlerdir. AOP, bu tür çapraz kesilen ilgileri ayrı ve modüler bir şekilde ele alarak kodun daha temiz, anlaşılır ve bakımının kolay olmasını sağlar.

Tarihçesi ve Gelişimi

AOP’nin kökenleri 1990'ların ortalarına kadar uzanır. İlk olarak Xerox PARC’ta geliştirilen bir kavramdır. AspectJ, ilk ve en yaygın kullanılan AOP araçlarından biri olarak kabul edilir ve Java programlama dili için geliştirilmiştir. AOP, nesne yönelimli programlamanın (OOP) bir tamamlayıcısı olarak görülmüştür ve zamanla, diğer programlama dillerine ve platformlara uyarlanmıştır.

Neden AOP?

AOP’nin temel amacı, yazılım sistemlerinde çapraz kesilen ilgileri merkezi bir şekilde yöneterek kodun modülerliğini ve okunabilirliğini artırmaktır. Bu, aşağıdaki avantajları sağlar:

  1. Kod Tekrarını Azaltma: Çapraz kesilen işlevler tek bir yerden yönetilerek, kod tekrarını azaltır.
  2. Bakımı Kolaylaştırma: Çapraz kesilen işlevler ayrı modüller olarak yönetildiğinde, bu işlevlerde yapılacak değişiklikler daha kolay ve hızlı bir şekilde uygulanabilir.
  3. Modülerlik ve Yeniden Kullanılabilirlik: AOP, modülerliği artırarak kodun yeniden kullanılabilirliğini sağlar.

Çapraz Kesilen İlgiler (Cross-Cutting Concerns)

Çapraz kesilen ilgiler (cross-cutting concerns), bir yazılım sisteminde farklı modüller veya bileşenler üzerinde yaygın olan ve bu bileşenlerin işleyişine etki eden işlevsel gereksinimlerdir. Bu ilgiler, uygulamanın çeşitli bölümlerinde ortak işlevler olarak ortaya çıkar ve genellikle altyapısal veya destekleyici işlevlerdir.

Örnek : Güvenlik ve Yetkilendirme (Security and Authorization) Bir uygulamada her metod çağrısı öncesinde güvenlik kontrolü yapmak isteyelim.

Service.java:

Bu örnekte, her metod için güvenlik kontrolü kodu tekrar edilir. Bu, kodun bakımını zorlaştırır ve hata yapma olasılığını artırır. Yazının ilerleyen bölümlerinde bunları ele alacağız.

AOP’nin Temel Kavramları

Aspect

Aspect, çapraz kesilen ilgileri kapsülleyen bir modüldür. Örneğin, bir uygulamada günlük kaydı (logging) yapmak istiyorsanız, bu işlevi bir Aspect olarak tanımlayabilirsiniz. Aspect’ler, belirli bir işlevi merkezi bir yerden yönetmek ve uygulamanın farklı bölümlerine bu işlevi eklemek için kullanılır.

Join Point

Join Point, bir Aspect’in uygulama kodu ile birleştiği belirli bir noktadır. Bu, bir metodun çağrılması, bir nesnenin oluşturulması veya bir değişkenin değeri gibi çeşitli işlemler olabilir. Join Point’ler, uygulamanın farklı noktalarında Aspect’lerin nasıl ve ne zaman uygulanacağını tanımlar.

Pointcut

Pointcut, bir veya daha fazla Join Point’i seçen bir ifade veya kalıptır. Aspect’lerin hangi Join Point’lerde uygulanacağını belirlemek için kullanılır. Örneğin, belirli bir sınıftaki tüm metod çağrılarını veya belirli bir ad ile başlayan metodları hedefleyebilirsiniz. Pointcut’lar, AOP’nin esnekliğini ve gücünü sağlar.

Advice

Advice, belirli bir Join Point’te yürütülecek kodu tanımlar. Farklı türde Advice’lar vardır:

  • Before Advice: Bir Join Point’ten önce çalışır.
  • After Advice: Bir Join Point’ten sonra çalışır.
  • Around Advice: Bir Join Point’in hem öncesinde hem de sonrasında çalışabilir ve Join Point’in kendisinin çalışmasını kontrol edebilir.

Advice’lar, çapraz kesilen ilgileri belirli bir şekilde ele alarak uygulamanın farklı noktalarına ek işlevsellik sağlar.

Weaving

Weaving, Aspect’lerin uygulama koduna entegre edilmesi sürecidir. Bu işlem derleme zamanında (compile-time), yükleme zamanında (load-time) veya çalışma zamanında (runtime) gerçekleştirilebilir. Weaving işlemi, Aspect’lerin belirtilen Join Point’lerde çalışmasını sağlar. Weaving yöntemine bağlı olarak, uygulamanın performansı ve davranışı değişebilir.

Örnek

Bu temel kavramları daha iyi anlamak için basit bir örnek ele alalım. Öncelikle Aspect kullanacağımız basit bir sınıf tanımlayalım:

Service.java

Yukarıdaki kodda Service sınıfı içerisinde iki method tanımlandı ve method basit olarak ekrana çıktı veriyor. Buradaki com.example.service paketine dikkat edelim. Şimdi de bir Aspect tanımlayalım:

LoggingAspect.java

Bu örnekte, LoggingAspect adlı bir Aspect oluşturduk. Bu Aspect, com.example.service paketindeki tüm metodlar çağrılmadan önce ve sonra log kaydı yapar. @Before ve @After notasyonları, Advice türlerini belirtir ve execution(* com.example.service.*.*(..)) ifadesi, Pointcut tanımıdır. Uygulama çalıştırıldığında, Service sınıfındaki metodlar çağrıldığında LoggingAspect tarafından eklenen günlük kaydı işlevleri devreye girer. Ekran çıktısı aşağıdaki gibi olacaktır:

Method: method1 is about to be called.
Executing method1
Method: method1 has been called.
Method: method2 is about to be called.
Executing method2
Method: method2 has been called.

Bu ekran çıktısı, LoggingAspect aspect'inin method1 ve method2 çağrılmadan önce ve sonra günlük kaydı yaptığını göstermektedir. Aspect, her iki metodun çalışmasından önce ve sonra otomatik olarak devreye girerek belirtilen mesajları ekrana yazar.

AOP Uygulama Alanları ve Örnekler

Aspect-Oriented Programming (AOP), yazılım geliştirme süreçlerinde çeşitli cross-cutting concerns yönetmek için kullanılır. AOP’nin bazı yaygın uygulama alanları şunlardır: günlük kaydı (logging), performans izleme, güvenlik ve yetkilendirme, hata yönetimi, nakit işlemleri ve izleme. Bu bölümde, gerçek hayattan senaryolar ve kod örnekleri ile birlikte ekran çıktıları vereceğiz

1. Performans İzleme (Performance Monitoring)

Performans izleme, uygulamanın belirli metodlarının çalışma süresini izlemek ve optimize etmek için kullanılabilir.

Örnek Senaryo:

Bir finans uygulamasında, işlem süresi uzun olan metodların izlenmesi ve optimize edilmesi gerekiyor.

Service.java

PerformanceAspect.java

Ekran Çıktısı:

Performance: Method processTransaction took 2002 ms Transaction processed.

Burada paket altındaki her metodun çalışma süresini görebiliriz.

Hata Yönetimi (Error Handling)

Hata yönetimi, uygulamanın belirli noktalarında meydana gelen hataları ele almak ve raporlamak için kullanılır.

Örnek Senaryo:

Bir banka uygulamasında, her metod çağrısında meydana gelen hataların merkezi bir şekilde yönetilmesi gerekiyor.

Service.java:

ErrorHandlingAspect.java:

Ekran Çıktısı:

Error Handling: Exception in method withdraw: Insufficient funds.
Amount deposited.

AOP’nin Zorlukları

Öğrenme Eğrisi

  • AOP’nin kavramları ve terminolojisi, özellikle yeni başlayanlar için karmaşık olabilir. Join Point, Pointcut, Advice ve Weaving gibi kavramları anlamak zaman alabilir.
  • Öneri: AOP’yi öğrenmeye başlarken, basit örneklerle başlayarak adım adım ilerlemek ve çeşitli kaynaklardan yararlanmak faydalı olacaktır.

Performans Etkileri

  • AOP’nin dinamik dokuma (weaving) işlemleri, özellikle çalışma zamanı (runtime) dokuma yöntemleri kullanıldığında performans üzerinde olumsuz etkiler yaratabilir. Bu, özellikle yüksek performans gereksinimleri olan uygulamalarda dikkate alınması gereken bir konudur.
  • Öneri: Performans etkilerini minimize etmek için dokuma işlemlerini derleme zamanı (compile-time) veya yükleme zamanı (load-time) sırasında yapmak tercih edilebilir.

Hata Ayıklama (Debugging) Zorlukları

  • AOP, uygulama kodunun içine dinamik olarak yerleştirildiği için, hata ayıklama süreçleri karmaşıklaşabilir. Hangi Aspect’in hangi noktada devreye girdiğini takip etmek zor olabilir.
  • Öneri: Hata ayıklama süreçlerinde uygun araçlar ve teknikler kullanarak, Aspect’lerin devreye girdiği noktaları izlemek ve loglama yapmak faydalı olabilir.

AOP’nin Uygulama Araçları ve Diğer Diller

Aspect-Oriented Programming (AOP), çeşitli programlama dilleri ve araçlarla uygulanabilir. Bu bölümde, Spring haricinde AOP’nin yaygın olarak kullanıldığı araçlar ve diller üzerinde duracağız.

NET ve PostSharp

.NET platformunda, AOP yetenekleri sağlayan çeşitli araçlar bulunur. PostSharp, .NET için en popüler AOP araçlarından biridir.

PostSharp: PostSharp, .NET uygulamalarında AOP’yi destekleyen güçlü bir araçtır. Derleme zamanı dokuma yöntemini kullanarak çalışır ve .NET dilinde çeşitli çapraz kesilen ilgileri yönetir.

Ekran Çıktısı:

PostSharp: Method: someMethod is about to be called.
PostSharp: Method: someMethod has been called.

Python ve Aspectlib

Python, AOP’yi destekleyen daha az sayıda araca sahip olmasına rağmen, Aspectlib gibi bazı kütüphanelerle AOP yetenekleri sağlanabilir.

Aspectlib: Aspectlib, Python dilinde AOP yetenekleri sağlayan bir kütüphanedir. Dinamik dokuma yöntemini kullanarak çalışır.

Örnek:

Ekran Çıktısı:

Aspectlib: Method some_method is about to be called.
Executing some_method
Aspectlib: Method some_method has been called.

Spring Örnek Proje

Bu bölümde gerçek hayat senaryolarından spring projesi yapacağız. Bu proje kapsamında bir retry mekanizması yazacağız ve bunu @Retryable adını verdiğimiz bir anotasyon ile yöneteceğiz. Bu anotasyon, belirli bir metodun hatalı çalışması durumunda belirtilen sayıda tekrar denenmesini sağlayacak. Proje yapısı aşağıdaki gibi olacak:

Adım 1: Spring Boot Uygulama Sınıfı

AopDemoApplication.java:

Adım 2: Anotasyon Tanımlama

Retryable.java:

Yukarıda ilgili anotasyonu tanımlıyoruz.

Adım 3: Aspect Sınıfı

RetryableAspect.java:

Şimdi yukarıdaki sınıfı inceleyelim:

  1. Anotasyon ve Component Tanımlaması:
  • @Aspect Anotasyonu: Bu anotasyon, sınıfın bir Aspect olduğunu belirtir ve Spring AOP tarafından kullanılan kesişim noktalarını tanımlamak için kullanılır.
  • @Component Anotasyonu: Bu anotasyon, Spring’in bu sınıfı bir bean olarak yönetmesini sağlar, yani Spring konteyneri bu sınıfın bir örneğini oluşturur ve yönetir.

2. ThreadLocal ve AtomicInteger Tanımlaması:

  • ThreadLocal: Bu sınıf, her bir thread için ayrı bir değişken saklamak amacıyla kullanılır. Bu, aynı değişkenin farklı thread’ler arasında güvenli bir şekilde kullanılmasını sağlar.
  • AtomicInteger: Bu sınıf, atomik (kesintisiz) olarak artan bir tamsayıyı tutar. ThreadLocal ile birlikte kullanıldığında, her thread'in kendi yeniden deneme sayacını (attempt count) takip etmesini sağlar.

3. @Around Anotasyonu ve retry Metodu:

  • @Around Anotasyonu: Bu anotasyon, belirtilen kesişim noktası etrafında (öncesinde ve sonrasında) bir tavsiye (advice) çalıştırılmasını sağlar. Burada, @annotation(com.example.aopdemo.annotation.Retryable) ifadesi, @Retryable anotasyonu ile işaretlenmiş metodları hedef alır.
  • ProceedingJoinPoint: Bu parametre, kesişim noktasındaki (join point) metodun çağrılmasını temsil eder ve metodun çalıştırılmasını sağlar.

4. Metod Bilgilerini Alma:

  • MethodSignature: Bu sınıf, kesişim noktasındaki metodun imzasını temsil eder ve metodun adını, dönüş tipini ve parametrelerini içerir.
  • Method: Bu sınıf, belirli bir metodun yansımasını (reflection) sağlar. Bu, metodun kendisine ve anotasyonlarına erişmemizi sağlar.
  • Retryable Anotasyonu: Bu, metod üzerinde tanımlı olan @Retryable anotasyonunu temsil eder ve bu anotasyonun parametrelerine erişmemizi sağlar.

5. Anotasyondan Parametreleri Alma:

  • maxAttempts: Bu, @Retryable anotasyonunda belirtilen maksimum deneme sayısını temsil eder.
  • retryOn: Bu, @Retryable anotasyonunda belirtilen ve yeniden denemeye neden olacak istisnaların (exceptions) sınıflarını içeren bir dizi (array) temsil eder.

6. Yeniden Deneme Döngüsü:

  • Deneme Sayısını Artırma: attemptCount değişkeni, her yeniden deneme girişiminde bir artırılır.
  • Metodun Çağrılması: joinPoint.proceed() metodu, kesişim noktasındaki (join point) metodun çalıştırılmasını sağlar.
  • İstisna Yakalama: Eğer bir istisna fırlatılırsa, bu istisna yakalanır ve belirli koşullara göre yeniden denenip denenmeyeceğine karar verilir.
  • İstisnanın Türünü Kontrol Etme: Yakalanan istisna, retryOn dizisinde belirtilen türlerden biriyle eşleşip eşleşmediği kontrol edilir. Eğer eşleşmiyorsa, istisna yeniden fırlatılır.
  • Maksimum Deneme Sayısını Kontrol Etme: Eğer deneme sayısı maksimum deneme sayısını aşarsa, istisna yeniden fırlatılır.
  • Yeniden Deneme Mesajı: Her yeniden deneme girişiminde, deneme sayısı ve metodun adı ekrana yazdırılır.

7. ThreadLocal Temizleme:

  • attemptCount.remove(): Bu metod, ThreadLocal değişkenini temizler ve böylece yeniden kullanılmasını önler.

Bu RetryableAspect sınıfı, bir metodun başarısız olması durumunda belirli bir sayıda yeniden denenmesini sağlayan bir mekanizma sunar. @Retryable anotasyonu ile işaretlenmiş metodlarda, belirtilen hatalarla karşılaşıldığında metod belirli sayıda tekrar çalıştırılır. Bu, özellikle ağ bağlantıları gibi hataların geçici olabileceği durumlarda yararlıdır ve otomatik yeniden deneme (retry) mekanizması sağlar.

Adım 4: Servis Sınıfı

SampleService.java:

Adım 5: Uygulamanın Çalıştırılması

AopDemoApplication.java:

Ekran Çıktısı

Uygulama çalıştırıldığında, SampleService sınıfındaki performTask metodunun @Retryable anotasyonu ile belirtilen yeniden deneme (retry) mekanizması çalışacaktır:

Performing task, attempt: 1
Retry attempt 1 for method performTask
Performing task, attempt: 2
Retry attempt 2 for method performTask
Performing task, attempt: 3
Task completed successfully on attempt 3

Bu örnekte, performTask metodu başarısız olduğunda yeniden deneme mekanizması devreye girer ve belirtilen sayıda tekrar deneme yapılır. Başarılı olduğunda ise işlem tamamlanır ve başarı mesajı ekrana yazdırılır.

AOP’nin Geleceği ve Trendler

Aspect-Oriented Programming (AOP), yazılım geliştirme süreçlerinde çapraz kesilen ilgileri yönetmek için önemli bir araç olarak kabul edilmektedir. AOP’nin geleceği ve trendleri, yazılım mühendisliği alanındaki ilerlemelerle birlikte evrilmektedir. Bu bölümde, AOP’nin geleceği ve güncel trendler üzerinde duracağız.

Güncel Araştırmalar ve Gelişmeler

AOP’nin yazılım geliştirme dünyasındaki yeri, sürekli olarak yeni araştırmalar ve gelişmelerle desteklenmektedir. Bu araştırmalar, AOP’nin verimliliğini artırmaya ve kullanımını daha geniş alanlara yaymaya odaklanmaktadır.

  • Dinamik AOP: Dinamik AOP, çalışma zamanında (runtime) dokuma işlemleri gerçekleştirerek daha esnek ve dinamik bir yapı sağlar. Bu, özellikle mikro hizmet mimarileri ve bulut tabanlı uygulamalarda önem kazanmaktadır.
  • Yeni Programlama Dilleri ve Platformlar: AOP, daha fazla programlama dili ve platforma entegre edilmektedir. Örneğin, JavaScript ve TypeScript gibi modern web geliştirme dillerinde AOP yetenekleri araştırılmaktadır.
  • Makine Öğrenimi ve Yapay Zeka: AOP’nin makine öğrenimi ve yapay zeka alanlarındaki uygulamaları da araştırılmaktadır. Bu, özellikle büyük veri işleme ve analitik süreçlerde çapraz kesilen ilgileri yönetmek için kullanılmaktadır.

Endüstri Kullanım Durumları

AOP, çeşitli endüstrilerde ve kullanım durumlarında yaygın olarak kullanılmaktadır.

  • Finans ve Bankacılık: Güvenlik, yetkilendirme ve log kaydı gibi kritik işlevler, AOP ile merkezi bir şekilde yönetilmektedir.
  • Sağlık: Sağlık sektöründe, hasta verilerinin güvenliği, erişim kontrolü ve performans izleme gibi ilgiler AOP ile yönetilmektedir.
  • Telekomünikasyon: Ağ izleme, hata yönetimi ve performans optimizasyonu gibi işlevler AOP kullanılarak etkin bir şekilde ele alınmaktadır.
  • E-ticaret: Kullanıcı davranışlarının izlenmesi, güvenlik kontrolleri ve hata yönetimi, e-ticaret platformlarında AOP ile uygulanmaktadır.

Bu yazımızda AOP kavramının ne olduğuna ve kullanım yerlerine değindik. Sonraki makalede görüşmek dileğiyle. Keyifle…

--

--