Bir önceki yazımda, AOP’in birbiri ile kesişen ilgileri ayırmak ve basitleştirmek için kullanabileceğimiz bir yaklaşım olduğunu söylemiştim hatırlarsanız. Ve hatırlarsanız bir tane de pseudo kodu ile bir insanın yaşam sürecini örneklendirmeye çalışmıştım. Yaşam döngüsünde birbiri ile kesişen iglileri görmüştük. Biraz daha anlaşılır olması adına daha sık karşımıza çıkan problemleri bu yazıda ele almaya çalışacağım.Bu sayede AOP’ı ve hangi sorunlara çözüm sunduğunu anlamak daha kolay olacaktır. İlk olarak aşağıdaki metod ile başlayalım.

public ResultSet SearchCustomer(string username, string customerName,string customerSurname)
 {
              try
            {
                if (!IsExists(username))
                    throw new DoesNotExistsException();

                if (!HasAccess(username))
                    throw new AccessDeniedException();

                Logger.Write("Search will be done with CustomerName:{0} CustomerSurname:{1}",customerName,customerSurname);

                ResultSet results = Database.Search(customerName, customerSurname);

                Logger.Write("Search is successfully done");

                return results;
            }
            catch (Exception ex)
            {

                Logger.Write(ex.Message, "ERROR");
            }

            return null;
 }

Müşteri adı ve soyadına göre arama yapan, arama yaparken bazı kontrolleri gerçekleştiren bir metod var yukarıda. Arama yapan kullanıcıyı kontrol eden,daha sonra bu kullanıcının durumuna göre başka bir kontrol yapan, kayıt eden ve sonra arama operasyonunu gerçekleştiren ve bir hata olursa yine bunu kayıt altına alan bir metod dikkat ederseniz. Bir çok farklı ilgi aslında iç içe…Daha doğrusu kesişiyor. Bu tarz ilgiler aslında bir çok yazılım projesinde önemli yer kaplıyor. Bu tarz ilgilerin birden fazla metod içerisinde kullanıldığını düşünün…Search() metodunun içerisinde yapılan kontrollerin, aynı gereksinimlerden dolayı SaveCustomer() metodunda da yapılması gerektiğinde birbirini tekrarlayan, bir değişiklikte bir çok yeri etkileyen kod parçaları ortaya çıkacaktır. Bunlar zaman zaman soruna, zaman zaman da karmaşıklığa yol açar bildiğiniz üzere…Ve bu şekilde iç içe girmiş karmaşıklıkları yönetmek oldukça zor olacaktır.

Bu karmaşıklıklar, nesnelerin yazılımın yaşam süresindeki durumlarından dolayı oluşacak karmaşıklık ile iç içe girdimi tam bir çıkmaza dönüşür.Bu tarz problemleri çözmek için, mesela metodları çağırırken, nesneleri yaratırken veya değerlere atama yaparken kendi ilgilerini ayırmak kısmen de olsa yeterli olacaktır. Yukarıdaki Search metodundan önce, yani daha metod çağrımı yapılmadan kullanıcı kontrolleri yapılsa,log işlemi gerçekleşse,sonra metod çağrımı yapılsa bir şekilde ilgiler birbirinden ayrılmış olacak. Bu ilgileri ayırdığımız zaman benzer ihtiyaçları olan metodlarda da bu ilgileri kullanabilmek mümkün olacaktır. Bu ilgileri ayırabildiğimiz zaman, kesişen ilgilerden dolayı oluşabilecek problemleri yok edebiliriz.

Başka bir sorun ise bu ilgilerin yazılımın yaşam süresi içerisinde ortaya çıkması. Mesela aşağıdaki kod parçasına bakalım. Person diye bir sınıfımız var. CanDrive diye bir metodu yaş ve ehliyet değerlerine göre sonuç dönüyor…Person sınıfımızdan yaratılan nesnemiz, uygulama içerisinde Türkiye’de olan bir nesne şeklinde çalışıyorsa CanDrive() metodunda sorun olmayacaktır. Ancak Person sınıfının nesnesi ABD içeriğinde oluştuğunu düşündüğümüzde CanDrive() metodu yanlış çalışacaktır. Çünkü ABD’de araba kullanabilmek için 18 yaşını beklemeye gerek yok bildiğiniz üzere…

    public class Person
    {
        public bool CanDrive()
        {
            if (_age >= 18 && HasLicense)
            {
                return true;
            }

            return false;
        }
    }

Burada sorun bir eylem gerçekleştirmek için kullanılan metodun içerisinde bazı kurallarında metodun içerisinde yer alması. Person sınıfdan bir nesne yaratan kişi, bu kuralları bilemeyeceği için bu nesneyi istediği gibi kullanamayacktır. Bunu çözmek için bu tarz kuralları dışarıya verebiliyor olmak sorunumuzu çözecektir.

Aşağıdaki gibi bir uygulama çözüm yollarından bir tanesine örnek olabilir. Bu şekilde CanDrive bilgisine ulaşmadan önce yaş kontrolünü yapmak mümkün olacaktır. Bu kontrolün nasıl yapıldığı kendi içinde saklandığından CanDrive ilgisi ile bir kesişimi kalmamış oluyor. Asp.Net MVC’de ki Data Annotation Validators kavramını hatırlamak belki sorunu ve çözümünün anlaşılmasında biraz daha yardımcı olur. Oradaki yaklaşımda AOP yaklaşımı ile aynı…

    public class Person
    {
        private bool _canDrive=false;
        public bool CanDrive {

            [Age(Min = 18)]
            get {
                return _canDrive;
            }
        }
    }

Bu yazımda AOP’nın neden ihtiyaç olabileceğini, hangi sorunlara çözüm sunduğunu anlatmaya çalıştım. Biraz sorunlara çözümlerinden çok ağırlık verdiğimi biliyorum…Sorunları anlamanın, çözüm üretmek adına önemli olduğunu düşündüğüm için araya böyle bir yazı daha sıkıştırdım. Ama bir sonra ki yazımda çözümlere çok daha fazla ağırlık vereceğim ve evet kod yazacağım…(:

AOP’nın tam olarak uygulanması için sınıfların,methodların metadata seviyesinde bazı bilgileri dışarıya vermesi ve dışarıdan da bu bilgileri dinamik olarak alabilmesi lazım. Bu bağlamda compiler(derleme) aşamasında bazı değişikliklerin olması da gerekmekte. Compile ve link aşamasına biraz müdahale edebilecek konuma geldiğimizde AOP yaklaşımını daha kolay uygulayabilir ve anlayabilir hale geleceğimizi düşünüyorum. Neyse şimdilik bu kadar…Bu konu ile ilgili bir sonra ki yazıda görüşmek üzere…
Tekrardan hatırlatmak isterim ki her türlü sorunuzu ve düşüncenizi çekinmeden paylaşabilirsiniz…