Category Archives: Yazılım Mühendisliği

Interface mi, Abstract mı?

Genellikle Nesneye Yönelik Programlamaya yeni başlayanların kafasındaki büyük soru işaretlerinden bazıları "Interface ile Abstract arasındaki farklar nelerdir?, Ne zaman Interface ne zaman Abstract sınıfları kullanmalıyız ? …." gibi sorulardır.

Acı ve komik bir anımdan bahsetmeden olmaz. Okulda Java hocama neden Interface kullanırız diye sorduğumda bana "Genelde pek kullanılmaz. Fakat benim daha önce çalıştığım bilmem ne işyerinde bi abi interface kullanarak yazılım geliştirirdi. Biz 2 haftada yapıyorsak o bir haftada bitirirdi" demişti. Tabi daha sonra interface,abstract gibi kavramların nesneye yönelik programlamada ne kadar önemli kavramalar olduğunu öğrenince neden o abinin 1 haftada bitirdiğini anladım. :)

Interface ve Abstract kavramları nesneye yönelik programlamanın en temel ve önemli kavramlarından biridir.Önceki yazılarımızda Interface nedir ne zaman kullanılır?, ve Abstract nedir ne zaman kullanılır? ile bu kavramların nerede nasıl kullanıldığına ayrı ayrı konular altında değinmiştik. Eğer okumadıysanız öncelikle eski yazıları okumanızı tavsiye ederim. Aslında iki yazıyıda dikkatlice okuduğunuzda hangi durumda hangisi kullanılabilir diye karar verebilirsiniz.  Bu yazıda da genel bir özet yapıp bu kavramlar hakkında son düşüncelerimi ve kişisel tercihimi yazmak istedim.

Öncelikle daha önceki yazılarda Abstract sınıfların genellikle IS-A(dır,dir) ilişkilerinde,kalıtım(inheritance) özelliğini kullanarak kod tekrarını azaltmak için kullanıldığını söylemiştik. Interface sınıfların ise daha çok CAN-DO(yapabilir..) tarzı ilişkilerde değişen kavramları uygulamadan soyutlamak için kullanıldığını söylemiştik. Birde bu iki kavramın avantaj ve dezavantajlarına bakalım.Sonuçta Abstract bir sınıfın bütün metodlarını abstract yaparak onu da aynı bir interface gibide kullanabiliriz.

Öncelikle bence en büyük fark Abstract sınıfların tekli kalıtım(inheritance ) kullanması Interface sınıfların ise çoklu kalıtıma(multiple inheritance) izin vermesidir.Bildiğiniz gibi bir sınıfı başka bir sınıftan,ya da abstract bir sınıftan türettiğiniz zaman başka bir sınıftan daha türetme imkanınız olmuyor. Fakat interface sınıflarda durum daha farklı. Bir sınıfı istediğiniz kadar interfaceden türetebilirsiniz. Bu bakımdan interface sınıflar abstract sınıflardan oldukça daha esnek diyebiliriz. Fakat interface sınıflara baktığımızda abstract sınıflardan daha yavaş çalıştığı için hız bakımından devavantajı var diyebiliriz.

Şimdi hız mı esneklik mi diye bana soracak olursanız tabiki tercihim esneklikten yana olacaktır. Bu soruyu 2-3 sene önce sorsaydınız önce hız derdim büyük ihtimalle :)

Kendi kişisel tercihim olarak eğer soyutlamak istediğim yapıda ilişki CAN-DO ise ve hiç ortak kod yoksa sadece interface kullanırım. Fakat ortak kod içeriyorsa öncelikle bir interface(dikkat edin yine interface koyarım) koyup ardından ortak kodu kullanan bir abstract sınıf koyup onu o interfaceden türetir ve diğer sınıfları interface sınıfını kullanır hale getiririm.Burada interface i koymasakta olur fakat koymamın sebebi esnekliği arttırması ve özellikle Test Driven Development açısından Mock objelerin oluşturulması için interface kullanan sınıfların test edilmesinin çok daha kolay olması.Mock objelere ayrı bir konu başlığı altında değiniriz fazla uzatmayalım.

Eğer soyutlamak istediğim yapı IS-A ilişkisi ise sadece Abstract sınıf kullanırım. Abstract sınıfların sevmediğim yanı kalıtım(inheritance) diyebilirim.Kalıtım ilişkisi herzaman bağımlılığı(coupling) fazla olan bir ilişkidir. Yani türettiğiniz sınıfa tamamen bağımlı oluyorsunuz. Türettiğiniz sınıftaki herhangi bir değişiklik alt sınıfları etkiliyor. Fakat interface sınıflarda bu tarz bir problem daha az interface içindeki bir metodu değiştirmedikçe hiç bir sınıf bundan etkilenmiyor.Geliştirdiğiniz sınıflar tamamen plug-in mantığı ile interface sınıflar sayesinde hiç problemsiz değiştirilebiliyor. Bu yüzden kalıtıma her zaman şüpheyle yaklaşıyorum. Zaten Object OOP nin insanlar tarafından uzun yıllar kullanıldıktan sonra da aynı fikre varılmış. Kalıtımın bu problemli yapısı görüldüğü için daha sonra kalıtım yerine birleşim(Composition over Inheritance) kullanmak çoğu durumda tercih edilen bir yöntem.OOP için oldukça önemli olan bu konuyuda başka bir yazı konusu olarak ileriye bırakıyorum.

Konu ile ilgili yazıyı yazdığım gün konu ile alakalı çok güzel bir webcast e denk geldim. sizde izleyebilirsiniz. Konu Interface vs Abstract sınıflar. Burada konuşmacı benden daha katı olarak tamamen interface kullanılması gerektiğini savunuyor.Kısmen katılsamda bu şekile katı bir interface kullanımı her zaman doğru olmayabilir. Ayrıca konu ile ilgili daha derin bilgi edinmek için okumaya fırsat bulamadığım Interface Oriented Design kitabını okuyabilirsiniz. Ayrıca Wikide de  kısa bir bilgi verilmiş(Interface Based Programming).

Bu konuda şuanda aklıma gelenler bu kadar.Dediğim gibi konu bir blog yazısına sığmayacak kadar detaylı. En azından biraz ışık tutabilmiştirim. Ne kadar örneği bol tutmaya çalışsamda kendiniz yazmadıkça projelerinizde kullanmadıkta biraz havada kalabilir. O yüzden eller klavyeye diyorum…

Interface nedir,ne zaman kullanılır?

 

Interface içinde sadece kendisinden türeyen sınıfların içini doldurmak zorunda olduğu içi boş metod tanımlarının yapıldığı bir yapıdır. Kısacası kendisini kullanacak sınıflar için bir yerine getirmeleri gereken metodları belirten bir kontrat gibidir. Java ve C# dillerinde aşağıdaki gibi kullanılır.


interface Rapor{
    public void hazirla(Fatura fatura);
}

Bu interface kendinden türeyen tüm sınıfların public void hazirla(Fatura fatura) adında bir metoda sahip olmalarını zorunlu kılar aksi taktirde derleyici hata verecektir. Aşağıdaki gibi bir sınıfın bu interface’i nasıl uyguladığını gösteren koda bakalım.


class PdfRapor implements Rapor{
    public void hazirla(Fatura fatura) {
        //Faturayı pdf formatında hazırlayan kodlar
    }
}

Gördüğünüz gibi interface’den türeyen sınıflar bu şekilde interface’in belirttiği kurallara uyup içindeki metodları kendileri yazmak zorundadır.Kısacası interface’ler sınıfların yapabildiği şeyleri belirten kontratlardır diyebiliriz. Aklımıza gelmişken interface’lerin diğer özelliklerini de yazalım.

  • Interface’ler de Abstract sınıflar gibi new ile oluşturulamazlar
  • İçi dolu metod bulunduramazlar
  • public static final değişkenler dışında herhangi bir değişken bulunduramazlar
  • Bir sınıf birden fazla interface’den türeyebilir

Şimdi asıl önemli soruya geldik. Az önceki durumda neden interface kullandık?Aslında bunun sebebi tamamen bizden geliştirmemiz istenen yazılımın özelliklerine bağlı. "Yukarıdaki gibi bir kod yazmamızın ne gereği var?, Direk PdfRapor sınıfını interface’den türetmeden yazamazmıydık?" gibi sorular aklınıza gelmiş olabilir. Evet yazabilirdik tabi, fakat yazmamamızın sebebini şöyle açıklayalım.Öncelikle daha önceden müşteri ile konuştuğumuzda bizden şöyle bir talepte bulunmuştu: "Geliştireceğiniz yazılımda ben faturalarımı Pdf,Word,Excel formatlarında hazırlayabilmek istiyorum. Ayrıca ileride belki yeni formatlarda da sizden fatura isteyebilirim" diye daha önceden bizle konuşmuştu.Durum böyle olduğu için daha önceden Dependency Inversion makalesinde yazdığım gibi kodumuzun değişikliklerden etkilenmemesi, içinde bolca if-else yapılarının olmaması ve daha esnek olması için değişen kısmı bir interface kullanarak kodumuzdan soyutladık.Kodun içinde sadece aşağıdaki gibi interface kullanıldığı için ileride eklenecek yeni rapor formatlarından da etkilenmeyecektir.


class FaturaRaporFormu {
        private List calisanlar;
        private Fatura seciliFatura;
        private Rapor rapor;

        public FaturaRaporFormu(Rapor rapor){
               this.rapor = rapor;
       }

        public void FaturayaAitRapor(){
                this.rapor.hazirla(seciliFatura);
        }
}

Ayrıca interface ya da abstract sınıfların en büyük güzelliklerinden biride Polymorphism diyebiliriz. Interface ya da Abstract sınıfları kodun herhangi bir yerinde bir metoda parametre ya da metodun dönüş değeri,bir değişken, bir dizi tanımlamasında… gibi yerlerde kullanabiliriz. Ve bu kullanılan yerlerde Abstract ya da Interface’den türeyen herhangi bir sınıfı bu metoda,değişkene parametre olarak gönderdiğimizde ya da değişkene atadığımızda kod aynen çalışmaya devam edecek Java,C# dilleri Interface ya da Abstract sınıftan türeyen bütün alt sınıflara aynı şekilde tavranacaktır.

Gördüğünüz gibi interface kullanmak kodun esnekleğini arttırıyor. Fakat geliştirdiğimiz yazılımda ileride değişmeyecek bir kavramı sırf esneklik olsun diye interface kullanarak soyutlamakda kodu daha anlaşılması zor ve karmaşık hale getirecektir.Unutmayın yazılımın ve kodun basit ve sadece müşterinin ihtiyaçlarını karşılayanı makbuldür.Basitlik yazılım geliştirirken daima aklımızın bir köşesinde bulunmalı. Bu yüzden eğer müşteri bizden tek tip rapor isteseydi bu sefer interface kullanmamıza gerek kalmazdı.

Kısaca özetlersek Interface geliştirdiğimiz yazılımda aynı kavramın birden farklı şekilde uygulandığında bu kavramı soyutlayarak kodun esnekliğini,okunulabilirliğini arttırmak ve değişimin etkisini en aza indirmek için kullanılan yapılardır.Genelde Interface’den türeyen sınıflar arasında CAN-DO(yapabilir) ilişkisi vardır.Yukarıda neden kullanmamız gerektiğini umarım anlatabilmişimdir.

Abstract nedir, ne zaman kullanılır?

Abstract sınıflar içerisinde normal yani içi dolu metodların,değişkenlerin ve interface’lerdeki gibi abstract (boş) metodların tanımlanabildiği yapılardır.Bu sınıflar new kelimesi ile oluşturulamazlar.

Hemen uygulamaya geçelim örnek olarak arabalarla alakalı geliştirdiğimiz bir uygulamamız olsun. Sistemimizde bulunan çeşitli marka arabalara ait bazı özellikleri ekranda göstersin. Arabaların ağırlık,renk,model gibi ortak özellikleri ve cant kalınlığı,devir sayısı gibi kendilerine has özellikleri mevcut. Bunu ifade eden aşağıdaki gibi kodumuzu yazalım.

class Araba{
    private int agirlik;
    private String renk;
    private String model;

    public int getAgirlik() {
        return agirlik;
    }
    public void setAgirlik(int agirlik) {
        this.agirlik = agirlik;
    }
    public String getRenk() {
        return renk;
    }
    public void setRenk(String renk) {
        this.renk = renk;
    }
    public String getModel() {
        return model;
    }
    public void setModel(String model) {
        this.model = model;
    }
}
class Mercedes extends Araba{
    private int cantKalinligi;

    public int getCantKalinligi() {
        return cantKalinligi;
    }
    public void setCantKalinligi(int cantKalinligi) {
        this.cantKalinligi = cantKalinligi;
    }
}
class Ford extends Araba{
    private int devirSayisi;

    public int getDevirSayisi() {
        return devirSayisi;
    }
    public void setDevirSayisi(int devirSayisi) {
        this.devirSayisi = devirSayisi;
    }
}
class KullaniciEkrani{
    public void goster(Araba[] arabalar){
        for (int i = 0; i < arabalar.length; i++) {
            Araba araba = arabalar[i];
            System.out.println("Agirlik : "+araba.getAgirlik());
            System.out.println("Model : "+araba.getModel());
            System.out.println("Renk : "+araba.getRenk());
        }
    }
}
class AnaProgram{
    public static void main(String[] args) {
        Araba ford =new Ford();
        ford.setAgirlik(1000);
        ford.setModel("Fiesta");
        ford.setRenk("Gri");
        Araba mercedes=new Mercedes();
        mercedes.setAgirlik(2000);
        mercedes.setModel("E200");
        mercedes.setRenk("Siyah");

        Araba arabalar[]=new Araba[]{mercedes,ford};
        KullaniciEkrani ekran =new KullaniciEkrani();
        ekran.goster(arabalar);
    }
}


Yukarıdaki kodda gördüğünüz gibi Polymorphism sayesinde KullaniciEkrani sınıfı arabaların markalarından habersiz hepsini gösterebiliyor. Araba sınıfından türeyen her sınıf KullaniciEkrani sınıfında gösterilebiliyor.Buraya kadar gayet güzel. Şimdi müşteri bizden bu ekranda araçların saatte kaç litre benzin yaktıklarını da göstermemizi istedi.Fakat burada şöyle bir problem var her marka arabanın kaç litre benzin yaktığı kendi ağırlığına göre farklı hesaplanıyor.Araba sınıfına saatte yaktığı litre diye değişken eklesek olmayacak çünkü Mercedes bunu hesaplamak için farklı katsayı ile çarpıyor Ford farklı sayı ile çarpıyor.İşte bu noktada yardımımıza Abstract kavramı yetişiyor ve kodumuzu şöyle değiştiriyoruz.

abstract class Araba{
    private int agirlik;
    private String renk;
    private String model;

    public int getAgirlik() {
        return agirlik;
    }
    public void setAgirlik(int agirlik) {
        this.agirlik = agirlik;
    }
    public String getRenk() {
        return renk;
    }
    public void setRenk(String renk) {
        this.renk = renk;
    }
    public String getModel() {
        return model;
    }
    public void setModel(String model) {
        this.model = model;
    }

    public abstract int saateYaktigiBenzinLitresi();
}
class Mercedes extends Araba{
    private int cantKalinligi;

    public int getCantKalinligi() {
        return cantKalinligi;
    }
    public void setCantKalinligi(int cantKalinligi) {
        this.cantKalinligi = cantKalinligi;
    }

    public int saateYaktigiBenzinLitresi() {
        return getAgirlik()*2;
    }
}
class Ford extends Araba{
    private int devirSayisi;

    public int getDevirSayisi() {
        return devirSayisi;
    }
    public void setDevirSayisi(int devirSayisi) {
        this.devirSayisi = devirSayisi;
    }

    public int saateYaktigiBenzinLitresi() {
        return getAgirlik()*1;
    }
}
class KullaniciEkrani{
    public void goster(Araba[] arabalar){
        for (int i = 0; i < arabalar.length; i++) {
            Araba araba = arabalar[i];
            System.out.println("Agirlik : "+araba.getAgirlik());
            System.out.println("Model : "+araba.getModel());
            System.out.println("Renk : "+araba.getRenk());
            System.out.println("Yaktigi Lt. Benzin : "+araba.saateYaktigiBenzinLitresi());
        }
    }
}
class AnaProgram{
    public static void main(String[] args) {
        Araba ford =new Ford();
        ford.setAgirlik(1000);
        ford.setModel("Fiesta");
        ford.setRenk("Gri");
        Araba mercedes=new Mercedes();
        mercedes.setAgirlik(2000);
        mercedes.setModel("E200");
        mercedes.setRenk("Siyah");

        Araba arabalar[]=new Araba[]{mercedes,ford};
        KullaniciEkrani ekran =new KullaniciEkrani();
        ekran.goster(arabalar);
    }
}

Gördüğünüz gibi yukarıdaki kodda Araba sınıfına public abstract int saateYaktigiBenzinLitresi(); adında bir soyut metod ekledik. Bir sınıfın abstract metod bulundurabilmesi için Abstract bir sınıf olması gerekir. İkinci olarak Araba sınıfını abstract olarak değiştirdik. Bunu yapmamızın sebebi Araba sınıfı tarafından bu hesaplama işleminin nasıl yapılacağının bilinmemesidir. Yani bu hesaplamayı kendi yapmayıp kendinden türeyen sınıfların yapmasını şart koşmuştur. Bu hesaplamayı gördüğünüz gibi her marka araba sınıfı kendi katsayılarına göre kendi içinde yapıyor. Yukarıda Mercedes ve Ford sınıflarında saateYaktigiBenzinLitresi() metodunun nasıl farklı şekillerde yazıldığını gördünüz.Bu sayede KullaniciEkrani sınıfında Araba sınıfındaki saateYaktigiBenzinLitresi() metodunu çağırdığında her marka araba için kendi içlerinde yazdıkları saateYaktigiBenzinLitresi() metodu çalışacaktır.

Dikkat ederseniz uygulamamızada new kelimesi ile Araba nesnelerini zaten oluşturmuyorduk. Bizim oluşturduğumuz nesneler new Merceses,Ford gibi nesnelerdi.O yüzden Araba sınıfını normal sınıf tanımlamak tasarım bakımından zaten anlamsız.Burada Araba sınıfı kodun diğer kısımlarından Mercedes ve Ford gibi belirgin sınıfları soyutlamak ve sınıflarındaki ortak özellikleri(agirlik,renk,model) kodu tekrar yazmamak için oluşturulmuş bir soyut sınıf.Kod olarak baktığımızda KullaniciEkrani sınıfı Mercedes ve Ford sınıflarından habersiz sadece Araba sınıfını biliyor.

Gördüğünüz gibi Abstract sınıflar daha çok nesneler arasındaki ortak özelliklerin veya metodların bir üst sınıfta toplanarak kod tekrarını önlemek ve kodu diğer sınıflardan soyutlayarak değişimin etkisini en alt düzeye indirmektir.

Aklınızda bulunsun herhangi bir sınıfı Abstract bir sınıftan türetmek istediğinizde genel olarak dikkat etmeniz gereken durum aralarında IS-A özelliği olmasıdır.Yani Mercedes bir Arabadır, Ford bir Arabadır diyebiliriz.

Kısaca özetleyecek olursak Abstract sınıflar aralarında IS-A(..dır,..dir) ilişkisi olan sınıflardaki ortak özelliklerin ve metodların soyut üst sınıfda toplanması ondan sonra uygulamada bu soyut sınıfın kullanılarak uygulamanın diğer sınıflarından habersiz halde çalışmasını sağlamaktır. Nesneye yönelik tasarımda uygulamayı iyi soyutlamalar üzerine kurmak oldukça önemlidir. Uygulamada soyutlama oluşturmak için kullanılan önemli kavramlardan olan Abstract sınıfları küçük bir örnekle inceledik. Yakında diğer soyutlama mekanizması olan Interface kavramına değineceğiz. Tekrar görüşmek üzere…

Unutma Ey İyi Yazılım Mühendisi Adayı!

“You don’t have to be

great to get started, but you have to get started to be great.”

Les Brown

Yazılım Mühendisliği Rehberi-(P)Object Oriented

Nasıl daha iyi yazılım mühendisi olabiliriz diye daha önceden birkaç şey karalamıştık hatırlarsanız. Bu seferde birkaç satır Object Oriented dünyasına ait birşeyler karalayalım. Object Oriented yani türkçeye çevirmeye çalışırsak Nesneye Yönelik yazılım felsefesi hakkında birkaç şeyde biz söyleyelim. Object Oriented Programming, Object Oriented Design, Object Oriented Analysis hepsine yazının bundan sonraki kısmında Object Oriented diyeceğim.

Bugünlerde Object Oriented denince nedense aklıma eski bi Ruffles reklamı vardı o geliyor. Reklamda spiker taraftarın birine mikrofonu uzatıyortı birşey soruyordu yanılmıyorsam ardından geçen konuşmadan sonra öldürücü slogan geliyordu : "Ruffles Her maça gidiyor , her maçta yeniyor" diyordu. Nereden Object Oriented ile bağdaştırdığımı sorarsanız size hak vererecek şöyle açıklamaya çalışayım. Günümüzdeki modern yazılım dünyasında, modern object oriented programlama dilleri, modern geliştirme ortamları, modern framework’lere sahibiz. Bunları kullananlardan herhangi birine sorduğunuzda size muhtemelen Object Oriented yazılım geliştirdiğini söyleyecektir. Bunların gelişiminde Object oriented felsefenin etkisi çok büyük fakat bunları kullanarak gerçekten Object Oriented yazılım geliştirmiş oluyormuyuz? Cevap acı ama gerçek malesef olmuyoruz. Hatta daha da acısı büyük bir çoğunluğumuz Object Oriented olarak yazılım geliştirdiğimizi düşünüyoruz fakat eski prosedürel mantıktaki programlanın biraz bozuk şekilde evrimleşmiş şekli olan Prosedürel Object Oriented diye yorumladığım PObject Oriented yazılım geliştiriyoruz.

Kendimden örnek vereyim ilk önce. Okul yıllarında Java’da ya da C# , C++ gibi dillerde programlama yaparken dil Object Oriented diye benim yaptığım programlarında Object Oriented olduğunu düşünürdüm. İşin kötüsü tabi bunu sonradan yanlış olduğunu anlamak oldu. Tabi ilk başta insanın aklına "E ben java’da program yazmıyormuyum? Yazıyorum.. E java’da herşey nesne değil mi? Nesne.. E o zaman ben Object Oriented yazılım geliştirmiş olmuyormuyum?" diye bir soru geliyor. Bu soruya cevabımız "Malesef hayır, geliştirmiş olmuyorsunuz.". Muhtemelen Object Oriented olduğunu düşünerek Object tabanlı modern bir dilde geliştirdiğiniz programların çoğu PObject Oriented. Etrafta birkaç (on,yüz,bin) sınıf var, bu birkaç (on,yüz,bin)’lik sınıfların içindeki çoğu kod sadece birkaç onluk sınıfta toplanmış, o da yetmezmiş gibi bu sınıfların içindeki onlarca metod yüzlerce satırdan oluşuyor. Ayrıca şöyle bi yapıya göz gezdiriyorsunuz kimin eli kimin cebinde değil bütün sınıfların referansları bütün sınıflarda bulunuyor. Proje interface fakiri vb….Zaten niye interface diye bir kavramı bu programlama dillerine koymuşlar bir türlü anlamadım neymiş efendim C++’da çoklu kalıtım varmış modern programlama dillerinde de çoklu kalıtımın sorunlu yapısı yerine interface kavramı çıkarılmışşşşşşşş.. Sınıfları şöyle bir inceliyorsunuz bazıları metodlarını kabadayı binlerce satırlık sınıflara kaptırmış. Bu sınıflarda property ya da getter/setter ‘dan başka birşey yok. Aslında bu tarz sınıfları C’ deki struct ya da Pascal’daki Record yapısını kullanarakta çok güzel yapabilirdik. Bana sorarsanız o binlerce satırlık sınıflarıda prosedürel programlama ana sınıfta birkaç yüz satırlık uzun parametreli metodlarla yapabilirdik ne gerek vardı Java’ya, C#’a. Birde object oriented havası vermek için Köpek sınıfını Hayvan sınıfından türettikmi olay bitmişti. :)

Yukarıdaki bahsettiğim şeylerin hepsini Ali desideronun dediği gibi bizzat denedim çocuklara denettim. Valla hepside okumuş çocuklar bende dahil olmak üzere ama Object Oriented’ın böyle olmadığını birtürlü okulda ya da başka bir yerde okuyamamışız :)

Günümüz modern Yazılım dünyasında, Yazılım Mühendisliğinde gerçekten Object Oriented yazılım geliştirmenin önemi çok büyük fakat bunu ancak gerçek anlamda Object Oriented felsefeyi öğrendikten sonra anlıyorsunuz.Bunu bilmeden önce Pascalda C de aynı programı geliştirmişsiniz bir fark yaratmıyor gibi geliyor insana. Hatta ilk başlarda orda geliştirmek daha kolay bile gelebilir çünkü onlar saf kan Prosedürel Oriented, (P)Object Oriented değil. Ama Object Oriented dünyasına bir daldığınızda işlerin ne kadar temiz , düzenli, kolay yönetilebilir, kolay yeni özellik eklenebilir, esnek olarak geliştirildiğini görünce eski günlere geri dönmeyi pek istemiyorsunuz. Tabi unutmamak lazım amacımız Object Oriented hatrına böyle yazılım geliştirmek değil amaç gittikçe kompleksleşen yazılım projelerini daha ucuza daha kısa sürede daha yönetilebilir, yeni özellikleri kolayca eklenebilir yapıda geliştirmek bu yüzden Object Oriented sayıklayıp duruyoruz.

Object Oriented denince aslında ilk akla gelmesi gereken şey Data Hiding, Encapsulation kavramlarıdır. Ayrıca Polymorphism ve Overloading kavramlarıda bunlardan sonra oldukça önemlidir. Aslında bunlardan kısa kısa bahsetmektense uzun uzun makale hazırlamak istiyorum. Çünkü ilk başta bu kavramları yarım yamakak öğrendiğimde tamam Object Oriented felsefeyi kaptım demiştim ve hiçte önemsememiştim ama ilerledirkçe hiçde doğru anlamadığımı ve ne kadar önemli olduğunu anladım.

Object Oriented ile prosedürel programlama arasındaki en büyük farklardan birisi de Prosedürel programlamada veriler ve fonksiyonlar birbirinden ayrıdır.Yani dışarıda global veriler bulunur ve bu verileri işleyen fonksiyonlar bulunur. Object Oriented programlamada ise tam tersi veriler ve onlar üzerinde işlem yapan fonksiyonlar bir aradadır.Ayrıca Kısa bir tanımlama yaparsak Data Hiding (Bilgi Saklama) nesnelerin iç yapılarının yani sahip oldukları verilerin dışarıdan gizlenmesidir. Encapsulation ise bu dışarıdan saklanmış verilerin nesne üzerinde tanımlanmış fonksiyonlar ile dışarıya açılmasıdır. İlerleyen zamanlada daha detaylı bu konulara değiniriz…

Yukarıda olmaması gereken birçok özellik saydım bunlar sadece bazılarıydı. Eğer kodunuzda bu tarz şeyler görüyorsanız birkaç OO kitabı almanın biraz makale okumanın vakti gelmiş demektir. En azından benim için en faydalı olanda öyle sanarak yazdığım kodların Object Oriented olmadığını kısa sürede görebilmiş olmamdı. Ondan sonrası zaten kolaylıkla geliyor doğru olanın arayışı içine giriyorsunuz çünkü.

Kısaca yazılım mühendisi olanlara, adaylarına kodlarını tekrar gözden geçirmelerini gerçek anlamda Object Oriented yazılım geliştirip geliştirmediklerini sorgulamasını tavsiye ediyorum. En kısa zamanda Object Oriented felsefeyi kavramalarını şiddetle tavsiye ediyorum. Hatta aynı projede çalışsaydık muhtemelen şimdi arkadaşlara yaptığım gibi durmadan faydalarını anlatıp ikna etmeye çalışırdım olmadı dikte ederdim :)Gerçekten Object Oriented felsefenin yazılım mühendisliği alanının en önemli konularından biri olduğunu düşünüyorum . Diğer birçok yazılım mühendisliği konusu (Design Patterns, Refactoring, TDD vb..) aslında nasıl daha iyi Object Oriented yazılım geliştireceğimiz hakkındaki tekniklerdir.

Şimdi benimde en çok zorlandığım nasıl öğreneceğiz kısmına geldik . Öncelikle eğer şanslıysanız ve çevrenizde Object Oriented felsefeyi iyi bilen birileri varsa hemen yapışın hiç bırakmayın derim.Beraber yazılım geliştirin yazdığı kodu inceleyin sınıflara atadığı metodların neden oraya konduğuna dair sorular sorun vb… Dikkat edin tecrübeli demiyorum çünkü gözlemlediğim şöyle bir sonuç var Çalışma yılı = İyi yazılım mühendisi demek değildir. Bu kişilerden ne kadar bilgi alırsanız yazılım kariyeriniz için o kadar iyi olacaktır. Kitaplardan makalelerden günlerce okuyup bulamayacağınz bir bilgiyi yanınızdaki kişiden 5-10 dakika içerisinde öğrenebilirsiniz. Benimde seçtiğim ikinci seçenek kendi kendinize öğrenmekten geçiyor yani zor olan yol. Açıkçası bu şekilde öğrenmek yıllar alabiliyor. Sürekli konu hakkında kitap makale blog forum takip etmeniz gerekiyor. Takıldığınız yerlerde forumlardan yardım almak biraz zorlaşıyor dolayısıyla öğrenme süresi oldukça uzuyor. Yıllar oldu ben açıkçası hala OOP adına bilmediğim yeni şeyler öğreniyorum. Kitap olarakda daha önceden okuduğum en iyi Object Oriented başlangıç kitabı olarak tavsiye edebileceğim

Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development

aklınıza takılan sorular varsa ben burdayım. Object Oriented dünyasına giriş biletinizi kestik hadi hayırlı yolculuklar….

Yazılım Mühendisiği Rehberi-Design Patterns

Nasıl daha iyi bir yazılım mühendisi olabiliriz? Geçen yazıdan hatırladığımız gibi araştırmalarımız devam ediyordu. Bu yazıda meşhur Design Patterns konusuna değineceğiz.

Design Patterns aslında Object Oriented Design, Object Oriented Programming konularını uygulamalı olarak anlatıyor aslında. O yüzden bu konuya açıkçası OOP, OOD nin uygumalı olarak problemler üzerinde öğrenimi olarak bakıyorum. Günümüzde modern Yazılım mühendisliğinin temelindede bu konular yatmaktadır. O yüzden bu konu yazılım mühendisliğinde oldukça önemli bir yer tutmaktadır.

Yazılım mühendisiliğine ilk olarak merak salmamı sağlayan alanlardan biriydi Design Patterns. İlk olarak öyle sitelerde yazılımla alakalı makaleler okurken bahsediliyordu sonra biraz araştırayım dedim ve genelde herkesin referans olarak tavsiye ettiği ve yazılım dünyasında çığır açan Design Patterns, Elements Of Reusable Object Oriented Software kitabını e-book olarak edindim. İlk bölümleri okumaya başlayınca önce kısa süreli beyin sarsıntısı geçirip ardından "Vay bee" anı yaşamıştım. Çünkü benim yazılım geliştirirken karşılaştığım problemleri gösteriyordu ve ardından nasıl bu problemlere uygun çözümler getirilir onları adım adım anlatıyordu.Ve çözümler klasik mantıktan, alıştığımdan çözümlerden oldukça farklıydı. Çok iyi anlamasamda ilk okuduğumda edindiğim izlenim yazılım geliştirmeyi kod yazmayı, Object Oriented felsefese adına hiçbirşey bilmediğim oldu. Gerçekten okulda öğretilen Yazılım Mühendisliği, Object Oriented Programming vb.. derslerde açıkçası hiçbişey gösterilmemiş. Daha önceden interface, abstract class kavramlarını bilsemde gerçekten ne işe yaradıklarını hangi durumlarda kullanıldıklarını o kitabı okuduktan sonra öğrendim. Bu benim için Yazılım Mühendisliği dünyasına ilk ve iyi bir giriş oldu, ama sadece giriş….Buz dağının görünen ucuydu yani.

Yazılım geliştirmeyi,kod yazmayı bilmediğimi anlamamı erken sağladığı için kendimi çok şanslı hissediyorum. Burada Design Pattern nedir ne değildir diye anlatmayacağım. Zaten internette bir dünya kaynak mevcut. Ama Yazılım mühendisliği adına öğrenilmesi gereken en önemli konulardan biri olduğunu düşünüyorum. Kaynak olarakda yukarıda yazdığım orjinal GOF’un kitabını kullanabilirsiniz . Kitap C++ ile örnekleri anlatıyor fakat OOP mantığı diğer bütün dillerde aynı olduğu için çok fazla fark etmiyor. Bu bakımdan eğer C++ bilginiz iyi değilse ya da C++ diliyle proje geliştirmiyorsanız Java ile örnekleri anlatan Head First Design Patterns kitabını öneririm. Açıkçası bu kitap sonrada okumama rağmen orjinalinden daha çok hoşuma gitmişti.

Ayrıca benimde ilk olarak yapmaya çalıştığım bütün Pattern’ları tek tek öğrenmeye çalışmaktı. Pattern ezberlemek gibi bişey oldu yani. Tabi çok fazla faydası olmadı sadece hangi Pattern ne işe yarar nerede kullanılır gibi şeyleri birde havalı Pattern isimleri öğrenmiş oldum:) . Bir anda Pattern manyağı oldum çıktım :) . Etrafta deli gibi hangi Pattern’ı kodlarımın neresinde kullanabilirim onu arıyorum. Tabi bunun da çok fazla faydası olmadı. Gerçek anlamda kafamda Design Patterns kavramını oluşturmam yeni bir projeye başlamamla oldu. Kodda meydana gelen tasarım problemlerini daha önceden adlarını ve ne iş yaptıklarını bildiğim Pattern’ları kullanınca taşlar yerli yerine oturmaya başladı. Örnek olmadan bir tasarım,design problemi ile karşılaşmadan tasarım kalıbı kullanmanın verimli olmadığını o zaman anladım.

Bu konuda tavsiyem tek tek Design Pattern’ları okuyup ezberlemek yerine geliştirdiğiniz bir projede karşılaştığınız bir probleme ait bir tasarım kalıbı varmı yokmu onu araştırıp ardından bulduğunuz tasarım kalıbını orada kullanmanızdır. bu şekilde çok daha oturaklı şekilde öğrenmiş olursunuz. Benim gibi aynı kitabı birkaç defa okumak zorunda kalmazsınız.

Yazılım Mühendisiği Rehberi – Kitaplar

kitaplar.jpgDaha iyi bir yazılım mühendisi olmak için neler yapmalıyız? Malesef ülkemizde yazılım mühendisliği kavramı pek oturmuş olmadığı için bu konuda kaynak bulmak gerçekten zor. Ülkemizdeki yazılım mühendisiliğini daha sonra enine boyuna tartışırız aslında yazmak istediğim çok şey var . Daha önceden iyi bir yazılım mühendisi olmak için neler yapmalıyım hangi kitapları okumalıyım baya bir araştırmıştım. Türkçe pek (aslında hiç) kaynak bulamamıştım. Bölüm bölüm burada nelerden faydalandım yazmaya çalışacağım. Aklıma gelmişken ilk olarak okunmasında fayda gördüğüm kitapları yazayım dedim

Object Oriented Design,Programming

  • Applying UML and Patterns – An Introduction to Object-Oriented Analysis and Design and Iterative Development
  • Agile Principles, Patterns, and Practices in C#

Desing Patterns

  • Head First Design Patterns
  • Design Patterns Elements of Reusable Object-Oriented Software

Test Driven Development

  • Test-Driven Development: A Practical Guide
  • Test-Driven Development By Example
  • Pragmatic Unit Testing

Refactoring

  • Refactoring: Improving the Design of Existing Code
  • Working Effectively with Legacy Code
  • Refactoring to Patterns

Agile,XP

  • Practices of an Agile.Developer Working in the Real World
  • Extreme Programming Explained
  • Extreme Programming Explained Embrace Change

Öncelikle belirteyim biraz fazla oldu ama gerçekten hepside çok faydalı kitaplar. Gerçekten okumanızı tavsiye ederim. Şimdi bana bu kadar kitabı sen nasıl okudun diyebilirsiniz. Valla üşenmedim okudum.Bazılarını sırf tren, vapur ile işe giderken vakit boş geçmesin diye PSP aldım, pdf olarak içine atıp öyle okudum. Unutmayın iyi bir yazılım mühendisi olmak için gerçekten çok ama çok okumanız ve pratik yapmanız gerekli. Kitap, blog, forum vs.. çok fazla araştırmak incelemek gerekiyor.Fazla uzatmadan kolay gelsin diyelim. Umarım iyi bir başlangıç olur..