ServerErr0r
uid=0(root)
- Katılım
- 12 Eyl 2009
- Mesajlar
- 2,330
- Reaction score
- 0
- Puanları
- 0
Temmuz 2010’da Codeproject tarafından ödül almış bir makaledir.
Karım Farhana, kariyerine yazılım geliştirici olarak tekrar başlamak istiyor (kariyerine yazılım geliştirici olarak başlamıştı, ilk çocuğumuzun doğumu nedeni ile fazla ilerleyememişti) ve bugünlerde tecrübeli bir yazılım tasarımcısı ve geliştirici olarak ona Nesne Yönelimli Tasarımı öğretmeye çalışıyorum.
Yazılım uzmanlığımın ilk günlerinden itibaren, teknik bir meselenin ne kadar zor göründüğünü önemsememeye dikkat ederim, konuşma diline uygun biçimde açıklama, real hayat perspertifinden ve tartışmalarından olursa bu her zaman daha kolay olacaktır. Aynen bizim Nesne Yönelimli Tasarım konusunda yaptığımız verimli konuşma gibi, düşündüm ki bunu sizinle paylaşabilirim, belki birinin Nesne Yönelimli Tasarımı öğrenmesini için ilginç bir taktik olabilir.
Nesne yönelimli tasarımın bizim konuşmamızda nasıl yer aldığını izleyin.
NESNE YÖNELİMLİ TASARIMA GİRİŞ
Shubho: Hayatım, hadi Nesne yönelimli tasarımı öğrenmeye başlayalım, Nesne Yönelim ilkelerini biliyorsun, değilmi?
Farhana: Yani, Kapsülleme, Kalıtım ve Çok biçimlilikten bahsediyorsun değilmi? Evet, bu ilkeleri biliyorum.
Shubho: Peki, umarım classların ve nesnelerin nasıl kullanıldığınıda biliyorsundur. Hani Nesne Yönelimli Tasarımı bugün öğrenelim.
Farhana: Bir dakika bekle, Nesne Yönelim ilkeleri Nesne Yönelimli Programlama için yeterli değilmi? Yani, Ben özellikler ve metodlar içeren sınıflar tanımlayabiliyorum. Ben birde kendi türlerine bağlı kalıtımsal sınıflarda tanımlayabiliyorum. Yani, kaçırdığım nedir?
Shubho: Güzel soru, Nesne Yönelim ilkeleri ile Nesne Yönelimli tasarım aslında iki farklı şeydir. Sana gerçek hayattan bir örnekle anlamana yardımcı olmam için açıklamama izim ver.
Sen çocukken ilk öğrendiğin alfabe idi, doğrumu?
Farhana: Evet.
Shubho: Peki, Ve sen birde kelimeleri ve anlamlı kelimeleri yapmak için alfabeyi birleştirmenin nasıl olduğunu öğrendin. Bununla beraber, sen kelimeleri bir cümlede birleştirmek için biraz basit gramer öğrendin. Örneğin, gramer olarak doğru cümleler için zamanlara dikkat etmek zorundaydın, ve edatları, bağlaçları ve diğer özellikleri kullanmak zorundaydın. Söyle, bir cümle aşağıdaki gibidir.
"Ben" (zamir) "OOD"(isim) "öğrenmek"(fiil) "istiyorum"(fiil).
Görüyorsun, kelimeleri bu düzende bir araya getiriyorsun, ve cümlenin sonuda bazı anlamları olan bir cümle ile doğru kelimeleri seçiyorsun.
Farhana: Peki, yani bunun anlamı nedir?
Shubho: Bu Nesne Yönelim İlkelerine benzer. Nesne Yönelim İlkeleri basit ilkelerden ve Nesne Yönelimli Programlamanın ana fikrinden bahseder. Burada, Nesne Yönelim ilkelerini, kelimeleri kullanarak doğru ve anlamlı cümlelerin nasıl oluşturulduğunu öğreten basit gramerle karşılaştırabiliriz, ve Nesne Yönelim İlkeleri, sınıf oluşturmayı, kapsüllenmiş özellikleri ve içerisindeki metodları oluşturmayı öğretir, ve birde onların arasındaki hiyerarşiyi ve onları senin kodunun içerisinde nasıl kullanılacağını öğretir.
Farhana: Hmm.. Yani, Nesne Yönelimli Tasarım burada neye uygun? Bu noktayı anladım.
Shubho: Yakında cevabını öğreneceksin. Şimdi, Bazı başlıklardan makaleler ve denemeler yazman iyi olacaktır, ve birde farklı üzerinde uzman olduğun farklı konularda kitap yazmayı diliyorsun. Cümle oluşturmayı bilmek kitap yada makale yazmak için yeterli değil, doğrumu? Çokça yazman ve konuları iyi bir yöntemle açıklamayı öğrenmen gerek ki okuyucular kolaylıkla ne demeye çalıştığını anlayabilsinler.
Farhana: İlginç görünüyor, devam et!!
Shubho: Şimdi, eğer belli bir konuda bir kitap yazmak istiyorsan(örneğin, Nesne Yönelimli tasarımı öğrenme gibi), konuları ufak başlıklara nasıl ayıracağını bilmen gerekir, Birde bu bölümler üzerine pasajlar yazman gerekir, ve pasajlarda önsözleri, tanıtımları, açıklamaları, örnekleri ve diğer birçok paragrafı yazman gerekir. Tüm kitabı dizayn edip ve yazma teknikleri üzerine en iyi bazı pratikleri öğrenmen gerekir ki okuyucu ne açıklamaya çalıştığını kolaylıkla anlayabilsin. Bu daha büyük resimle alakalıdır.
Yazılım geliştirmede, OOD(Nesne Yönelimli Tasarım) daha büyük resme hitap eder, tekrar kullanılabilen, esnek, ve nasıl yaptığını anlatan bazı açıklamaların olduğu, sınıflarının ve kodunun modularize edilmiş bir şekilde yazılımını dizayn etmen gerekir ki sistemin nasıl çalıştığını tekrar sunmana gerek kalmasın. sınıflarını ve objelerini tasarlamayı uygulayabileceğin bazı tasarım ilkeleri bulunur. Düşünsene?
Farhana: Hmm.. Anafikri anladım, ama daha fazla öğrenmek gerek.
Shubho: Endişelenme, yakında öğreneceksin, sadece konuşmaya devam etmeme izin ver.
NEDEN NESNE YÖNELİMLİ TASARIM?
Shubho: Bu çok önemli bir soru. Hızlıca birçok sınıfımızı oluşturup ve yazılımı geliştirip, teslim edecekken neden OOD’yi bu kadar önemseyelim ki? Bu yeterli değilmi?
Farhana: Evet, Ben eskiden OOD’yi bilmiyordum, ve hala projeleri geliştirebiliyor ve teslim edebiliyordum. Yani, büyük mesele nedir?
Shubho: Peki, sana klasik bir cevap vermeme izin ver:
"Suda yürümek ve bir tarife göre yazılım geliştirmek kolaydır, eğer ikiside dondurulursa" - Edward V. Berard
Farhana: Yazılım geliştirme tariflerinin geliştirmeyi tamamen tıkadığınımı ifade ediyorsun?
Shubho: Tamamen!! Yazılımın evrensel gerçeği "yazılım değişime mecburdur" Neden?
Çünkü, yazılımın gerçek hayattaki iş problemlerini çözer ve gerçek hayattaki iş süreçlerini geliştirir ve değiştirir- daima
Yazılımın bugünün gereksiminlerine göre ne gerekiyorsa en iyi olarak onu yapar. Ama yazılımın değişiklikleri desteklemek için yeterlimidir? Hayır ise, senin akıllıca tasarlanmış bir yazılımın yoktur.
Farhana: Peki, lütfen akıllıca tasarlanmış yazılımı açıklarmısınız bayım!
Shubho: "Akıllıca tasarlanmış bir yazılım kolayca geliştirilmeye ayarlanmıştır; o genişletilebilir ve tekrar kullanılabilir"
Ve, İyi bir "Nesne Yönelimli Tasarım" uygulamak, bu kadar akıllıca tasarımı başarmak için bir anahtardır. Şimdi, yazdığın koda, iyi bir OOD’yi uygulayabildiğini ne zaman iddia edebilirsin?
Farhana: Bu, benimde sorum.
Shubho: Eğer yazdığın kod:
1- Tabiki, nesne yönelimli ise
2- Tekrar kullanılabilir ise
3- Az bir çaba ile değiştirilebiliyorsa
4- Var olan kodu değiştirmeden genişletilebiliyor ise
Nesne Yönelimli tasarımı yapıyorsun demektir
Farhana: ve?
Shubho: Biz yanlız değiliz, Birçok insanın bir sürü düşüncesi vardır ve birçok emek verilmiştir bu konuda. ve iyi Nesne Yönelimli Tasarımı başarmayı denemişlerdir ve Nesne Yönelimli Tasarımı yapmak için bazı basit ilkeleri saptamışlardır (Nesne yönelimli tasarımı kendi temandan kullanabilmen için bazı basit fikirler). Onlar birde bazı genel tasarım örneklerini yaygın senaryolara eklenebilmesi için tanımlamışlardır (temel düzeyi baz alarak)
Farhana: Bazılarını adlandırabilirmisin?
Shubho: Tabi. Bunların dışında birçok tasarım ilkesi vardır. ama temel düzeyde, SOLID ilkeleri olarak kısaltılmış 5 tane ilke vardır. (OOD ustası Uncle Bob’a teşekkürle)
S = Single Responsibility Principle
O = Opened Closed Principle
L = Liscov Substitution Principle
I = Interface Segregation Principle
D = Dependency Inversion Principle
Konuşmamızın devamında, bu ilkelerin herbirini detayları ile anlamaya çalışalım
SINGLE RESPONSİBİLİTY PRINCIPLE(Tek sorumluluk ilkesi)
Shubho: Sana ilk resmimi göstermeme izin ver. Bu resmi yapan kişiye teşekkür etmeliyiz, gerçekten çok ilginç.
Tek sorumluluk ilkesi resmi
Diyorki "Sadece tek bir aletle tüm özellikleri yerine getirebilirsin, yapmamalısın" Neden, Çünkü, uzun vadede bu birçok idare edilebilir problemide beraberinde getirir.
Nesne Yönelim terimleri ile bu ilkeyi sana anlatmama izin ver.
Orada asla bir sınıfı değiştirmek için birden fazla neden olmamalıydı.
Yada, farklı bir şekilde söylemek gerekirse :"Bir sınıf sadece ve sadece bir sorumluluğa sahip olmalıydı"
Farhana: Lütfen açıklarmısın?
Shubho: Tabi, Bu ilke şunu diyor, eğer sınıfınızda değiştirilmesi gerekecek birden fazla neden varsa (yada birden fazla sorumluluk üstlenmişse), sınıfınızı, sorumluluğunu baz alarak çoklu sınıflara ayırmanız gerekir.
Farhana: Hmm.. Yani, bunun anlamı, bir sınıfta birden fazla method’a sahip olunmamasımı?
Shubho: Hayır, hayır. Bir sınıfta birden fazla metodun olmasını tercih edebilirsin. Bu konu, onların tek bir amaca hizmet etmesi içindir. Şimdi, ayırmak neden önemlidir?
Önemlidir, çünkü:
1- Her sorumluluk bir değişim nedenidir.
2- Eğer sınıflar bir sorumluluktan fazlasına sahip olurlarsa, kod bağlanmaya başlayacaktır.
Farhana: Bana bir örnek verebilirmisin lütfen?
Shubho: Tabi, aşağıdaki kod hiyerarşisini kontrol et lütfen, aslında bu örnekte Uncle Bob’dan alınmıştır, kendisine tekrar teşekkürler.
SRP ilkesini bozan sınıf hiyerarşisi gösterimi
Burada, Rectangle sınıfı aşağıdakileri yapar;
1- Dikdörtgen alanını hesaplar
2- UI(user interface)’de dikdörtgeni sağlar
Ve iki uygulama Rectangle sınıfını kullanıyor
1- Hesaba dayalı geometri uygulaması, alan hesabı yapmak için bu uygulamayı kullanır
2- Bir grafik uygulaması UI’de bir dikdörtgen çizmek için bu sınıfı kullanır.
Farhana: Nasıl?
Shubho: Görüyorsun, Rectangle sınıfı aslında iki farklı şeyi icra ediyor. Bir metodda alan hesabını yapıyor, ve diğer bir metodda bir dikdörtgen simgesini döndürüyor. Bu durum bazı ilginç problemleri beraberinde getirir:
1- Hesaba dayalı geometri uygulamasına bu GUI yi dahil etmeliyiz. Geometri uygulamasını dağıtırken, GUI kütüphanesinide dahil etmeliyiz.
2- Grafik uygulama için Rectangle sınıfındaki bir değişiklik, hesaba dayalı geometri uygulaması için bir değişikliğe, yapılmasına ve test edilmesine neden olacaktır, ve aksine.
Farhana: Bu ilginçleşiyor. Yani sanıyorum sorumluluklarını baz alarak sınıfı parçalara ayırmamız gerekir, doğrumu?
Shubho: Kesinlikle, Neyi yapmamız gerektiğini tahmin edebilirmisin?
Farhana: Tabi, denememe izin ver. Bunu yapmak için nelere ihtiyaç duyduğumuz aşağıdadır.
Sorumlulukları iki farklı sınıfa dağıtalım. şunlar gibi:
1- Rectangle : Bu sınıf area() metodunu tanımlamalı.
2- RectangleUI : Bu sınıf Rectangle sınıfından türetilmeli ve Draw() metodunu tanımlamalıdır.
Shubho: Mükemmel, demek oluyor ki, Rectangle sınıfı hesaba dayalı geometri uygulaması tarafından kullanılacak, ve RectangleUI sınıfı grafik uygulaması tarafından kullanılacak. Biz bu sınıfları paylaşılabilir iki farklı DLL olarakta dağıtabiliriz, ve birini uygulamak için değişiklik gerektiğinde diğerine etki etmesine izin vermemeliyiz.
Farhana: Teşekkürler, Sanırım SRP(single responsibility principle)’yi anladım. Bir şey, SRP, işlere çok küçük parçalardan başlama fikri gibi gözüküyor böylece kodlar yeniden kullanılabilir ve merkezden idare edilebilir. Yani, metot düzeyinde SRP’i uygulamamalı mıydık?
Dediğim, birçok şeyi yapmak için kod satırlarında metod yazmış olabilirdik, bu metodlar SRP’yi bozuyor olabilirdi, doğrumu?
Shubho: Doğru olarak anlamışsın. metodlarını bölmelisin böylece her bir metod özel bir işi yapar. Bu metodlarını tekrak kullanmana izin verecektir ve değişiklik gereken bir durumda, küçük kod parçalarını modifiye ederek, değişiklik yapmana olanak tanıyacaktır.
OPEN-CLOSED PRİNCİPLE(Açıp-Kapama İlkesi)
Shubho: işte Open-closed principle için yeni postere gidiyoruz.
Açıp-Kapama ilkesi resmi
Tasarım terimlerini açıklamam gerekseydi, aynen aşağıdaki gibi olurdu.
"Yazılım öğeleri(sınıflar, modüller, işlevler..vs" gelişmelere açılmalı ama değişikliklere kapatılmalıdır."
En temel düzeyde, bunun anlamı, bir sınıf özelliği onu modifiye etmeden değiştirilebilmelidir. Bu aynen şuna benzer, bir elbiseyi bedenimde herhangi bir değişiklik yapmadan üzerime giyebilmeliyim, hehe..
Farhana: İlginç, giydiğin elbiseyi istersen görünüşüne göre değiştirebilirsin, ve kendi bedenini ona göre değiştirmene gerek yoktur. Yani gelişme için açıksındır, doğrumu?
Shubho: Evet, OOD’de gelişmeler için açılmanın anlamı modül yada sınıfın davranışını geliştirebilirsin ve değiştirme gereksinimleri olarak farklı ve yeni yollarla modül davranışı oluşturabiliriz, veya yeni uygulamaların gerekliliklerini karşılayabiliriz.
Farhana: Böylece bedenin değişime kapatılmış olur. Bu örnek hoşuma gitti. Gelişmelere ihtiyaç duyduğumuz zaman bir çekirdek sınıfı yada modül için kaynak kodu değiştirmemeliyiz, Bunları bazı örneklerle açıklayabilirmisin?
Açıp kapama ilkesini bozan sınıf hiyerarşisi gösterimi
Görüyorsun, Server ve Client sınıfları somutlaştırıldı. Böylece, eğer herhangi bir sebep içinse, server uygulaması değitirilecektır, Client’inde değiştirilmesi gerekir.
Farhana: Düşünsene.Eğer Bir browser özel bir servere sıkıca bağlanmış olarak yürütüldüğünde (IIS gibi), sonra eğer server bazı nedenlerden bir diğeriyle ile değiştirildiğinde (Apache, gibi), browser dahi değiştirilmeye ihtiyaç duyar veya değiştirilir. Bu gerçekten çok kötü olacaktır.
shubbo : Doğru, bundan dolayı doğru tasarımı izleyelim:
Açıp kapama ilkesini gösteren sınıf hiyerarşisi gösterimi
Bu örnekte, eklenen Abstract Server sınıfı vardır, ve client abstract sınıfından bir referans içerir, ve Somut Server sınıfı, Abstract server sınıfının yürütür. Yani, eğer bazı nedenlerden dolayı, server uygulaması değiştirilirse, Client’in herhangi bir değişikliği gerektirmesi olası değildir.
Abstract server sınıfı burada değişikliğe kapatılmıştır, ve Buradaki somut sınıf uygulamaları gelişmeler için açıktır.
Farhana: Anladığım şekilde, soyutlaştırma bir anahtardır, değilmi?
Shubho: Evet, basitçe, nesneleri soyutlaman sisteminin ana düşüncesidir, eğer soyutlamayı iyi bir şekilde yaparsan, muhtemelen, fonksiyonelliğinin geliştirileceği zaman onun değiştirilmesine gerek kalmayacaktır (serverin soyut bir kavram olması gibi). Ve, uygulamanda soyut nesneler tanımlarsın (IISServer’in server uygulaması gibi) ve karşı kod soyutlama kadar mümkündür (server). Bu client kodda herhangi bir değişiklik yapmadan soyut nesneyi geliştirmen ve yeni uygulama tanımlaman için sana izin verecektir(ApacheServer gibi).
LİSKOV’S SUBSTITUTION PRINCIPLE(Liskov’s yer değiştirme ilkesi)
Shubho: Liskov’s Substitution ilkeleri çok ağır gibi görünür, ama bu fikir oldukça basittir. İlginç bir resme göz gezdirelim.
Liskov’s yer değiştirme ilkesi resmi
Bu ilke şunu der :
"Alt tipler temel tiplerinin yerine konulabilir olmalılar"
Yada, farklı olarak söyleceksek eğer:
"sınıfları temel alan referansları kullanan fonksiyonlar, onu bilmeden türetilen sınıfların nesnelerini kullanabilmeliler"
Farhana: Üzgünüm, bunlar kafamı karıştırdı, bu OOP(Nesne yönelim ilkeleri) nin temeli olduğunu düşündüm. Bu çok biçimlilik, doğrumu? Bu konuda neden OOP’nin bir ilkesine gerek görülüyor?
Shubho: Güzel soru. Cevabı burda:
OOP’nin temelinde, "kalıtım" genellikle "mi midir" ilişkisi olarak tanımlanır. Eğer bir "geliştirici" "YazılımUzmanı" ise, o zaman "geliştirici" sınıfı "YazılımUzmanı"’dan türetilmiş olmalıdır. Bunun gibi "mi midir" ilişkileri sınıf tasarımında çok önemlidir,ama yanlış bir türetme ile bunun kontrolünü kaybedilmesi kolaydır ve yanlış tasarımla sonuçlanır.
The "Liskov’s Substitution İlkesi" sadece kalıtımın doğru olarak kullanıldığını garanti etmenin bir yoludur.
Farhana: Görüyorum, ilginç.
Shubho: Evet canım, gerçekten öyle. Hadi bir örneğe bakalım:
Sınıf hiyerarşisini gösteren Liskov’s yer değiştirme ilkesi örneği
Burda, KingFisher sınıfı Bird temel sınıfının uzantısıdır ve bundan dolayı yeterli olan Fly() metodunuda kalıtımla alır.
Şimdi başka bir örneğe bakalım:
Liskov yerdeğiştirme ilkesinin düzeltilen sınıf hiyerarşisi
Ostrich bir kuştur (kesinlikle öyle!) ve bundan dolayı Bird sınıfından türetilmiştir. Şimdi, o uçabiliyormu? Hayır! Burada, tasarım LSP’yi bozar.
Yani, gerçek dünyada bu doğal olarak gözükür, ama sınıf tasarımında, Ostrich, Bird sınıfından türetilmemelidir. ve orada gerçekte uçamıyan kuşlar için ayrı bir sınıf olmalıydı ve Ostrich ondan türetilmeliydi.
Farhana: Peki, anladım. Bu yüzden, LSP(Liskov’un yerdeğiştirme ilkesi) neden bu kadar önemli göstermeye çalışmama izin ver:
1- Eğer LSP korunmazsa, sınıf hiyerarşisinde dağınıklık olacaktır, ve eğer bir alt sınıf nesnesi metodlara parametre olarak aktarılırsa, garib davranış meydana gelecekti.
2- Eğer LSP korunmazsa, temel sınıflar için birim testi alt sınıflar için asla başarılı olmayacaktı.
Haklımıyım?
Shubho: Kesinlikle haklısın. Nesne tasarlayabilirsin ve kalıtımın doğru bir şekilde yapılıp yapılmadığını test etmek için, LSP’yi bir uygulama aracı olarak ekle.
THE INTERFACE SEGREGATİON PRINCIPLE(Arayüz ayrım ilkesi)
Shubho: Bugün, "Arayüz ayrım ilkesi" ni öğreneceğiz. resmimiz burda:
Arayüz ayrım ilkesi resmi
Farhana: Bunun anlamı nedir?
Shubho: Anlamı aşağıda:
"Müşterileri alışık olmadıkları arayüzleri kullanmaya zorlanılmamalıdır"
Farhana: Açıkla lütfen.
Shubho: Tabi, açıklaman burda:
Varsayalım ki televizyon almak istiyorsun ve iki seçeneğin var. Birinde birçok giriş ve düğme mevcut, ve birçoğuda karışık gözüküyor ve senin için zorunlu değil gibi gözüküyor. Bir diğerinin aşina olduğun ve senin için mantıklı olan birkaç girişi ve düğmesi var. Her iki televizyonunda aynı çalışma şekli olduğu hakkında kabaca bilgi verilmiş, hangisini seçerdin?
Farhana: Açıkçası daha az düğme ve girişi olanı tercih ederdim.
Shubho: Evet, ama neden?
Farhana: Çünkü bu kadar kafa karıştırıcı düğme ve girişe ihtiyacım yok ve benim için gerekli değil.
Shubho: Doğru, Aynı şekilde, birçok sınıfa sahipsin ve sınıflarının fonksiyonelliğini arayüzler kullanarak açığa çıkarıyorsun, öyleki dış dünyada uygun olan fonksiyonellikleri bilebilir ve müşteri kodu arayüzlere göre yapılabilir. Şimdi, bir arayüz çok büyükse ve birçok meydanda olan metoda sahipse, bu dış dünya için kafa karıştırıcı görünecektir. Birde, çok fazla metodlu arayüzler daha nadir tekrar kullanılabilirdir, ve kullanışsız metodlar eklenmiş böyle "şişman arayüzler" sınıflar arasındaki bağlantıların artmasına neden olacaktır.
Bu birde bir başka soruna neden olacaktır. Eğer bir sınıf arayüzde çalışmak isterse, o tüm metodlarını çalıştırmak zorundadır, bunlardan bazılarına bu sınıf tarafından herhangi bir şekilde ihtiyaç duyulmaz. Böylece, gereksiz karmaşıklığa neden olacak, ve sistemdeki sürdürülebilirlik ve sağlamlığı azaltacaktır.
Arayüz ayrım ilkesi, arayüzlerin geliştirilmesini garantiler öyleki onların her birinin kendi sorumluluklarına sahiptirler, böylece, özel, kolay anlaşılır, ve tekrar kullanılabilir olacaklardır.
Farhana: Görüyorum, Yani sen diyorsunki arayüzler sadece gerekli metodları içermeliler başka birşeyi değil?
Shubho: Kesinlikle, Hadi bir örneğe bakalım.
Aşağıdaki arayüz, ISP(arayüz ayrım ilkesi)ni bozan "Şişman arayüz"dür:
Arayüz ayrım ilkesini bozan arayüze bir örnek
IBird arayüzü (interface)nün Fly() metodu ile beraber birçok kuş davranışına sahip olduğuna dikkat et. Şimdi,eğer bir kuş sınıfı (Ostrich gibi) bu arayüzü uygularsa, bu Fly() davranışınıda uygulamak zorunda kalacaktır.(Ostich uçan bir kuş değildir)
Farhana: Bu doğru. Bu yüzden bu arayüzü ayrılmalımı?
Shubho: Evet, bu "Şişman arayüz" iki farklı arayüze (interface) ye ayrılmalı, IFlyingBird’in IBird’den türetildiği yerde, IBird ve IFlyingBird olarak ayrılmalı.
Arayüz ayrım ilkesi örneğinde arayüzün doğru uyarlanması
Eğer uçamayan bir kuş varsa (Ostrich gibi), IBird arayüzünü(interface) uygular, ve eğer uçabilen bir kuş varsa (KingFisher gibi), IflyingBird arayüzünü uygular.
Farhana: Yani, eğer birçok giriş ve düğmesi olan televizyonlu örneğe dönecek olursak, televizyon üreticisinin o televizyonun giriş ve düğmelerinin planlarının yeraldığı mavi kopyaya sahip olmalılar. Televizyonun yeni modelini üretmek istedikleri herhangi bir zamanda, eğer o mavi kopyayı tekrar kullanmalarına gerek olursa, en az planda yer aldığı kadar giriş ve düğme oluşturmaları gerekir. O, onların o planı tekrar kullanmalarına izin vermeyecektir, doğrumu?
Shubho: Doğru.
Farhana: Televizyonun mavi kopyasını öyle küçük parçalara bölmeliler ki, ne zaman yeni bir tür televizyon üretmek isteseler, o planı tekrar kullanabilsinler.
Shubho: Fikri anladın.
THE DEPENDENCY INVERSION PRINCIPLE(Bağımlılığı ters çevirme ilkesi)
Shubho: Bu SOLID ilkeleri arasındaki son ilkemiz. Resmimiz burda
Bağımlılığı ters çevirme ilkesi
Diyor ki..
"Yüksek seviye modüller düşük seviye üzerine bağlı olmamalıdır, daha iyisi, ikiside soyutlamalar üzerine bağlı olmalılar"
Shubho: Bunu anlamak için gerçek hayattan bir örnek düşünelim. Araban, motor, tekerlekler, klima ve diğerleri gibi birçok nesneden oluşur, doğrumu?
Farhana: Evet, tabi.
Shubho: Peki, bu nesnelerin hiçbiri sabit olarak tek bir ünite içinde inşa edimez; daha iyisi, bunların herbiri "pluggable" özelliktedir bu nedenle motor yada tekerlekte bir sorun olduğu zaman, onu onarabilirsin(diğerlerini onarmadan) ve değiştirebilirsin bile.
Değiştirme sırasında, sen sadece tekerleğin yada motorun arabanın tasarımına uygun olup olmadığına emin olmalısın (araba ancak 1500 CC motoru kabul edebilir ve 18 inç tekerlek ona uygun olabilir)
Tabi birde, araba 1500 CC yerine 2000 CC lik motoru koymana izin verebilir, üretici buna izin verebilir (Toyota gibi)
Şimdi, arabanın farklı parçaları bu kadar "pluggable yapı"da yapılmamış olsaydı ne olurdu?
Farhana: Bu korkunç olurdu! Çünkü, bu durumda, eğer arabanın motoru çalışmazsa, tüm arabayı tamir etmek yada yenisini almak zorunda kalınabilirdi.
Shubho: Evet, Şimdi, "Pluggable yapı" nasıl başarılabilir?
Farhana: "soyutlama"(Abstraction) anahtardır. doğrumu?
Shubho: Evet, gerçek dünyada, Araba daha yüksek seviye modül/varlıktır, ve o motorlar yada tekerlekler gibi daha aşağı modül/varlığa bağlıdır.
Motorlara veya tekerleklere güvenmekten ziyade, araba motor yada tekerleğin bazı tanımlamalarının soyutlanmasına bağlıdır ki, herhangi bir motor yada tekerlek soyutlamaya uyarsa, onlar arabaya uygun olacaklardır ve araba çalışacaktır.
Hadi aşağıdaki sınıf diyagramına gözatalım:
Bağımlılığı ters çevirme ilkesi sınıf hiyerarşisi
Shubho: Yukarıdaki araba sınıfında, iki özellik olduğuna dikkat et, ve bunların ikiside somut tipten ziyade soyut(abstract) tipte (Interface) dir.
Motor yada tekerlekler pluggabledir çünkü araba atanan arayüz(interface)ü uygulayacak herhangi bir nesneyi kabul edecektir, ve o araba sınıfında herhangi bir değişikliğe gerektirmeyecektir.
Farhana: Yani, eğer Bağımlılığı ters çevirme ilkesini kodumuzda uygulamaz isek, biz şu riskleri alırız:
1- Daha aşağı seviye sınıfları kullanan daha yüksek seviye kod zarar görecektir.
2- Daha aşağı seviye kodlarda meydana gelecek bir değişiklikte, daha yüksek seviye kodları değiştirmek için çok fazla zaman ve emek gerektirecektir.
3- Daha az tekrar kullanılabilir kod oluşturulmuş olacaktır.
Shubho: Harikasın hayatım!!
ÖZET
Shubho: SOLID ilkelerinden başka Nesne yönelimli tasarımın başka ilkeleride vardır.
1- "Composition over Inheritance"(Kalıtım üzerinde düzenleme): Kalıtımın üzerinde düzenleme üstünlüğünü anlatır.
2- "Principle of least knowledge"(Enaz bilgi ilkesi): "Daha az sınıfının bilmesi daha iyidir" der
3- "The Common Closure principle"(Genel kapama ilkesi): "İlişkili sınıflar bir arada paketlenmelidir" der
4- "The Stable Abstractions principle"(Dengeli soyutlama ilkesi): "Daha dengeli bir sınıf, daha soyut sınıflardan meydana gelmelidir" der
Farhana: Bu ilkeleride öğrenmelimiydim?
Shubho: Evet, tabiki, öğrenmen için internetin var. Sadece google bu ilkeleri anlamayı denemen için yeterlidir. Ve tabiki, yardıma ihtiyacın olduğunda bana sormaktan tereddüt etme.
Farhana: Bu tasarım ilkeleri üzerinden inşa edilen birçok tasarım örneği olduğunu duydum.
Shubho: Haklısın, Tasarım örnekleri aslında hiçbirşeydir, ama tekrar eden durumlarda akla getirilen tasarım önerileri sunar.
Farhana: Yani, Desing Patterns(Tasarım örneklerini) daha sonra öğrenecekmiyim?
Shubho: Evet hayatım.
Farhana: O, çıkıyor olacaktı, doğrumu?
Shubho: Evet, kesinlikle çıkıyor olacaktır.
Belgenin çevirisi yapılmamış özgün kaynağı
Karım Farhana, kariyerine yazılım geliştirici olarak tekrar başlamak istiyor (kariyerine yazılım geliştirici olarak başlamıştı, ilk çocuğumuzun doğumu nedeni ile fazla ilerleyememişti) ve bugünlerde tecrübeli bir yazılım tasarımcısı ve geliştirici olarak ona Nesne Yönelimli Tasarımı öğretmeye çalışıyorum.
Yazılım uzmanlığımın ilk günlerinden itibaren, teknik bir meselenin ne kadar zor göründüğünü önemsememeye dikkat ederim, konuşma diline uygun biçimde açıklama, real hayat perspertifinden ve tartışmalarından olursa bu her zaman daha kolay olacaktır. Aynen bizim Nesne Yönelimli Tasarım konusunda yaptığımız verimli konuşma gibi, düşündüm ki bunu sizinle paylaşabilirim, belki birinin Nesne Yönelimli Tasarımı öğrenmesini için ilginç bir taktik olabilir.
Nesne yönelimli tasarımın bizim konuşmamızda nasıl yer aldığını izleyin.
NESNE YÖNELİMLİ TASARIMA GİRİŞ
Shubho: Hayatım, hadi Nesne yönelimli tasarımı öğrenmeye başlayalım, Nesne Yönelim ilkelerini biliyorsun, değilmi?
Farhana: Yani, Kapsülleme, Kalıtım ve Çok biçimlilikten bahsediyorsun değilmi? Evet, bu ilkeleri biliyorum.
Shubho: Peki, umarım classların ve nesnelerin nasıl kullanıldığınıda biliyorsundur. Hani Nesne Yönelimli Tasarımı bugün öğrenelim.
Farhana: Bir dakika bekle, Nesne Yönelim ilkeleri Nesne Yönelimli Programlama için yeterli değilmi? Yani, Ben özellikler ve metodlar içeren sınıflar tanımlayabiliyorum. Ben birde kendi türlerine bağlı kalıtımsal sınıflarda tanımlayabiliyorum. Yani, kaçırdığım nedir?
Shubho: Güzel soru, Nesne Yönelim ilkeleri ile Nesne Yönelimli tasarım aslında iki farklı şeydir. Sana gerçek hayattan bir örnekle anlamana yardımcı olmam için açıklamama izim ver.
Sen çocukken ilk öğrendiğin alfabe idi, doğrumu?
Farhana: Evet.
Shubho: Peki, Ve sen birde kelimeleri ve anlamlı kelimeleri yapmak için alfabeyi birleştirmenin nasıl olduğunu öğrendin. Bununla beraber, sen kelimeleri bir cümlede birleştirmek için biraz basit gramer öğrendin. Örneğin, gramer olarak doğru cümleler için zamanlara dikkat etmek zorundaydın, ve edatları, bağlaçları ve diğer özellikleri kullanmak zorundaydın. Söyle, bir cümle aşağıdaki gibidir.
"Ben" (zamir) "OOD"(isim) "öğrenmek"(fiil) "istiyorum"(fiil).
Görüyorsun, kelimeleri bu düzende bir araya getiriyorsun, ve cümlenin sonuda bazı anlamları olan bir cümle ile doğru kelimeleri seçiyorsun.
Farhana: Peki, yani bunun anlamı nedir?
Shubho: Bu Nesne Yönelim İlkelerine benzer. Nesne Yönelim İlkeleri basit ilkelerden ve Nesne Yönelimli Programlamanın ana fikrinden bahseder. Burada, Nesne Yönelim ilkelerini, kelimeleri kullanarak doğru ve anlamlı cümlelerin nasıl oluşturulduğunu öğreten basit gramerle karşılaştırabiliriz, ve Nesne Yönelim İlkeleri, sınıf oluşturmayı, kapsüllenmiş özellikleri ve içerisindeki metodları oluşturmayı öğretir, ve birde onların arasındaki hiyerarşiyi ve onları senin kodunun içerisinde nasıl kullanılacağını öğretir.
Farhana: Hmm.. Yani, Nesne Yönelimli Tasarım burada neye uygun? Bu noktayı anladım.
Shubho: Yakında cevabını öğreneceksin. Şimdi, Bazı başlıklardan makaleler ve denemeler yazman iyi olacaktır, ve birde farklı üzerinde uzman olduğun farklı konularda kitap yazmayı diliyorsun. Cümle oluşturmayı bilmek kitap yada makale yazmak için yeterli değil, doğrumu? Çokça yazman ve konuları iyi bir yöntemle açıklamayı öğrenmen gerek ki okuyucular kolaylıkla ne demeye çalıştığını anlayabilsinler.
Farhana: İlginç görünüyor, devam et!!
Shubho: Şimdi, eğer belli bir konuda bir kitap yazmak istiyorsan(örneğin, Nesne Yönelimli tasarımı öğrenme gibi), konuları ufak başlıklara nasıl ayıracağını bilmen gerekir, Birde bu bölümler üzerine pasajlar yazman gerekir, ve pasajlarda önsözleri, tanıtımları, açıklamaları, örnekleri ve diğer birçok paragrafı yazman gerekir. Tüm kitabı dizayn edip ve yazma teknikleri üzerine en iyi bazı pratikleri öğrenmen gerekir ki okuyucu ne açıklamaya çalıştığını kolaylıkla anlayabilsin. Bu daha büyük resimle alakalıdır.
Yazılım geliştirmede, OOD(Nesne Yönelimli Tasarım) daha büyük resme hitap eder, tekrar kullanılabilen, esnek, ve nasıl yaptığını anlatan bazı açıklamaların olduğu, sınıflarının ve kodunun modularize edilmiş bir şekilde yazılımını dizayn etmen gerekir ki sistemin nasıl çalıştığını tekrar sunmana gerek kalmasın. sınıflarını ve objelerini tasarlamayı uygulayabileceğin bazı tasarım ilkeleri bulunur. Düşünsene?
Farhana: Hmm.. Anafikri anladım, ama daha fazla öğrenmek gerek.
Shubho: Endişelenme, yakında öğreneceksin, sadece konuşmaya devam etmeme izin ver.
NEDEN NESNE YÖNELİMLİ TASARIM?
Shubho: Bu çok önemli bir soru. Hızlıca birçok sınıfımızı oluşturup ve yazılımı geliştirip, teslim edecekken neden OOD’yi bu kadar önemseyelim ki? Bu yeterli değilmi?
Farhana: Evet, Ben eskiden OOD’yi bilmiyordum, ve hala projeleri geliştirebiliyor ve teslim edebiliyordum. Yani, büyük mesele nedir?
Shubho: Peki, sana klasik bir cevap vermeme izin ver:
"Suda yürümek ve bir tarife göre yazılım geliştirmek kolaydır, eğer ikiside dondurulursa" - Edward V. Berard
Farhana: Yazılım geliştirme tariflerinin geliştirmeyi tamamen tıkadığınımı ifade ediyorsun?
Shubho: Tamamen!! Yazılımın evrensel gerçeği "yazılım değişime mecburdur" Neden?
Çünkü, yazılımın gerçek hayattaki iş problemlerini çözer ve gerçek hayattaki iş süreçlerini geliştirir ve değiştirir- daima
Yazılımın bugünün gereksiminlerine göre ne gerekiyorsa en iyi olarak onu yapar. Ama yazılımın değişiklikleri desteklemek için yeterlimidir? Hayır ise, senin akıllıca tasarlanmış bir yazılımın yoktur.
Farhana: Peki, lütfen akıllıca tasarlanmış yazılımı açıklarmısınız bayım!
Shubho: "Akıllıca tasarlanmış bir yazılım kolayca geliştirilmeye ayarlanmıştır; o genişletilebilir ve tekrar kullanılabilir"
Ve, İyi bir "Nesne Yönelimli Tasarım" uygulamak, bu kadar akıllıca tasarımı başarmak için bir anahtardır. Şimdi, yazdığın koda, iyi bir OOD’yi uygulayabildiğini ne zaman iddia edebilirsin?
Farhana: Bu, benimde sorum.
Shubho: Eğer yazdığın kod:
1- Tabiki, nesne yönelimli ise
2- Tekrar kullanılabilir ise
3- Az bir çaba ile değiştirilebiliyorsa
4- Var olan kodu değiştirmeden genişletilebiliyor ise
Nesne Yönelimli tasarımı yapıyorsun demektir
Farhana: ve?
Shubho: Biz yanlız değiliz, Birçok insanın bir sürü düşüncesi vardır ve birçok emek verilmiştir bu konuda. ve iyi Nesne Yönelimli Tasarımı başarmayı denemişlerdir ve Nesne Yönelimli Tasarımı yapmak için bazı basit ilkeleri saptamışlardır (Nesne yönelimli tasarımı kendi temandan kullanabilmen için bazı basit fikirler). Onlar birde bazı genel tasarım örneklerini yaygın senaryolara eklenebilmesi için tanımlamışlardır (temel düzeyi baz alarak)
Farhana: Bazılarını adlandırabilirmisin?
Shubho: Tabi. Bunların dışında birçok tasarım ilkesi vardır. ama temel düzeyde, SOLID ilkeleri olarak kısaltılmış 5 tane ilke vardır. (OOD ustası Uncle Bob’a teşekkürle)
S = Single Responsibility Principle
O = Opened Closed Principle
L = Liscov Substitution Principle
I = Interface Segregation Principle
D = Dependency Inversion Principle
Konuşmamızın devamında, bu ilkelerin herbirini detayları ile anlamaya çalışalım
SINGLE RESPONSİBİLİTY PRINCIPLE(Tek sorumluluk ilkesi)
Shubho: Sana ilk resmimi göstermeme izin ver. Bu resmi yapan kişiye teşekkür etmeliyiz, gerçekten çok ilginç.

Tek sorumluluk ilkesi resmi
Diyorki "Sadece tek bir aletle tüm özellikleri yerine getirebilirsin, yapmamalısın" Neden, Çünkü, uzun vadede bu birçok idare edilebilir problemide beraberinde getirir.
Nesne Yönelim terimleri ile bu ilkeyi sana anlatmama izin ver.
Orada asla bir sınıfı değiştirmek için birden fazla neden olmamalıydı.
Yada, farklı bir şekilde söylemek gerekirse :"Bir sınıf sadece ve sadece bir sorumluluğa sahip olmalıydı"
Farhana: Lütfen açıklarmısın?
Shubho: Tabi, Bu ilke şunu diyor, eğer sınıfınızda değiştirilmesi gerekecek birden fazla neden varsa (yada birden fazla sorumluluk üstlenmişse), sınıfınızı, sorumluluğunu baz alarak çoklu sınıflara ayırmanız gerekir.
Farhana: Hmm.. Yani, bunun anlamı, bir sınıfta birden fazla method’a sahip olunmamasımı?
Shubho: Hayır, hayır. Bir sınıfta birden fazla metodun olmasını tercih edebilirsin. Bu konu, onların tek bir amaca hizmet etmesi içindir. Şimdi, ayırmak neden önemlidir?
Önemlidir, çünkü:
1- Her sorumluluk bir değişim nedenidir.
2- Eğer sınıflar bir sorumluluktan fazlasına sahip olurlarsa, kod bağlanmaya başlayacaktır.
Farhana: Bana bir örnek verebilirmisin lütfen?
Shubho: Tabi, aşağıdaki kod hiyerarşisini kontrol et lütfen, aslında bu örnekte Uncle Bob’dan alınmıştır, kendisine tekrar teşekkürler.

SRP ilkesini bozan sınıf hiyerarşisi gösterimi
Burada, Rectangle sınıfı aşağıdakileri yapar;
1- Dikdörtgen alanını hesaplar
2- UI(user interface)’de dikdörtgeni sağlar
Ve iki uygulama Rectangle sınıfını kullanıyor
1- Hesaba dayalı geometri uygulaması, alan hesabı yapmak için bu uygulamayı kullanır
2- Bir grafik uygulaması UI’de bir dikdörtgen çizmek için bu sınıfı kullanır.
Farhana: Nasıl?
Shubho: Görüyorsun, Rectangle sınıfı aslında iki farklı şeyi icra ediyor. Bir metodda alan hesabını yapıyor, ve diğer bir metodda bir dikdörtgen simgesini döndürüyor. Bu durum bazı ilginç problemleri beraberinde getirir:
1- Hesaba dayalı geometri uygulamasına bu GUI yi dahil etmeliyiz. Geometri uygulamasını dağıtırken, GUI kütüphanesinide dahil etmeliyiz.
2- Grafik uygulama için Rectangle sınıfındaki bir değişiklik, hesaba dayalı geometri uygulaması için bir değişikliğe, yapılmasına ve test edilmesine neden olacaktır, ve aksine.
Farhana: Bu ilginçleşiyor. Yani sanıyorum sorumluluklarını baz alarak sınıfı parçalara ayırmamız gerekir, doğrumu?
Shubho: Kesinlikle, Neyi yapmamız gerektiğini tahmin edebilirmisin?
Farhana: Tabi, denememe izin ver. Bunu yapmak için nelere ihtiyaç duyduğumuz aşağıdadır.
Sorumlulukları iki farklı sınıfa dağıtalım. şunlar gibi:
1- Rectangle : Bu sınıf area() metodunu tanımlamalı.
2- RectangleUI : Bu sınıf Rectangle sınıfından türetilmeli ve Draw() metodunu tanımlamalıdır.
Shubho: Mükemmel, demek oluyor ki, Rectangle sınıfı hesaba dayalı geometri uygulaması tarafından kullanılacak, ve RectangleUI sınıfı grafik uygulaması tarafından kullanılacak. Biz bu sınıfları paylaşılabilir iki farklı DLL olarakta dağıtabiliriz, ve birini uygulamak için değişiklik gerektiğinde diğerine etki etmesine izin vermemeliyiz.
Farhana: Teşekkürler, Sanırım SRP(single responsibility principle)’yi anladım. Bir şey, SRP, işlere çok küçük parçalardan başlama fikri gibi gözüküyor böylece kodlar yeniden kullanılabilir ve merkezden idare edilebilir. Yani, metot düzeyinde SRP’i uygulamamalı mıydık?
Dediğim, birçok şeyi yapmak için kod satırlarında metod yazmış olabilirdik, bu metodlar SRP’yi bozuyor olabilirdi, doğrumu?
Shubho: Doğru olarak anlamışsın. metodlarını bölmelisin böylece her bir metod özel bir işi yapar. Bu metodlarını tekrak kullanmana izin verecektir ve değişiklik gereken bir durumda, küçük kod parçalarını modifiye ederek, değişiklik yapmana olanak tanıyacaktır.
OPEN-CLOSED PRİNCİPLE(Açıp-Kapama İlkesi)
Shubho: işte Open-closed principle için yeni postere gidiyoruz.

Açıp-Kapama ilkesi resmi
Tasarım terimlerini açıklamam gerekseydi, aynen aşağıdaki gibi olurdu.
"Yazılım öğeleri(sınıflar, modüller, işlevler..vs" gelişmelere açılmalı ama değişikliklere kapatılmalıdır."
En temel düzeyde, bunun anlamı, bir sınıf özelliği onu modifiye etmeden değiştirilebilmelidir. Bu aynen şuna benzer, bir elbiseyi bedenimde herhangi bir değişiklik yapmadan üzerime giyebilmeliyim, hehe..
Farhana: İlginç, giydiğin elbiseyi istersen görünüşüne göre değiştirebilirsin, ve kendi bedenini ona göre değiştirmene gerek yoktur. Yani gelişme için açıksındır, doğrumu?
Shubho: Evet, OOD’de gelişmeler için açılmanın anlamı modül yada sınıfın davranışını geliştirebilirsin ve değiştirme gereksinimleri olarak farklı ve yeni yollarla modül davranışı oluşturabiliriz, veya yeni uygulamaların gerekliliklerini karşılayabiliriz.
Farhana: Böylece bedenin değişime kapatılmış olur. Bu örnek hoşuma gitti. Gelişmelere ihtiyaç duyduğumuz zaman bir çekirdek sınıfı yada modül için kaynak kodu değiştirmemeliyiz, Bunları bazı örneklerle açıklayabilirmisin?

Açıp kapama ilkesini bozan sınıf hiyerarşisi gösterimi
Görüyorsun, Server ve Client sınıfları somutlaştırıldı. Böylece, eğer herhangi bir sebep içinse, server uygulaması değitirilecektır, Client’inde değiştirilmesi gerekir.
Farhana: Düşünsene.Eğer Bir browser özel bir servere sıkıca bağlanmış olarak yürütüldüğünde (IIS gibi), sonra eğer server bazı nedenlerden bir diğeriyle ile değiştirildiğinde (Apache, gibi), browser dahi değiştirilmeye ihtiyaç duyar veya değiştirilir. Bu gerçekten çok kötü olacaktır.
shubbo : Doğru, bundan dolayı doğru tasarımı izleyelim:

Açıp kapama ilkesini gösteren sınıf hiyerarşisi gösterimi
Bu örnekte, eklenen Abstract Server sınıfı vardır, ve client abstract sınıfından bir referans içerir, ve Somut Server sınıfı, Abstract server sınıfının yürütür. Yani, eğer bazı nedenlerden dolayı, server uygulaması değiştirilirse, Client’in herhangi bir değişikliği gerektirmesi olası değildir.
Abstract server sınıfı burada değişikliğe kapatılmıştır, ve Buradaki somut sınıf uygulamaları gelişmeler için açıktır.
Farhana: Anladığım şekilde, soyutlaştırma bir anahtardır, değilmi?
Shubho: Evet, basitçe, nesneleri soyutlaman sisteminin ana düşüncesidir, eğer soyutlamayı iyi bir şekilde yaparsan, muhtemelen, fonksiyonelliğinin geliştirileceği zaman onun değiştirilmesine gerek kalmayacaktır (serverin soyut bir kavram olması gibi). Ve, uygulamanda soyut nesneler tanımlarsın (IISServer’in server uygulaması gibi) ve karşı kod soyutlama kadar mümkündür (server). Bu client kodda herhangi bir değişiklik yapmadan soyut nesneyi geliştirmen ve yeni uygulama tanımlaman için sana izin verecektir(ApacheServer gibi).
LİSKOV’S SUBSTITUTION PRINCIPLE(Liskov’s yer değiştirme ilkesi)
Shubho: Liskov’s Substitution ilkeleri çok ağır gibi görünür, ama bu fikir oldukça basittir. İlginç bir resme göz gezdirelim.

Liskov’s yer değiştirme ilkesi resmi
Bu ilke şunu der :
"Alt tipler temel tiplerinin yerine konulabilir olmalılar"
Yada, farklı olarak söyleceksek eğer:
"sınıfları temel alan referansları kullanan fonksiyonlar, onu bilmeden türetilen sınıfların nesnelerini kullanabilmeliler"
Farhana: Üzgünüm, bunlar kafamı karıştırdı, bu OOP(Nesne yönelim ilkeleri) nin temeli olduğunu düşündüm. Bu çok biçimlilik, doğrumu? Bu konuda neden OOP’nin bir ilkesine gerek görülüyor?
Shubho: Güzel soru. Cevabı burda:
OOP’nin temelinde, "kalıtım" genellikle "mi midir" ilişkisi olarak tanımlanır. Eğer bir "geliştirici" "YazılımUzmanı" ise, o zaman "geliştirici" sınıfı "YazılımUzmanı"’dan türetilmiş olmalıdır. Bunun gibi "mi midir" ilişkileri sınıf tasarımında çok önemlidir,ama yanlış bir türetme ile bunun kontrolünü kaybedilmesi kolaydır ve yanlış tasarımla sonuçlanır.
The "Liskov’s Substitution İlkesi" sadece kalıtımın doğru olarak kullanıldığını garanti etmenin bir yoludur.
Farhana: Görüyorum, ilginç.
Shubho: Evet canım, gerçekten öyle. Hadi bir örneğe bakalım:

Sınıf hiyerarşisini gösteren Liskov’s yer değiştirme ilkesi örneği
Burda, KingFisher sınıfı Bird temel sınıfının uzantısıdır ve bundan dolayı yeterli olan Fly() metodunuda kalıtımla alır.
Şimdi başka bir örneğe bakalım:

Liskov yerdeğiştirme ilkesinin düzeltilen sınıf hiyerarşisi
Ostrich bir kuştur (kesinlikle öyle!) ve bundan dolayı Bird sınıfından türetilmiştir. Şimdi, o uçabiliyormu? Hayır! Burada, tasarım LSP’yi bozar.
Yani, gerçek dünyada bu doğal olarak gözükür, ama sınıf tasarımında, Ostrich, Bird sınıfından türetilmemelidir. ve orada gerçekte uçamıyan kuşlar için ayrı bir sınıf olmalıydı ve Ostrich ondan türetilmeliydi.
Farhana: Peki, anladım. Bu yüzden, LSP(Liskov’un yerdeğiştirme ilkesi) neden bu kadar önemli göstermeye çalışmama izin ver:
1- Eğer LSP korunmazsa, sınıf hiyerarşisinde dağınıklık olacaktır, ve eğer bir alt sınıf nesnesi metodlara parametre olarak aktarılırsa, garib davranış meydana gelecekti.
2- Eğer LSP korunmazsa, temel sınıflar için birim testi alt sınıflar için asla başarılı olmayacaktı.
Haklımıyım?
Shubho: Kesinlikle haklısın. Nesne tasarlayabilirsin ve kalıtımın doğru bir şekilde yapılıp yapılmadığını test etmek için, LSP’yi bir uygulama aracı olarak ekle.
THE INTERFACE SEGREGATİON PRINCIPLE(Arayüz ayrım ilkesi)
Shubho: Bugün, "Arayüz ayrım ilkesi" ni öğreneceğiz. resmimiz burda:

Arayüz ayrım ilkesi resmi
Farhana: Bunun anlamı nedir?
Shubho: Anlamı aşağıda:
"Müşterileri alışık olmadıkları arayüzleri kullanmaya zorlanılmamalıdır"
Farhana: Açıkla lütfen.
Shubho: Tabi, açıklaman burda:
Varsayalım ki televizyon almak istiyorsun ve iki seçeneğin var. Birinde birçok giriş ve düğme mevcut, ve birçoğuda karışık gözüküyor ve senin için zorunlu değil gibi gözüküyor. Bir diğerinin aşina olduğun ve senin için mantıklı olan birkaç girişi ve düğmesi var. Her iki televizyonunda aynı çalışma şekli olduğu hakkında kabaca bilgi verilmiş, hangisini seçerdin?
Farhana: Açıkçası daha az düğme ve girişi olanı tercih ederdim.
Shubho: Evet, ama neden?
Farhana: Çünkü bu kadar kafa karıştırıcı düğme ve girişe ihtiyacım yok ve benim için gerekli değil.
Shubho: Doğru, Aynı şekilde, birçok sınıfa sahipsin ve sınıflarının fonksiyonelliğini arayüzler kullanarak açığa çıkarıyorsun, öyleki dış dünyada uygun olan fonksiyonellikleri bilebilir ve müşteri kodu arayüzlere göre yapılabilir. Şimdi, bir arayüz çok büyükse ve birçok meydanda olan metoda sahipse, bu dış dünya için kafa karıştırıcı görünecektir. Birde, çok fazla metodlu arayüzler daha nadir tekrar kullanılabilirdir, ve kullanışsız metodlar eklenmiş böyle "şişman arayüzler" sınıflar arasındaki bağlantıların artmasına neden olacaktır.
Bu birde bir başka soruna neden olacaktır. Eğer bir sınıf arayüzde çalışmak isterse, o tüm metodlarını çalıştırmak zorundadır, bunlardan bazılarına bu sınıf tarafından herhangi bir şekilde ihtiyaç duyulmaz. Böylece, gereksiz karmaşıklığa neden olacak, ve sistemdeki sürdürülebilirlik ve sağlamlığı azaltacaktır.
Arayüz ayrım ilkesi, arayüzlerin geliştirilmesini garantiler öyleki onların her birinin kendi sorumluluklarına sahiptirler, böylece, özel, kolay anlaşılır, ve tekrar kullanılabilir olacaklardır.
Farhana: Görüyorum, Yani sen diyorsunki arayüzler sadece gerekli metodları içermeliler başka birşeyi değil?
Shubho: Kesinlikle, Hadi bir örneğe bakalım.
Aşağıdaki arayüz, ISP(arayüz ayrım ilkesi)ni bozan "Şişman arayüz"dür:

Arayüz ayrım ilkesini bozan arayüze bir örnek
IBird arayüzü (interface)nün Fly() metodu ile beraber birçok kuş davranışına sahip olduğuna dikkat et. Şimdi,eğer bir kuş sınıfı (Ostrich gibi) bu arayüzü uygularsa, bu Fly() davranışınıda uygulamak zorunda kalacaktır.(Ostich uçan bir kuş değildir)
Farhana: Bu doğru. Bu yüzden bu arayüzü ayrılmalımı?
Shubho: Evet, bu "Şişman arayüz" iki farklı arayüze (interface) ye ayrılmalı, IFlyingBird’in IBird’den türetildiği yerde, IBird ve IFlyingBird olarak ayrılmalı.

Arayüz ayrım ilkesi örneğinde arayüzün doğru uyarlanması
Eğer uçamayan bir kuş varsa (Ostrich gibi), IBird arayüzünü(interface) uygular, ve eğer uçabilen bir kuş varsa (KingFisher gibi), IflyingBird arayüzünü uygular.
Farhana: Yani, eğer birçok giriş ve düğmesi olan televizyonlu örneğe dönecek olursak, televizyon üreticisinin o televizyonun giriş ve düğmelerinin planlarının yeraldığı mavi kopyaya sahip olmalılar. Televizyonun yeni modelini üretmek istedikleri herhangi bir zamanda, eğer o mavi kopyayı tekrar kullanmalarına gerek olursa, en az planda yer aldığı kadar giriş ve düğme oluşturmaları gerekir. O, onların o planı tekrar kullanmalarına izin vermeyecektir, doğrumu?
Shubho: Doğru.
Farhana: Televizyonun mavi kopyasını öyle küçük parçalara bölmeliler ki, ne zaman yeni bir tür televizyon üretmek isteseler, o planı tekrar kullanabilsinler.
Shubho: Fikri anladın.
THE DEPENDENCY INVERSION PRINCIPLE(Bağımlılığı ters çevirme ilkesi)
Shubho: Bu SOLID ilkeleri arasındaki son ilkemiz. Resmimiz burda

Bağımlılığı ters çevirme ilkesi
Diyor ki..
"Yüksek seviye modüller düşük seviye üzerine bağlı olmamalıdır, daha iyisi, ikiside soyutlamalar üzerine bağlı olmalılar"
Shubho: Bunu anlamak için gerçek hayattan bir örnek düşünelim. Araban, motor, tekerlekler, klima ve diğerleri gibi birçok nesneden oluşur, doğrumu?
Farhana: Evet, tabi.
Shubho: Peki, bu nesnelerin hiçbiri sabit olarak tek bir ünite içinde inşa edimez; daha iyisi, bunların herbiri "pluggable" özelliktedir bu nedenle motor yada tekerlekte bir sorun olduğu zaman, onu onarabilirsin(diğerlerini onarmadan) ve değiştirebilirsin bile.
Değiştirme sırasında, sen sadece tekerleğin yada motorun arabanın tasarımına uygun olup olmadığına emin olmalısın (araba ancak 1500 CC motoru kabul edebilir ve 18 inç tekerlek ona uygun olabilir)
Tabi birde, araba 1500 CC yerine 2000 CC lik motoru koymana izin verebilir, üretici buna izin verebilir (Toyota gibi)
Şimdi, arabanın farklı parçaları bu kadar "pluggable yapı"da yapılmamış olsaydı ne olurdu?
Farhana: Bu korkunç olurdu! Çünkü, bu durumda, eğer arabanın motoru çalışmazsa, tüm arabayı tamir etmek yada yenisini almak zorunda kalınabilirdi.
Shubho: Evet, Şimdi, "Pluggable yapı" nasıl başarılabilir?
Farhana: "soyutlama"(Abstraction) anahtardır. doğrumu?
Shubho: Evet, gerçek dünyada, Araba daha yüksek seviye modül/varlıktır, ve o motorlar yada tekerlekler gibi daha aşağı modül/varlığa bağlıdır.
Motorlara veya tekerleklere güvenmekten ziyade, araba motor yada tekerleğin bazı tanımlamalarının soyutlanmasına bağlıdır ki, herhangi bir motor yada tekerlek soyutlamaya uyarsa, onlar arabaya uygun olacaklardır ve araba çalışacaktır.
Hadi aşağıdaki sınıf diyagramına gözatalım:

Bağımlılığı ters çevirme ilkesi sınıf hiyerarşisi
Shubho: Yukarıdaki araba sınıfında, iki özellik olduğuna dikkat et, ve bunların ikiside somut tipten ziyade soyut(abstract) tipte (Interface) dir.
Motor yada tekerlekler pluggabledir çünkü araba atanan arayüz(interface)ü uygulayacak herhangi bir nesneyi kabul edecektir, ve o araba sınıfında herhangi bir değişikliğe gerektirmeyecektir.
Farhana: Yani, eğer Bağımlılığı ters çevirme ilkesini kodumuzda uygulamaz isek, biz şu riskleri alırız:
1- Daha aşağı seviye sınıfları kullanan daha yüksek seviye kod zarar görecektir.
2- Daha aşağı seviye kodlarda meydana gelecek bir değişiklikte, daha yüksek seviye kodları değiştirmek için çok fazla zaman ve emek gerektirecektir.
3- Daha az tekrar kullanılabilir kod oluşturulmuş olacaktır.
Shubho: Harikasın hayatım!!
ÖZET
Shubho: SOLID ilkelerinden başka Nesne yönelimli tasarımın başka ilkeleride vardır.
1- "Composition over Inheritance"(Kalıtım üzerinde düzenleme): Kalıtımın üzerinde düzenleme üstünlüğünü anlatır.
2- "Principle of least knowledge"(Enaz bilgi ilkesi): "Daha az sınıfının bilmesi daha iyidir" der
3- "The Common Closure principle"(Genel kapama ilkesi): "İlişkili sınıflar bir arada paketlenmelidir" der
4- "The Stable Abstractions principle"(Dengeli soyutlama ilkesi): "Daha dengeli bir sınıf, daha soyut sınıflardan meydana gelmelidir" der
Farhana: Bu ilkeleride öğrenmelimiydim?
Shubho: Evet, tabiki, öğrenmen için internetin var. Sadece google bu ilkeleri anlamayı denemen için yeterlidir. Ve tabiki, yardıma ihtiyacın olduğunda bana sormaktan tereddüt etme.
Farhana: Bu tasarım ilkeleri üzerinden inşa edilen birçok tasarım örneği olduğunu duydum.
Shubho: Haklısın, Tasarım örnekleri aslında hiçbirşeydir, ama tekrar eden durumlarda akla getirilen tasarım önerileri sunar.
Farhana: Yani, Desing Patterns(Tasarım örneklerini) daha sonra öğrenecekmiyim?
Shubho: Evet hayatım.
Farhana: O, çıkıyor olacaktı, doğrumu?
Shubho: Evet, kesinlikle çıkıyor olacaktır.
Belgenin çevirisi yapılmamış özgün kaynağı