SOLID Prenciples etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SOLID Prenciples etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

6 Haziran 2016 Pazartesi

1 - SINGLE RESPONSIBILITY PRINCIPLE (SRP) ( Tek Sorumluluk Prensibi)

     Merhabalar, bu yazımda bir önceki yazımda SOLID kısaltmasıyla  bahsetmiş olduğum Tasarım Prensiplerinden, SOLID'in ilk harfi olan S 'yi ifade eden "Single Responsibility Principle" den bahsediyor olacağım. 
      Tek Sorumluluk Prensibi olarak nitelendirilen SRP adından da anlaşılacağı gibi bir sınıf veya metodun tek bir görev/sorumluluğunun olması gerektiğini belirtmektedir. SRP bize açık bir şekilde, bir sınıf veya metodun değiştirilebilmesi için tek bir sebebinin bulunması gerektiğini izah etmektedir. Birden fazla görev veya sorumluluk yerine getiren metod veya sınıfların değiştirilmeye açık birden fazla sebepleri olacak, bu da zamanla kodda karmaşıklık ve olası hata ihtimalini çoğaltacaktır. Teoride bu şekilde açıkladığımız olay, elbette projelerimizde gerek zaman darlığından, gerekse de SRP' ye dikkat edilmediğinden bir metod veya sınıfın birden fazla işi yerine getireceği şekilde dizayn edilmektedir. Bu tasarlayacağımız dizaynda sınıf veya metodların birbirine olan bağlılıkları düşünüldüğünde zaman içerisinde yapılacak herhangi bir fonksiyonel değişikliğin, bağlı diğer yapılardaki fonksiyonellikleri ne derecede etkileyeceğini ön görmemiz neredeyse imkansızdır ve buda hemen hemen tüm sürecin en baştan bütünüyle test edilmesini gerektirecektir. Bunu yapabilecek otomatik test programlarımızın olduğunu varsaysak bile ( ki çoğu yazılım firmasında dahi yok), çıkacak hataları çözmek ve süreci sorunsuz atlatmak için ne kadar iş gücüne ihtiyacımız olduğunu göz önünde bulundurmanız gerekmektedir.
      Durumu örneklendirmemiz gerekirse aşağıdaki gibi hem promosyonları hesaplayan hem de fatura kaydeden bir metodumuz olduğunu düşünelim;









"PromosyonHesaplaFaturaKes" metodunun yaptığı 2 iş olduğundan, bu metodu değiştirmek için 2 farklı ana sebep hatta bunlara bağlı onlarca yan sebep olacaktır. Bu kesinlikle istenmeyen bir durumdur, ayrıca bu metod işlev olarak başka yerlerde kullanılmaya uygun değildir. Promosyon hesapları sürekli değişebileceğinden aynı metod muhtemelen başka hiç bir yerde kullanılamayacaktır. Bu yüzden bunları ayırıp aşağıdaki şekilde 2 parçaya bölmemiz gerekecektir.










Hatta ve hatta yapısal olarak promosyon hesabı sipariş ve irsaliyede de olabileceğinden ve yine promosyon hesaplama işleminin fatura kesme işleminden çok farklı bir işlevi olduğundan, bu metodlar ayrı sınıfların üyesi olarak yazılmalıdırlar. Son hali aşağıdaki gibi olan bir yapıda Promosyon hesaplamada bir hata varsa veya bir değişiklik isteniyorsa nereye bakacağımız bellidir. Tek bir işlevi olan "PromosyonHesapla" metodundaki değişiklik programa dinamizm kazandıracak, ayrıca birden fazla yerde (sipariş, irsaliye,fatura vs) kullanılabilecektir.















          Yazılan ilk hatalı yapıdaki gibi farklı farklı işleri yapan metodları maalesef çoğu zaman aynı sınıfın içine yazıyoruz ( dolduruyoruz desek daha mantıklı). Bu tip durumlarda satır sayısı 5000 'leri bulan sınıflarımız oluyor. Düşünün ki 5000 satırlık bir sınıf, ne işler yapıyordur, neler neler barındırıyordur içinde. Entegrasyonundan tutun, loglamaya hatta sisteme login logout olmaya kadar her işi defalarca yapan sınıflar hayal edebilirsiniz, etmeyin :) Ayrı görevi ve sorumlulukları olan ayrı sınıflar ve metodlar hayal edin, tıpkı bir insanın hem doktor hem mühendis olamayacağını ve bunların ayrı görev sorumlulukları olduğu gibi. Hatta biraz daha irdeleyin doktor ve mühendisi ayırdıktan sonra bunları da kendi içinde ayırma yoluna gidin; göz doktoru, cerrah, kbb doktoru gibi...Unutmayın ki eğer yazdığınız metodlar 30-35 satırı, sınıflar da 1000 satırı geçiyorsa yaptığınız işte bir yanlışlık vardır :) Yazılan kodların mutlaka tekrar gözden geçirilmesi ve mümkün mertebe farklı işler yapan daha küçük parçalara ayrılması gerekmektedir.
     Programı yazarken, tasarlarken mümkün mertebe bu şekilde düşünerek en dibe inmeye çalışın. Ayrı işlevi olan bölümleri kesinlikle ayrı ve olabildiğince özel işler yapan kısımlara ayırın ki program esnek olsun, aynı zamanda kırılganlık ve bağımlılığı düşük olsun.Unutmayın ki 100 küsür satırdan oluşan bir metodun değiştirilmesi veya hata düzeltmesi bir yana, daha küçük parçalara bölünmüş 15 satırlık metodun değiştirilmesi bir yanadır.
    Unutulmaması gereken bir konu SRP 'nin teoride kolay, fakat pratikte uygulamanın hiç de öyle olmadığıdır. Programın nerede küçük kısımlara ayrılması gerektiği kodu yazarken tamamen kestirilememektedir. O yüzden bu işlem ilk başlarda uygulanması çok zor bir yöntemdir.Bir bakışta programı parçalara bölmek tecrübe gerektiren bir iştir, fakat üstte yaptığımız gibi kodlar yazıldıktan sonra tekrar tekrar üstünden geçerek düzeltilip SRP 'ye uygun hale getirilebilir ki biz buna Kod Gözden Geçirme (Refactoring) diyoruz, buradan bu bilgiyi de vermiş olalım :)

Örnek :
  Şimdi ki örneğimizde çok basit bir web sayfası tasarlayıp, input olarak aldığı bilgiyi müşteri bakiyesi ile kontrol ederek yeterli bakiye varsa, db ye kayıt atıp müşteriye de mail gönderen bir tasarım gerçekleştirelim.


















Yukarıdaki örnek işlevsel olarak sadece 1 görev/sorumluluk  üstlenen farklı metodlara bölünmüş olmasına rağmen, birbirinden çok farklı işler yapan bu metodların aynı sınıf içinde yer alması dolayısıyla SRP dizaynına uymamaktadır. Projemizi SRP'ye uygun hale getirmek için Refactoring yaparak, Mail gönderimi ve Müşteri Bakiye Kontrol işlemini ayrı sınıflara alıp tekrar aşağıdaki gibi yazmamız gerekmektedir.


Projemizde farklı işler yapan metodları farklı sınıflara ayırdıktan sonra, hem esneklik hem de kullanılabilirliği sağlamış olduk. Hatta bir adım daha öteye giderek, mail gönderme ve limit sorgulamanın çok genel bir yapı olduğunu göz önüne alarak, projeye isimlendirme standartlarına da uyarak "SRP.Core" diye bir class library ekleyip sınıflarımı, katmanları da birbirinden ayırmış  olduğum "SRP.Core" içerisine ekliyorum ve yeni tasarımım aşağıdaki hale geliyor.

















   Yapıyı bu şekilde oluşturduktan sonra artık farklı projelere referans verilebilir hale getirmiş bulunmaktayım.Şu durumda sadece "SRP.Core" library projesini başka projelere referans vermemiz ortak kullanabilmek adına yeterli olacaktır, aksi durumda koskoca web projesini referans göstermek zorunda kalacaktık ki, bu durumda ne esneklik ne de modülerlikten bahsedebiliriz. Fakat son durumda katmanları ayırarak hem katmanlı ve modüler bir mimari, hem de SRP 'ye uygun dizaynı gerçekleştirip bir taşla iki kuş vurmuş olduk. 
     Böylece SOLID prensiplerinden ilki olan SRP' yi oldukça basit bir şekilde anlatmaya çalıştım, bir sonraki yazım olacak olan "Open/Closed Principle" ile görüşmek üzere.

3 Haziran 2016 Cuma

TASARIM PRENSİPLERİ (Design Principles - SOLID)

       Herkese merhaba, bugün ki ve bundan sonraki muhtemel 4 - 5 yazımda aslında yazmayı iple çektiğim ve gerek yazarken gerekse de uygularken çok zevk aldığım "Design Principles" konusuna değiniyor olacağım. Konuyu daha önce bilen, duyan herkesin "hah şimdi esas konuya geldi" dediğini duyar gibiyim. Bu yazının bugüne kadar ki olan diğer yazılarımdan en büyük farkı, daha çok mimariye/tasarıma giriyor olmasıdır. Tasarım Prensipleri altında anlatacağım konular projelerimizin mimari yapısı ile ilgili olacaktır.
         Tasarım Prensipleri fikrinin ortaya çıkış temeli "Daha İyisini Nasıl Yaparım?" düşüncesidir. Benzer şekilde bu soruyla ilişkili olarak "Daha Hızlı, Daha Kolay Bir Şekilde Nasıl Yaparım?" düşüncesi ve "En İyisini Nasıl Tasarlarım?" sorusunun karşılığı olarak ortaya çıkan kalıplardır. Hayatta her şeyin daha iyisinin zaman içerisinde gelişim sürecine bağlı olarak yapılabileceğini varsayarsak, benzer şekilde yazılan projelerin,programların da daha iyisi olabileceğini sakın unutmayın. İşte tam bu noktada "Nasıl?" sorusunu sorduğumuz her durumda dönüp "Design Principles" konularına bakabilirsiniz, bu sizin için bir anahtar niteliği taşımaktadır.
      Object Oriented Programming (OOP) ile uğraşan herkesin günümüz mimari kuralları çerçevesinde mutlaka bilmesi gereken Tasarım Prensipleri, dünyada hemen herkes tarafından kabul görmüş SOLID kısaltması ile belirtebileceğimiz 5 ana prensipten oluşmaktadır. Bu prensipler sırasıyla aşağıdaki gibidir.

1 - Single Responsibility Principle         (Tekil Somluluk Prensibi)
2 - Open/Closed Principle                      (Açık / Kapalılık Prensibi)
3 - Liskov's Subtitution Principle           (Liskovun Yer Değiştirebilme Prensibi)
4 - Interface Segregation Principle         (Interface Ayırım Prensibi)
5 - Dependency Inversion Principle       (Bağımlılığı Ters Çevirme Prensibi)

       Yukarıda saydığım prensiplerin baş harflerinden oluşan SOLID, sağlıklı mimariler oluşturup sağlam tasarımlar yapmamıza olanak sağlayan prensipler bütünüdür diyebiliriz. Bu prensipleri bilmek ve uygulamak kullandığımız programlama dillerinin (C#, Java,C++ vs) gücünün de farkına varmamızı sağlayacaktır. Şunu belirtmek isterim ki prensipleri ilk başlarda uygulamak hatta anlamak dahi zor olabilir, fakat zaman içinde pratik kazandıkça "Vaay bee böyle bir şey de mi varmış?Ben bugüne kadar ne hamallık yapmışım." diyeceksiniz, buna eminim.
       Bugüne kadar ki tecrübelerimden yola çıkarak şunu gönül rahatlığı ile söyleyebilirim ki, bu prensipleri uygulamak bazen hayat kurtarır. Özellikle çok fazla yazılımcı ile büyük bir firmada büyük projelerde çalışıyorsanız. Mesela 20 küsür yazılımcı arkadaşla aynı proje üzerinde ortak çalıştığım da oldu, tabi burada herkesin aynı bilgi beceri ve kabiliyette olmadığı aşikar. Bu tip durumda herkese belirli standartlarda kod yazdırabilmenin de tek yolu OOP-Design Principles' ten geçer. Biraz daha açmak gerekirse, hem web tabanlı uygulamaların hem android hem de ios cihazların ortak eriştiği yapıların olduğu ayrı ayrı projeler düşünün, birisinde yapılan hatalı bir kod değişikliği domino etkisi yaparak kalan projelerde yıkıma sebep olabiliyor. Bu tip durumlarda yazılan kod ya geri alınmak zorunda kalıyor, ya da sürekli hatalı yapılan işin üstüne hatalı yamalar yapılarak iş iyice içinden çıkılmaz hale gelebiliyor (olmaz demeyin kaç defa başıma geldi, oluyor). Bu sorunlar neticesinde iş dönüp dolaşıp, 5 ana prensibe uymayan hatalı mimari tasarıma dayanıyor.
       Hangi proje üzerinde çalışıyorsanız çalışın, şayet mimari tasarımı sıfırdan kurma gibi bir şansınız varsa bu tip sorunlarla karşılaşmamak adına bu 5 prensipten vazgeçmemek sizi daha sonra doğması muhtemel büyük sorunlardan koruyacaktır. Aksi halde belirli oranda oturmuş mimari yapıyı da oturup sıfırdan yazamayacağınız için, sürekli hatalı ve yeni hatalara gebe yamalar yapmak zorunda kalacaksınız ki iş iyice arap saçına dönecek. Zaman içinde projede çalışan her arkadaşın "Yeter be bıktım bu hatalardan" deyip bir bir yanınızdan istifa edip gittiğine şahit olacaksınız. Yanlış tasarlanmış sistemin içinde boğuşmak sürekli kendini tekrarlayan hataların doğmasına sebep olacaktır. Şurasını unutmayın ki bu hatalar da sizi sürekli mesaiye bırakıp, kendinize ve sevdiklerinize ayırabileceğiniz zamanı çalacak en önemlisi yaptığınız işten zevk almak yerine ızdırap çekmenize sebep olacaktır.
      Anlattıklarımı en başından beri toparlarsanız yapılan mimari hataların domino etkisini kendi hayatınızda dahi hissedeceksiniz. "Abartıyorsun" diyenleriniz vardır belki, ama inanın en ufak abartı olmadan hatta eksiği var fazlası yok diyebileceğim şekilde bizzat yaşadıklarımdan alıntı yaparak yazdım. Sonuç olarak "Sağlam, Esnek, Daha az kodla daha çok iş ve Dinamik" olarak nasıl program yazarım tasasında iseniz şayet, bu prensiplere mutlaka riayet etmenizi öneririm. Evet, bunlara uymadan kod yazılabilir mi? derseniz..Yazılır..Ama kendinizden ve ailenizden çalarak yazılır, üstelik yaptığınızdan işten zevk almadan ve her an yeni hatalar çıkacakmış tedirginliği ile yazılır..
      Bu yazım biraz daha sohbet tadında, birikmiş tecrübelerden bahsederek geçti. Önümüzde ki yazılarda bu prensipleri teker teker irdeleyip, bol örnek yapıyor olacağız. Bu konular zor evet ama bence çok zevkli, sonraki yazılarda görüşmek dileğiyle..