Posts Tagged With 'Architecture'

  • Mar
  • 22
  • 2011

‘Aspect Oriented’ programlamaya başlıyoruz…Bölüm II

Tags: , , | View: 444 | Comments:

Hatırlayacak olursanız son bir kaç yazıdır AOP hakkında bir şeyler paylaşıyordum. İlk iki yazı teorik, son yazı ise biraz daha uygulamaya yönelik olmuştu. Bu yazıda ise, bir önceki yazıda başlamış olduğum örneği biraz daha geliştirip, AOP’ı daha iyi anlamaya çalışacağız. Ama isterseniz önceki yazıları bir hatırlayalım…

  1. ‘Aspect Oriented’ programlama mı…Nedir ki?
  2. Peki ama neden ‘Aspect Oriented’ programlama…
  3. ‘Aspect Oriented’ programlamaya başlıyoruz…Bölüm I

Bu yazıda bir önceki kod alt yapısını üzerinden giderek, AOP kavramında ki Aspect’leri yaratıyor olacağız. Özellikle “Aspect” şeklinde belirtmek istiyorum ki, yarattığımız bazı örnek sınıfları bu şekilde düşünmeye çalışmak, konunun bütününü anlamak adına yardımcı olacaktır. Hatırlarsanız bir önceki yazıda Person diye bir sınıf oluşturmuştuk örnek olarak ve bu sınıfı bir tane konsol uygulamasında kullanarak methodlarını çağırmadan önce nasıl araya girebileceğimize değinmiştim. Yine aynı sınıf üzerinden, onu biraz daha geliştirerek gidiyor olacağız. Bunun için sınıfımızı aşağıdaki gibi yenilememiz yeterli olacaktır şimdilik. Yeni bir özellik ve metod dışında aslında fazla bir şey de yok.

    [Controller]
    public class Person : ContextBoundObject
    {
        private int _age = 0;
        private string _name = "";

        public string Name { get { return _name; } }

        public Person(string name) : base() { _name = name; }

        public int Age
        {

            get
            {
                return _age;
            }
            set
            {
                _age = value;
            }
        }

        public string DoSomething()
        {

            string logMessage = "Person sınıfının DoSomething() methodu çalıştı";
            Console.WriteLine(logMessage);

            return "";
        }
        public void DoAnotherThing(int parameter1, string parameter2)
        {
            Console.WriteLine("Person sınıfının DoAnotherThing() methodu çalıştı");
        }

    }

AOP, yazılımda ki kesişen ilgileri ayırmak için kullanabileceğimiz bir yöntemdi demiştik. Bu ilgiler her yazılım ürününde bir şekilde olan Logging,Exception Handling gibi kavramlar olabileceği gibi, iş kuralları ve bu kuralların işletildiği methodlar da olabilir. Ama genellikle bir biri ile çakışan ilgiler Logging,Exception Handling, Security gibi kavramlar için daha karmaşık olur. Oluşan Exception için uygun kaydı tutmak, ya da bir metod çalıştığında bu metodun çalışmasına dair bazı bilgileri kayıt altına alabilmek bir çok kavramın iç içe girmesine sebep olur. Bu yazıda bu ilgilere biraz daha yer vererek, bu ilgileri AOP yaklaşımı ile nasıl ayırabileceğimizi anlamaya çalışacağız. Örnek olabilecek bir kaç ilgiyi oluşturup, bunu Person sınıfımızda kullanacağız. Bu ilgileri .NET Framework’ünde bulunan Attribute‘lar ile yaratıp, nesnelerimize,metodlarımıza ve nesnelerin özelliklerine bağlayacağız. Aşağıdaki gibi bir kaç nesne, örnek olması adına yeterli olacaktır diye düşünüyorum.

  • Mar
  • 13
  • 2011

‘Aspect Oriented’ programlamaya başlıyoruz…Bölüm I

Tags: , | View: 581 | Comments:

Bir önceki yazılarda hatırlarsanız, AOP’in ne olduğunu, neden gerekli olabileceğini anlatmaya çalışmıştım. Şimdi de biraz kod üzerinden giderek AOP kavramlarını anlatmaya çalışacağım. AOP için birbiri ile kesişen ilgileri ayırmak için kullanabileceğimiz bir yaklaşım demiştik hatırlarsanız. Kod üzerinden giderek bu ilgileri nasıl ayırabileceğimizi 2 kısım şeklinde olacak bir yazı dizisi ile anlatmaya çalışacağım. Bu ilk kısımda birbiri ile kesişen ilgileri ayırmak için bir alt yapı oluşturacağız. Daha sonra ki yazımda ise yarattığımız nesnelere yeni ilgiler vererek bu alt yapı sayesinde ilgilerin aslında hiç kesişmeden basit bir biçimde uygulandığını göreceğiz. O zaman başlayalım…

Bu yazı için .NET Framework içerisinde bulunan ContextBoundObject sınıfından faydalanacağız. Bu noktada .NET Framework’de direk olarak bir AOP desteği olmadığı hatırlatmak isterim. Sadece .NET Framework’ün bize sunduğu sınıf ve metodlar ile bu yaklaşımı biraz olsun oluşturmaya ve daha iyi anlamaya çalışıyor olacağız.

Öncelikle ContextBoundObject sınıfının ne olduğu kısaca anlatmaya çalışacağım. Biraz sonra aşağıda vereceğim örneğin daha anlaşılır olması adına gerekli olacağına inanıyorum.

Bir içeriğe(context) ve bu içeriğin kurallarına bağlı olan nesnelere, içeriğe bağlı nesneler deniyor, yani context-bound objects. Peki içerik ne? Belli özelliklerin ve kullanım kurallarının kullanıldığı, nesnelerin bir araya geldiği oluşumlar diyebiliriz. Yani bir nesne bir içeriğe dahil olduğu ya da bağlandığı zaman o içeriğin özelliklerini ve kurallarını uygulamak durumunda oluyor. Bir nesne yaratılırken var olan bir içeriğe ya da meta-data’sında bulunan Attribute’lara(özelliklere) göre yaratılacak yeni bir içeriğe bağlanabilir. Burada ki özellik kavramı da ContextAttribute sınıfı ile .NET Framework içerisinde tanımlanmakta. Biraz daha geniş ve ayrıntılı bilgiyi buradaki MSDN içeriğinden öğrenebilirsiniz. Ama bizim için şimdilik bu kadarı yeterli olacak.

Yukarıda özetlemeye çalıştığım ContextBoundObject sınıfı ile oluşturacağımız nesnelerin bir içerik dahilinde oluşmasını sağlayacağız. Daha sonra bu içerik içerisinde ki kurallara göre kesişen ilgileri kontrollü bir şekilde yönetebileceğiz. Bunu nesneleri yaratırken, tam yaratmadan önce bazı kontrolleri yaparak, nesnenin bir metodunu çağırırken, tam çağırmadan önce bazı kontrolleri yaparak ya da nesnenin özelliklerini değiştirirken, tam değiştirme aşamasından önce yine bazı kontroller yaparak yapacağız. Burada ki kontroller de aslında birbiri ile kesişen ilgiler olacak. Biraz karışık oldu sanırım ama kod örnekleri ile daha net anlaşılacağına inanıyorum.

Öncelikle ContextBoundObject sınıfından türeyen bir Person sınıfı yaratalım…

 public class Person : ContextBoundObject
 {
        private int _age = 0;
        public Person():base()
        {

        }
        public int Age
        {
            get
            {
                return _age;
            }

            set
            {
                _age = value;
            }
        }

        public string DoSomething()
        {
            return String.Format("Person sınıfının DoSomething methodu çalıştı");
        }
 }

Fark etmiş olduğunuz gibi ContextBoundObject’ten türemesine rağmen pek bir farklılığı yok. Bu nesnenin yaratıldığı içeriğin özelliklerini(Attribute) belirlememiz lazım ki, yaratıldığı zaman o özelliğin sağlayabileceği yöntemler ve özellikler ile nesnenin üzerinde kontroller yapabilelim. Bunun için aşağıdaki gibi bir kod bloğu ile ContextAttribute’dan türeyen bir Attribute yaratmamız lazım.

  • Mar
  • 12
  • 2011

Peki ama neden ‘Aspect Oriented’ programlama…

Tags: , | View: 710 | Comments:

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.

  • Mar
  • 11
  • 2011

‘Aspect Oriented’ programlama mı…Nedir ki?

Tags: | View: 1,222 | Comments:

Öncelikle “Aspect Oriented Programming”(AOP), “Object Oriented Programming”‘in bir sonra ki aşaması değil. Bazı kavramların ortak olmasından dolayı ilk akla gelen soru işaretleri bu yönde oluyor. AOP‘de, yazılımın karmaşıklığını gidermek adına gerekebilecek bir programlama yöntemi. Tıpki OOP gibi. Yani OOP ölüyor, yerine AOP geçiyor gibi bir durum söz konusu değil. OOP’e alternatif bir şey olmadığı şeklinde düşünmekte, AOP anlamak için fayda var…

Peki nedir bu AOP? AOP‘ı basitçe Türkçe’ye çevirirsek bazı şeyleri anlamak adına belki yardımcı olur…Bu bağlamda “Görünüşe Yönelik Programlama” benim en tercih ettiğim bir çeviri oluyor. AOP, yazılımdaki birbiri ile kesişen ilgileri(cross-cutting concerns) ve bu ilgilerin oluşturduğu karmaşıklığı çözmek adına ortaya çıkmış bir method aslında.

Yazılım geliştirken, en zorlayıcı kısım genellikle birbiri ile kesişen ilgileri basitleştirmektir. Neden böyle bir basitleştirme içerisinde olmaya gerek var ki şeklinde bir soru sorabilirsiniz… Geliştirdiğimiz uygulamaların yaşam süresinde oluşabilecek, yeni gereksinimleri, sorunları daha kolay yönetebilmek adına birbiri ile kesişen ilgileri en basit halde ele almamız gerekir…Haa yok ben bir kere yazacağım,çalışacak, sonra bir daha dokunmayacağım şeklinde bir uygulama geliştirmekteyseniz bunlara çok da kafa yormaya gerek yok açıkcası.

AOP, az önce bahsettiğim birbiri ile kesişen ilgileri basitleştirmek ve hatta ayırmak adına kullanılabilecek bir yöntem. Hemen bu noktada da OOP’de de bu tarz şeyleri yapabileceğimiz yöntemler var şeklinde düşünebilirsiniz…Doğrudur,var…Ancak zaman zaman yeterli olamıyor ne yazık ki…Ya da bazı şeyleri daha karmaşıklaştırıyor…Bu noktada “zaman” kelimelerinin altını çizmekte fayda var sanırım. Çünkü bu konuda AOP’ı düşünmeye sebep olan, OOP’den farklı yönlerini ortaya çıkaran kavram “zaman” kavramı…AOP, yazılımın yaşam süresi boyunca oluşabilecek ilgilerin bir biri ile kesişmesini ve karmaşıklığa yol açmasını engellemek adına OOP’den farklılaşıyor. Biraz daha teknik olarak açıklamak gerekirse, bir uygulamanın run-time süresinde ortaya çıkabilecek ilgileri ayırmak açısından farklılaşıyor diyebiliriz. AOP’i yazımın başında “Görünüşe Yönelik Programlama” şeklinde çevirmeyi tercih etmiştim. Görünüş olarak anlamlandırdığım kavram, uygulamanın kendisinin ya da içerisinde ki nesnelerin durumları diyebilirim.

  • Jan
  • 04
  • 2011

Nesneye yönelik programlama mı, nesneye yönelik tasarım mı…

Tags: | View: 641 | Comments:

Nesneye yönelik(Object-oriented) programlama diyince, eminim bir çok kişi “class”,”abstraction”,”encapsulation”,”inheritance”,”polymorphism” gibi janjanlı kelimeleri söyleyecektir. Kesinlikle yanlış başlıklar ya da konular değil…Nesneye yönelik programlamanın hatta temel taşları…Ama bunları bilmek, nesneye yönelik programlamayı anlamak, bilmek ve faydalanabilmek için yeterli mi?…

Bu soruya benim kendi kişisel cevabım, kesinlikle hayır olacaktır. Yarattığım sınıfları başka sınıflardan türeterek, çeşitli soyutlamalar yaparak, belli metodları ya da sınıfın özelliklerini saklayarak nesneye yönelik programlama yapabilirim ama bu gerçekten nesneye yönelik programlamanın amacına yönelik bir şey mi olur…
Bu sorunun cevabını verebilmek içinde nesneye yönelik tasarımı irdelemeye çalışmak, nesneye yönelik programlama ve nesneye yönelik tasarım arasında ki ilişkiyi anlamak yeterli olacaktır.
Nesneye yönelik tasarım, bir sistemi oluştururken, sistemin parçalarını, nesneler ve bu nesnelerin metodları ve özellikleri ile, birbirleri arasında ilişki sağlayabilmek şeklinde özetlenebilir. Bu noktada SOLID diye kısaltabileceğimiz 5 kavram karşımıza çıkıyor. Bunları ilke ve belki de kural şeklinde de ele alabiliriz, ki bence nesneye yönelik tasarımı daha iyi anlamak adına bu şekilde düşünmekte fayda var.

“Single responsibility”(ayrı sorumluluklar), “Open-closed”(Açık-kapalı),” Liskov substitution”(yerine konulabilirkik), “Interface segregation”(arayüzlerle ayırma) ve “Dependency inversion”(bağımlılıkları ters çevirme) kavramlarının kısaltması olan SOLID, nesneye yönelik tasarımın en temel olmazsa olmaz 5 ilkesidir. Ve nesneye yönelik programlama kavramlarının da aslında ortaya çıktığı noktalardır.

Single Responsibility: Bu ilke, her nesnenin kendine ait bir sorumluluğu olmasını söyler. Nesnelerin sorumlulukları dışına çıkması, tasarımı ve geliştirmeyi zorlayacak bir unsur olacağından, bu ilke nesneye yönelik tasarımın 5 ilkesinden en önemli olanıdır diyebilirim. Bu yüzden tasarım esnasında mimari bileşenlerinizin nesne modellerini iyice biçim tartmak gerekecektir. Oluşturacağınız nesnelerin özellikleri, metodları ve başka nesneler ile olan iletişimlerinin nasıl olacağı gibi konular nesnenin kendine ait bir sorumluluğu olması açısından önemle ele alınmalıdır. Ama tabi geliştirme ve tasarım süreçlerinin aynı ilerlediği(olmaz demeyin, gayette olur, çok da anormal bir durum değildir aslında) uygulama geliştirme durumlarında bu ilke başka nedenlerden dolayıda çok ihlal edilir…Hele ipin ucu kaçtı mı, bir çok şeyden sorumlu nesneler ve hiç bir sorumluluğu olmayan nesneler sistemde dolaşır…

Open-Closed: Bu ilke, nesnelerin değişikliğe kapalı(Closed), ama genişletmeye açık(Open) olmasını söyler. Bir nesnenin kendi özelliklerinin değişmesinden çok, bu değişiklikleri genişletme bakış açısından ele alıp, nesneyi genişletmek, nesnenin yavaş sürecinin sağlıklı kalmasını sağlayacaktır. Bir metodun değiştiğini düşünün, bu metodu kullanan diğer bileşenlerin de mevcut değişikliğe ayak uydurması gerekecektir. Bu bileşen çalışan bir sistem içerisindeki bir bileşense bu değişikliğe ayak uydurmak biraz zor olacak ve hatta çalışma süresine etki edecektir. Bundan dolayı nesneleri değiştirmek yerine genişletmek daha doğru olacaktır. Nesneleri “inheritance” kavramını uygulayarak yeni nesneler yaratacak şekilde genişletmek, ya da belirli “interface”(arayüz) ya da “abstract”(soyut) sınıfları uygulayacak şekilde genişletmek bu ilkenin doğru işletilmesi adına doğru bir yaklaşım olacaktır.

Liskov substitution: Bu ilke, X tipinden türeyen Y tipinde ki bir nesnenin, X tipinden türeyen herhangi bir tip ile değiştirebileceğini söyler. Burada önemli olan bu değişikliği yaparken, bu nesneleri kullanan sistemde bir değişiklik yapılmaması gerekliliği…Yani İnsan sınıfından türeyen Erkek sınıfı ve Kadın sınıfı, İnsan sınıfının özelliklerini, metodlarını kullanan bir sistem içerisinde değiştirilebilmelidir. (Ama tabi ayrımcılıkta yapmamak lazım :D )
Bu ilkenin amacı yapılan tasarımın belli kontratlara göre yapılmasını sağlamaktır. Bu sayede geliştirilen sistem kendi içinde istikrarlı ve kurallı olacaktır. Aynı zamanda bu kontratlara uyan başka nesneler ile de sistemin genişletilmesi mümkün olur. WCF deki “Data Contract” kavramının da temelinde bu ilke vardır. Aynı şekilde .NET Framework 4.0 ile beraber gelen “Contracts” kavramını da bu ilkeye örnek olarak gösterebilirz.

Interface segregation: Bu ilke, bir “interface”(arayüz)  aracılığıyla yaratılan nesnelerin gerektiğinde başka arayüzlere ayrılması gerektiğini söyler. Aslında amaç olarak Single Responsibility’e benzer, çünkü bu sayede her nesnenin sorumluluğu kadar arayüzü olmasını söyler. Bütün nesneleri bir arayüzden türetmek, bazı yaratılan nesnelerin o arayüz methodlarına ihtiyacı olmamasına rağmen kullanmasını zorunlu kılar. Ama bu çok doğru ve istenen bir kullanım olmamalıdır. Çünkü nesnelerin karmaşıklığını artırır…Bu yüzden nesneleri farklı arayüzlere ayırmak karmaşıklığı azaltır.

Dependency inversion: Bu ilke, nesnelerin soyutlaştırılmasını ve nesnelerin başka nesnelere bağlılığından çok, soyut nesnelere bağlı olmasını söyler. Bu sayede nesnelerin birbirlerine bağımlılıkları azalacaktır. Farklı ihtiyaçlara hitap eden nesnelerin birbirine bağımlılığı, yine nesneleri karmaşıklaştıracaktır. Nesnelerin birbirlerine bağlı olma şekli önemli ama nasıl bağlandığı önemli olmamalıdır. Bu detayların her nesne(leri)nin kendi içinde yönetilmesi daha doğru bir yaklaşım olacaktır. Genellikle bu ilkeyi nesneye yönelik tasarımda uygulamak oldukça zor olabiliyor, en azından benim gözlemlediğim süreçler bu yönde. Ancak bu ilke başarılı bir şekilde uygulandığı takdirde sağlıklı tasarımlar yapmak daha kolay olacaktır.

Nesneye yönelik programlama ve nesneye yönelik tasarım kavramlarını bir birinden ayırabilmek çok önemlidir. Bundan dolayı kendimce, çat bat ikisi arasında ki ilişkiyi biraz özetlemeye çalıştım. Umarım faydalı olur…

Neyse şimdilik bu kadar…Bu ve benzeri konularda biriken yazacak çok şey var…Yazma konusunda ki tembelliğimi yendiğim an onları da burada bulabileceksiniz…

  • Apr
  • 21
  • 2010

Microsoft Enterprise Library 5.0 versiyonu yayınlandı…

Tags: , , , | View: 1,069 | Comments:

patterns & practices ekibinden uzun süredir beklenen haber geldi. Microsoft Enterprise Library 5.0 versiyonu son halini alıp yayınlandı.  Bu adresten kütüphanenin kurulum dosyalarını ve kaynak kodlarını indirip, kendi geliştirmekte olduğunuz uygulamalarda kullanabilirsiniz.

Ayrıca ayrıntılı bilgi ve dökümantasyon için de MSDN sayfasına göz atmanızı tavsiye ederim.

  • Apr
  • 12
  • 2010

Yazılım karmaşık bir kavram…mı acaba?…

Tags: | View: 466 | Comments:

Yazılım karmaşık(kompleks) bir kavram mıdır?

Aslında evet ya da hayır şeklinde cevabı olan bir soru değil bu. Ya da bu şekilde cevaplanması gereken bir soru değil. Bu sorunun cevabını irdelemeden önce, neden böyle bir soru sorup, ortamı geriyoruz önce bunu anlayalım…
Bu soruyu sormamızın amacı, önümüze çıkacak olan karmaşık problemleri çözmek için nasıl bir yol izleyeceğimizi kestirebilmek. Bir yazılımın karmaşıklığını düşünmek, geliştirme sürecinde ortaya çıkabilecek, planda olmayan engelleri ortaya çıkarmak adına oldukça faydalıdır.

Neden bu soruya cevap aradımızı anladıktan sonra, cevabını bulmak daha kolay olacaktır. Yazılım kavramı, yeri geldiğinde oldukça karmaşık, içinden çıkması zor, bir o kadar da sıkıntılı olabilir. Ama aynı şekilde çok kolay da olabilir. Bunların bir kaç nedeni var. Birazdan bu nedenlere geçiyor olacağım.

Yazılımda karmaşıklık dendiğinde genelde, sistemi oluşturan bileşenlerin bir birleri olan ilişkileri ya da bileşenlerin kendi içerisinde çağırdıkları diğer alt bileşenlerin sayısı gibi şeyler hesaplanır. Bunun için çeşitli formüller ve yaklaşımlar var, aslında tamamen ayrı bir başlık altında incelenmesi daha doğrudur. Ama biraz daha yukarıdan bakıp karmaşıklığı daha net görmeye çalışacağız.

Yazılım da karmaşıklığa neden olabilecek faktörler “Gereksinimler”,”Teknoloji” ve “İnsan” olarak 3 ayrı başlıkta toplanabilir.

Gereksinimler

Karmaşıklığa yol açabilecek en büyük etken, yazılıma ihtiyaç duyulan, yazılımın yaşamsal döngüsünü başlatan “Gereksinimler”dir. Gereksinimlerden dolayı, teknik anlamda oldukça kolay bir operasyon, oldukça karmaşık bir hal alabilir. Aslında bu karmaşıklık bazen kaçınılmaz olup, diğer başka faktörler ile minimum seviye indirilebilir.
Mesela bir sisteme kayıt olma işlemini örnek olarak alalım. Sistem için ad,soyad,TC Kimlik No. ve e-mail anlamlı olsun diyelim. Oldukça basit bir şekilde sisteme bu bilgileri alan bir arayüz yapıp, bu bilgileri sistem altına kayıt edebiliriz. Şimdi çeşitli ihtiyaçlardan dolayı, sistemi tekrar ele alalım…Kayıt işlemi sırasında TC Kimlik No. geçerli bir numara olduğundan emin olmamız gerekmekte. Ayrıca e-mail adresinin formatının geçerli bir e-mail adresi olduğunun da kontrolü gerekmekte. Ek olarak, e-mail adresinin gerçekten karşılığının olduğunu kayıt sırasında teyit etmemiz gerekmekte. Görmüş olduğunuz gibi bir kaç basit gereksinimden dolayı, ilk baştaki kayıt işlemi biraz daha karmaşıklaştı. Aynı anda 500.000 kişinin veri girişi yapabileceği bir gereksinim oluştu diyelim sonra da…Bir de farklı arayüz ortamlarında(mobil,web…vs.) giriş işleminin yapılması gerektiğini de düşünelim. İlk baştaki kayıt işlemi, son haline göre oldukça karmaşık bir hal aldı.

Teknoloji

Teknoloji kavramı, yazılımın yaşam sürecinde beyin görevini gören bir kavramdır. İnsanoğlu beynin karmaşıklığını çözememişken, teknoloji de yazılımın karmaşıklığına büyük etken sağlar aslında. Kullanılan teknoloji, yazılımın karmaşıklığına ayrıca yol da verir. Yani X teknolojisi ile başladığınız bir yazılım, gereksinimlerden dolayı Y teknolojisinden de az biraz kullanmanızı gerektirebilir. Bundan dolayı, yazılımınızın karmaşıklığı doğal olarak artmış olur. Yukarıda bahsetmiş olduğum kayıt örneğini bu açıdan yine ele alalım. İlk başta basit bir masaüstü uygulaması ile .NET Framework kullanarak kolayca kayıt işlemini yapabiliyorkan, aynı uygulamayı kiosk tarzı ya da belli bir amaç için çalışan cihaz üzerinde çalıştırmak istediğimizde C++ ile çok daha kolay yapabiliyor olabiliriz. Ya da milyonlarca kişinin sahip olduğu cep telefonlarında Java ile cep telefonlarına uygulama yazmak işimizi daha kolaylaştıracaktır. Bundan dolayı yazılım geliştirme sürecinde kullanılacak teknoloji, karmaşıklık adına oldukça önemlidir.

İnsan

Yazılımı kullanıcak ve geliştirecek kişi yazılımın yaşam sürecine direk olarak etki eder. Bu da zaman içerisinde yazılımın karmaşıklığını etkileri. Önce kullanıcı açısından bakalım. Yazılımı kullanacak olan kullanıcı belli ihtiyaçlarını karşılamak için yazılıma ihtiyaç duymuştur mutlaka. Genellikle bu ihtiyaçlarını önceden bir şekilde karşılayabildiği için, belli alışkanlıkları vardır. İşte bu alışkanlıklar, kullanıcının ne istediğinde önemli etken olabilmektedir. Birden fazla kullanıcı olduğundan dolayı da bu etki oldukça büyük olacaktır. Geliştirici açısından ele aldığımızda, karmaşıklık kat sayısı oldukça artabiliyor. Geliştirme sürecinde yer alacak kişilerin bilgi birikimleri, hakim oldukları teknoloji ve tecrübeleri, yazılımı ister istemez karmaşıklaştıracaktır. Bir yazılımcı, tecrübelerinden dolayı, X işini oldukça kolay yabiliyorken, aynı işi başka bir yazılımcı daha zor ama daha etkili bir şekilde yapabilir. Bu tarz yaklaşım farkları, yazılımın karmaşıklığında büyük etki yapabilir.

Başka faktörler de yazılımın karmaşıklığında etken olabilir tabi ki. Ama bu 3 kavramın en önemli ve etken olduğu kanısındayım. Ayrıca yazılımlar, doğası itibari ile mutlaka karmaşık olacaktır. Önemli olan bu karmaşıklığa yol açabilecek şeylerin farkında olup, karmaşıklığı minimuma indirmek. Neyse çok karıştırmadan,bitiriyorum bende…:) Şimdilik bu kadar…

  • Mar
  • 14
  • 2010

“Nesne” tasarımı bu,başka bir şeye benzemez…

Tags: | View: 591 | Comments:

Bir yazılım projesinde yazılım tasarımına başlarken, kafamızda ilk yaptığımız şey genellikle direk projenin nesne modelini çıkarmaya çalışmak oluyor. Yanlış bir şey olmasa da öncesinde yapılması gereken başka şeyler olduğundan ortaya çıkan nesne modeli ne kadar sağlıklı oluyor tartışılır. Kendi tecrübelerim ve gözlemlerime göre genellikle nesnelerin bir birleri ile ilişkilendirilmeleri konusunda hatalar yapabiliyoruz. Aslında hata demek doğru olmaz. Bazı noktaları düşünmeden, bazı şeyleri göz ardı ederek nesne modellerini oluşturuyoruz ve bunlar yazılım tasarımının ilerleyen aşamalarında sorun olarak karşımıza çıkmasa da, geliştirme sürecinde mutlaka karşımıza çıkıyor. Nesnelerin bir birleri ile olan ilişikileri ile bir sonraki yazımda daha çok ilgileniyor olacağım. Ama önce nesnelerimizi tasarlarken göz ardı edildiğini düşündüğüm bir kaç noktaya değinmek istiyorum.

Bir nesnenin var oluş sebebi…

Her hangi bir kavramın nesne modelini oluştururken, o kavramın ne amaçla var olduğunu asla unutmamak gerekir. Gerçekleştireceği operasyonların, o kavram dahilinde olduğunu kesinleştirmek nesne modelini ve ilgilerini oluşturmakta daha kolaylık sağlayacaktır. Matemetikte ki 4 işlemi soyutlayan bir nesneye, belli bir süre için faiz hesaplayan bir metodu da 4 işlem dahilinde olduğunu düşünerek eklemek o nesnenin karmaşıklığını artıracaktır. Farklı yerlerde farklı şekillerde var olabileceğinden tasarımsal olarak soruna yol açacaktır. Dolayısıyla nesnelerin görevlerinin çok net bir şekilde tanımlanıyor olması gerekmekte.

Bir nesnenin yaşam süresi…

Nesnelerin, bütün içerisinde ki yaşam süresini yönetebiliyor olmak çok önemlidir. Gelişen “geliştirme teknolojileri” bu sürenin yönetimini biraz olsun geliştiriciden alıyor olsa da, en azından nesnelerin yaşam sürelerinin farkında olmak bizim için çok önemli. “Object reference not set to an instance of an object”(sanırım en çok alınan hatadır) hatasını alıyor olmamız, bir bakıma da nesnelerimizin nerede, ne zaman, nasıl yaşadığının farkında olmamamızdan kaynaklanıyor diyebilirim. Nesnelerimizin, nerede, ne şekilde, ne kadar yaşayacağını ya da var olacağını çok iyi belirlememiz gerekiyor.

Bir nesnenin ilişkileri…

Nesnelerin bir birleri ile olan ilişkilerini ortaya net bir şekilde çıkarmak çok önemlidir. Bu noktada “Composition(part-of)”(Bileşim),“Aggregation(has-a)”(Kümelenme,bir araya gelme) ve “Inheritance(is-a)”(Kalıtım) kavramlarını anlıyor olmak çok önemlidir. Teorik olarak kavramlara hakim olsak bile, nesne tasarımlarında bunları uygulama konusunda zaman zaman sıkıntı çekilebiliyor. Nesneler arasında ki ilişikleri, hangi nesnenin hangi nesneye bağlı olduğunu ya da olacağını ilk başlarda kestirebiliyor olmak çok zor olsada,  bu zorluğa katlanıp çözme çabası olumlu sonuçları beraberinde getirecektir. Bu aşamada “Dependency injection”, “Inversion of control” kavramlarını da çok iyi anlıyor olmamız gerekmekte…
Bu üç başlığın yazılım tasarımı konusunda, özellikle nesne modeli oluştururken çok önemli olduğunu düşünüyorum. Şimdilik bu kadar…

  • Feb
  • 16
  • 2010

İnşaatta hazır beton kullanıyoruz,yazılımda da kum…

Tags: | View: 588 | Comments:

Bir çok yerde “Architecture and Design Patterns”(Mimari ve Tasarım Kalıpları) başlığına benzer başlıklar altında çeşitli yazılar okuyoruz. Ve çoğunun içeriği Gof(gang of four)’un ön ayak olduğu tasarım kalıpları ile ilgili…İyi,güzel ama peki bunların “mimari” kelimesi ile alakası ne…Direkt olarak pek yok…Evet, gerçekten pek yok…

Belki benden tecrübeli meslektaşlarım biraz kızacak ve hatta ne saçmalıyorsun falan diyecektir. Ama açıkcası “Design Patterns”(Tasarım kalıplarının) direk olarak mimari yaklaşımlar ile alakalı olduğunu düşünmüyorum, aslında düşünmediğim gibi, kendi tecrübelerimden,okuduklarımdan, öğrendiklerimden görüyorum da…

“Design Patterns”(Tasarım kalıpları) hakkında internette bir çok kaynak var. Çoğunda belli kod parçacıkları ile örnekler ile ne amaçla kullanacağımızı falan anlatılıyor.Süper, mükemmel…Ama erken…Daha kod yazmaya başlamadık ki…

Madem böyle kalıp falan başladık bahsetmeye, bu yazının amaçı olan “Architecture Patterns(Sytles)”’e(Mimari Kalıplara) geçelim.Çeşitli kaynaklarda mimari sitiller, bazılarında da mimari kalıplar şeklinde geçer, ama yazılımcıların bakış açısından daha kolay anlaşılacağını düşündüğüm için bende kalıp olarak kullanacağım. Önceki yazılarda da bahsettiğim ihtiyaçlar doğrultusunda şekillenecek(şekillenmesi gereken) mimarimizi, belli tecrübelerden, teknolojik açılardan ve belli limitlerden dolayı belli kalıplar dahilinde şekillendirmemiz bize yardımcı olabilir. Kurabiye yaparken kullanılan kalıplar ya da kumdan kaleler yaparken kullandığımız kovalar gibi…

Bu bağlamda, ne olduklarının çok farkında olmadığımız ama sık sık kullandığımız kavramlar ortaya çıkıyor. Mimari kalıplar…

Mimari kalıplar, geliştireceğimiz sistemlerin ya da yazılımların ihtiyaçlarımız doğrultusunda çok daha etkili çalışabilmesini sağlayacak ve mimarimizi geliştirirken bize yol gösterecek kalıplardır. Çok daha iyi anlaşılması adına aşağıdaki gibi bir liste yaparsam daha iyi olur sanırım.

  • Bileşen tabanlı mimari
  • Katmanlı mimari
  • P2P mimari
  • UI tabalı mimari
  • Mesaj bazlı mimari
  • Servis tabanlı mimari
  • Event tabanlı mimari

Yukarıda bazı popüler mimari kalıplardan örnekler var. Daha çeşitlenebilir tabi ki. Bunları tek tek şuan için açıklamayı düşünmüyorum. Bu noktada mimari kalıpların neden önemli olduğunu anlatmak istiyorum. Mimari kalıplar, ihtiyaçlarımızı daha net bir şekilde karşılamamızda bize yol gösterir. Ayrıca ihtiyaçlarımızı karşılarken, hangi yöntemleri kullanabiliriz bunları sunar. Bu kalıpları ayrı ayrı düşünüyor olmak biraz hatalı olabilir. Direk olarak kesiştirmek de hatalı olur. Mimari tasarımı yaparken, ihtiyaçlarımızı bu kalıplar doğrultusunda çerçeveleyip tasarımımızı yapmak çok daha sağlıklı sonuçlar getirecektir. Ayrıca bu kalıpların kendi içlerindeki kanıtlanmış yöntemler, sizi bir çok şeyden kurtarıyor da olacaktır.

Son olarak tekrardan “Design Patterns”-tasarım kalıplarının, mimari tasarımla direk alakası olmadığını söylemek istiyorum. Bu karıştırmadan dolayı kavramların da karıştığını görüyorum. İlerleyen yazılarda yine bu konulardan bahsediyor olacağım…Şimdilik bu kadar…

  • Feb
  • 13
  • 2010

İnşaat mı tasarlarız, yoksa mimarisini mi…

Tags: | View: 868 | Comments:

“Yazılım mı tasarlarız, yoksa yazılım mimarisini mi?” şeklinde yukarıdaki soruyu geliştirdiğimiz yazılımlar için de sorabiliriz. Hem yazılımın kendini, hem de yazılım mimarisini  tasarlamayı aynı kelime ile tanımladığımız için bu kavramlarda karışıyor. “Tasarım”…

“Software Design” ve “Software Architecture Design” iki farklı kavram aslında. Bu iki kavramın karıştırılıyor olması, mimari kavramların kaybolmasına neden oluyor ne yazık ki. Bundan dolayı “Tasarım”(Design) ve “Mimari”(Architecture) kavramlarının arasındaki sınırı çok iyi anlamamız gerekmekte. Tüm mimari yaklaşımlar aslında bir tasarımdır. Ama bu tasarım, “Yazılım Tasarımı”(Software Design) daki tasarım değil. Mimari olarak yaklaştığımız zaman, “tasarım” kavramı çok daha yukarıdan bakmamızı gerektiren bir kelime olarak karşımıza çıkıyor. Bir yazılım ya da sistemdeki bileşenlerin nasıl organize olduğu ve ilişkilendirildiği, o sisteme ya da yazılıma “Mimari” açıdan yaklaşımı gösterir. Bu bileşenlerin nasıl sınıflandırıldığı ve ayrıştığı ise “Tasarımı” olarak açıklanabilir. Biraz daha basite indirgememiz gerekirse, yazılım geliştirirken bileşenlerimizi  “sınıf”(class)’lara ayırmamız, bu “sınıf”lar arasında ilişkileri belirlememiz “tasarım” kavramının konusu. Ama bileşenlerimizin(component) nasıl ilişkilendirileceği de “mimari” kavramının konusu.

Açıkcası kendi geliştirdiğim yazılımlarda, bu iki kavramın ayrımını fark ediyor olmak geliştirme sürecini daha sağlıklı hale getiriyor.Bir yazılım geliştirmeden önce hepimizin yapmış olduğu bir tasarım mutlaka vardır. İşte bu tasarım süreci  mimari tasarıma denk geliyor aslında. Ve yazılım geliştirme sürecinde herkesinde bildiği gibi çok önemli bir yer kaplıyor. Bu süreçte dikkat edilmesi gereken bir çok önemli nokta var.Bunlardan bence en önemlilerini kendimce anlatmaya çalışacağım;

  • Sınırlar: Tasarım sürecinde, geliştirmemiz gereken yazılımın ya da sistemin ihtiyaçları ve neden gerekli olduklarını kesinlikle unutmamak lazım. Ve ihtiyaçtan fazlasını düşünmememiz lazım. Açıkcası bunu sürekli yaşıyorum. İster istemez yazılımın olabildiğince geniş bir kapsamı olması, ya da “genişletilebilir” kalite özelliğinin hem tasarım hemde geliştirme sürecinde öne çıkması kötü tasarımlara yol açıyor. İş gereksinimleri dışında, tasarımı karmaşıklaştıracak etkenleri tasarıma sokmamak ve ihtiyaçlarımız doğrultusunda sınırlarımızı aşmamak lazım.
  • Bileşenlerin Ayrılması: Tasarımı yaparken, bir birinden farklı tüm fonksiyonel özellikleri belli bileşenler olarak ayırmak tasarımın karmaşıklığını önleyecektir, ayrıca ihtiyaçların gerçekten karşılanabiliyor olmasının gözlemlenmesine ve bileşenlerin tek başlarına ne işe yaradıklarını da anlamaya yardımcı olacaktır.Literatürde “Separation of Concerns” olarak yer alan bu kavram, geliştirme sürecindeki tasarım kalıpları ile ne kadar önemli olduğunu zaten belli edecektir.  Dolayısıyla geliştirme sürecinde sonradan fark etmek yerine, başlangıçta bu yaklaşıma göre yapılacak tasarımlar faydalı olacaktır.
  • Bileşim(Composition) ve Kalıtım(Inheritance): Bu iki kavramın çok iyi anlaşılıyor olması gerekmekte. Çünkü geliştirilecek sistemin ya da yazılımın bileşenleri üzerinde bu iki kavramın çok büyük etkisi olacaktır. İhtiyaca göre bu iki yaklaşım doğru çizilmelidir.”Kalıtım”(Inheritance) bileşenler üzerinde bağımlılığı artıracağından, hangi bileşenlerin bir birleri ile alakalı olacağı ilişkisinin çok iyi tanımlanması gerekmekte. Öte yandan “Bileşim”(Composition) bileşen kavramını daha netleştirecektir.
  • Katmanlar(Layers): Geliştirilen sistem ya da yazılım da, bileşenler arasındaki ilişikileri görmek ve yönetmek adına sistemi ya da yazılımı katmanlara ayırmak tasarımı kolaylaştıracak ve temelini güçlendirecektir. Bu şekilde katmanlara ayırmak sistemdeki akışın yolunuda görmenize yardımcı olacaktır.

Mimari tasarımı yaparken bu tarz şeylere dikkat ediyor olmak, cidden bazı şeyleri çok daha net ortaya çıkarıyor ve sağlıklı bir geliştirme sürecinin ilk ışıklarını gösteriyor. En azından kendi tecrübelerime dayanarak bunu söyleyebilirim.Kendi tecrübelerim ve bilgilerim dahilinde “Mimari Tasarım” ve “Yazılım Tasarımı” arasındaki farkı anlatmaya çalıştım. Hatta biraz da “Mimari Tasarım”a daldım…Umarım faydalı olmuştur.İlerleyen zamanlarda bu konular hakkında daha çok yazıyor olacağım. Her türlü eleştiriniz ve düşüncenizi lütfen paylaşmaktan çekinmeyin. Bu kavramlar böyle böyle ortaya çıkıyor ve gelişiyor…Haydi görüşmek üzere…