Monthly Archives: July 2008

Single Responsibility Principle(SRP)

Evet lütfen kemerlerinizi bağlayın koltuklarınıza sıkı sıkı yapışın nesneye yönelik programlamanın özüne doğru yolculuğa çıktık.Ufak çaplı sarsıntı yaşayabilirsiniz.Verdiğimiz rahatsızlıktan dolayı özür dileriz. :)

Şimdi bu kadar abarttığıma bakmayın ama konunun önemini belirmek için böyle bir giriş yaptım.Nesneye yönelik programlamanın,tasarımın en temel  ve yazılım tasarımının en önemli prensiplerinden olan Single-Responsibility Principle (SRP) hakkında bilgi verip ufak bir örnekle incelemeye çalışacağız.

Nesneye yönelik programlamanın hatta genel programlama mantığının temelinde yatan metodları nesneleri düşünelim.Neden kullandığımız dillerde bu tarz yapılar mevcut?Yönetimi kolaylaştırmak için.Amaç farklı işleri yapan kavramları birbirinden metodlar, sınıflar kullanarak yönetilmesini kolaylaştırmak için birbirinden ayırmak.Nesneye yönelik programlamada bunu nesneler kullanarak, prosedürel programlamada ise fonksiyonlar fonksiyon modülleri kullanarak yapıyoruz.Ama temel mantık aynı farklı işleri farklı farklı sınıflar, metodlar, katmanlar, kütüphaneler içine koyarak ayırıyoruz.

Tabi bazen farklı farklı işleri gidip aynı sınıf,metod ya da modül içine koyabiliyoruz(biri bizi durdursun).Hatta çoğu zaman bunu bu şekilde yapıyoruz diyebilirim.Etrafta yüzlerce binlerce satırlık sınıflar, metodlar görmemizin sebebi de bu. Tabi böyle yapınca sınıfın kodunu aşağıya doğru çekince en son satıra ulaşmak 10 saniye alıyor neredeyse. Mesela gördüğüm bir sınıf yaklaşık 5000 satırdı aşağıya çekmem bile baya süre alıyordu malesef.

Bertrand Meyer Object-Oriented Software Construction kitabında sınıfların,fonksiyonların,modüllerin nasıl olması gerektiğini aşağıdaki cümleyle çok güzel özetlemiş.

A class has a single responsibility: it does it all, does it well, and does it only.
Classes, interfaces, functions, etc. all become large and bloated when they’re trying to do too many things.

Aslında Single-Responsibility Principle (SRP) tamamen yukarıdaki sözle özetlenebilir. Bir sınıf,fonksiyon vs.. sadece tek bir sorumluluğu yerine getirmelidir  ve yerine getirdiği sorumluluğu iyi yapmalıdır.Birden fazla sorumluluk yerine getirmeye çalıştığı zaman aşırı büyür ve karmaşıklaşır.

Bu prensip aslında yazılım dünyasında uzun zamandır bilinen temel kavramlardan biridir. Kısaca bu prensibi şöyle açıklayabiliriz, kodumuzda, tasarladığımız modüllerde kullandığımız sınıflar,uygulamadaki katmanlarımız,modüllerimiz sadece tek bir sorumluluğunu yerine getirmelidir. Yani sınıfın,modülün sadece kendi ile alakalı işleri yapmasıdır diyebiliriz. Çünkü birden fazla sorumluluğu yerine getiren sınıfların,modüllerin değişmesi için birden fazla neden vardır. Kendi ile alakalı şeyleri yapmayan sınıfların modüllerin aşağıdaki gibi dezavantajları vardır.

    Anlaması zordur Tekrar kullanılabilmesi zordur. Yönetilmesi zordur. Hassas ve sürekli olarak diğer değişikliklerden etkilenen yapıdadır.

Modüller açısından bu prensibi inceleyelim.Katmanlı mimari modüler tasarım modül vb.. kavramlar da aslında bu tasarım prensibinin uygulanmasının bir sonucudur.Örnek olarak 3 katmanlı bir yapıda tasarlanmış bir uygulamada klasik olarak Sunum(Presentation Layer), İş(Business Layer) ve Veri(Data Layer) katmanları bulunsun. Adlarından da anlayabileceğimiz gibi her katman kendine ait sorumlulukları yerine getirir. Biri(Data Layer) veritabanı ile ilgilenirken diğeri(Business Layer) iş kurallarıyla alakalı sorumlulukları yerine getirir. Bir diğeride(Presentation Layer) bilgilerin kullanıcılara sunulması sorumluluğunu yerine getirir. Bu şekilde tasarımın en önemli faydalarından biride bir katmandaki değişikliğin diğer katmanları etkilememesi ve iyi tasarlanmış katmanların tekrar başka uygulamalarda kullanılabilmesidir. Çünkü her katman sadece kendi ile alakalı tek bir sorumluluğu yerine getirir. Böylece değişmesi için tek bir sebep vardır.Bu da o katmandaki ihtiyaçların değişmesi. Örnek olarak sunum katmanındaki bir değişim veri katmanını etkilemez çünkü ikisi de birbirinden bağımsız ayrı sorumlulukları yerine getirirler.Tabi bu sözde anlatması kolay fakat gerçekleştirmesi bir o kadar zor bir kavramdır.

Sınıflar için baktığımızda bu prensip anlatması ve anlaşılması en kolay fakat uygulamaya gelince en çok zorlandığımız prensiplerden biridir.Mesela benim 5000 satırlık işçi için sınıfım işciler ile alakalı iş mantığını yönetmekle sorumlu diyebilirim.Ama bu yönetme içinde veritabanı ile iletişim,import,export özellikleri,iş mantığını,cache yönetimi…. gibi bir sürü ayrı sorumluluğu yerine getiriyor yani birden fazla işi yapıyor ama ben olaya öyle bakmıyorum.Bu yüzden sorumluluk kavramını tam anlamıyla doğru şekilde uygulamak zaman ve deneyim isteyen bir süreçtir. Bunun bazı sebeplerinden biride sorumluluk kavramının karıştırılabilmesi, biraz bulanık bir kavram olmasından da kaynaklanmaktadır.

Mesela bir sınıf için baktığımızda sorumluluk nedir ? Genelde sorumluluk denince sınıfın bir methodu akla gelir fakat gerçekte birden fazla method bir sorumluluğu yerine getiriyor olabilir. Bence sorumluluğun en güzel özeti bir sınıfın değişmesi için bir sebep olarak tanımlayabiliriz. Yani bir sınıfın,metodun.. değişmesi için birden fazla neden varsa o sınıfın birden fazla sorumluluğu yerine getirdiğini söyleyebiliriz.Mesela yukarıda bahsettiğim işçi sınıfı için söyleyecek olursak bu sınıf veritabanına erişim mantığı değiştiğinde değişebilir, ayrıca değişik bir import seçeneği sunmak istediğimizde yine sınıfı değiştirmek gerekir,yeni bir cache algoritması eklemek istediğimizde doğal olarak tekrar bu sınıfı değiştirmek zorunda kalacağız. Bu da bize sınıfın değişmesi için birçok sebep verdi demekki bu sınıfın çok fazla sorumluluğu var onun sırtındaki yükü biraz azaltmamız lazım.

Örneklerin genelde gerçek hayattan olmasına özen göstermeye çalışıyorum. O yüzden daha önceden üzerinde çalıştığım kodun küçük bir kısmını değiştirerek incelemek için aşağıya yazıyorum.

class Contact
{
    private int _contactID;

    public int ContactID
    {
        get { return _contactID; }
        set { _contactID = value; }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    private string _number;

    public string Number
    {
        get { return _number; }
        set { _number = value; }
    }

    private ContactType _type;

    public string Type
    {
        get { return _type; }
        set { _type = value; }
    }

    public int ImportExcel(File file)
    {
        CantactDao contactDao = null;
        List<Contact> contactList = null;
        int contactCount = 0;
        try
        {
            contactDao = new ContactDao();
            tr = contactDao.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);
            contactList = contactDao.GetContactsFromExcel(file);
            if (contactList != null &amp;&amp; contactList.Count > 0)
            {
                for (int i = 0; i < contactList.Count; i++)
                {
                    contactList[i].Type = ContactType.Friend;
                    contactList[i].Save();
                }
                contactDao.CommitTransaction(tr);
                contactCount = contactList.Count;
            }
        }
        catch (Exception ex)
        {
            contactDao.RollbackTransaction(tr);
        }
        return contactCount;
    }

    public int Save()
    {
        ContactDao contactDao = null;
        try
        {
            contactDao = daoFactory.GetContactDao();
            tr = contactDao.BeginTransaction();
            contactDao.Insert(this);
            contactDao.CommitTransaction(tr);
        }
        catch (Exception ex)
        {
            contactDao.RollbackTransaction(tr);
        }
        return this.ContactID;
    }
}
class ContactDao
{
    public void Insert(Contact contact)
    {
//veritabanı erişim kodları ile veritabanına Contact sınıfının eklenmesi 
    }

    public void Update(Contact contact)
    {
        //veritabanı erişim kodları ile Contact sınıfının güncellenmesi 
    }

    public void Delete(Contact contact)
    {
        //veritabanı erişim kodları ile sınıfın veritabanından silinmesi 
    }

    public Contact GetByID(int contactID)
    {
        //veritabanı erişim kodları ile sınıfın veritabanından alınması 
    }

    public List<Contact> GetContactsFromExcel(File file)
    {
        Contact contact = null;
        List<Contact> contactList = null;
        System.Data.OleDb.OleDbConnection connection = null;
        System.Data.OleDb.OleDbCommand selectCommand = null;
        try
        {
            string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + File.FilePath +
                                      ";Extended Properties=Excel 8.0";
            string selectQuery = "SELECT * FROM [Contacts$]";
            connection = new System.Data.OleDb.OleDbConnection();
            connection.ConnectionString = connectionString;
            connection.Open();
            selectCommand = new System.Data.OleDb.OleDbCommand(selectQuery, connection);
            System.Data.OleDb.OleDbDataReader dataReader = selectCommand.ExecuteReader();
            if (dataReader != null &amp;&amp; dataReader.HasRows)
            {
                contactList = new List<Contact>();
                while (dataReader.Read())
                {
                    contact = new Contact();
                    contact.Name = dataReader["Name"];
                    contact.Number = dataReader["Number"];
                    //....diğer alanların alınması ve kontrolü 
                    contactList.Add(contact);
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return contactList;
    }
}

Şimdi yukarıdaki kodun yapısını biraz inceleyelim. Bir SMS programımız var SMS programının özelliklerinden biri dışarıdan excel içindeki kişi listesini programımıza import edebiliyoruz.Genelde çoğu programda bu tarz özellikleri sizde kullanmıştırsınız.Kodda gördüğünüz gibi bir adet Contact sınıfımız var bu sınıf programımızda kullandığımız kişileri temsil ediyor.Bu sınıfın metodlarına bakarsak gördüğünüz gibi bir adet excel dosyasından import eden ImportExcel metodumuz var. Ayrıca veritabanına bilgileri kayıt eden bir adet Save metodumuz var.Yani ActiveRecord tasarım kalıbını uygulayarak kendini veritabanına kayıt ediyor. ContactDao adında DAO(Data Access Object) tasarım kalıbını uygulayan bir adet sınıfımız var.Bu sınıfımızda Contact sınıfımızı veritabanına ekleme,güncelleme, silme ve Excel dosyasından veri alma işlemini yapıyor. Şimdide UML olarak static sınıf diyagramına bakalım.


Yukarıdaki Uml diyagramını çizmemin tek amacı görsel olarak sınıflar arasındaki ilişkileri görmek kodu okumaktan daha kolay olmasıdır. Şimdi yukarıdaki diyagram yardımıyla sınıfları daha yakından incelemeye başlayalım.Öncelikle sınıfların birbirine olan bağımlılığına(Dependency) bakalım. Etrafta uçuşan okları görüyorsunuz görüntü pek iç açıcı değil açıkçası. Contact sınıfımız üzerindeki ImportExcel metodu sayesinde File sınıfına bağımlı. Ayrıca Save metodunu kullandığında da Transaction oluşturduğu ve CantactDao sınıfının metodunu çağırdığı için bu sınıfa ve ADO.NET sınıflarına da bağımlı.

Öncelikle kötülüklerin anası olan bağımlılık neden bu kadar kötü kısaca bahsedelim. :) Bağımlılığı fazla olan sınıfları yeniden kullanmanız (Reuse) çok zordur. Çünkü kullanmak istediğiniz sınıf diğer  birçok sınıfa bağımlıdır onunla birlikte diğer sınıflarıda projede dahil etmeniz gerekir. Tabi bu da o kadar kolay değildir.Çünkü diğer sınıflarında birçok diğer sınıfa bağımlı olduğu düşünürsek küçük bir sınıfı yeniden kullanmak istediğinizde bütün projeyi diğer projeye dahil etmeniz gerekir. Diğer bir kötü yanı bağımlı olduğu sınıflarda meydana gelen hataların o sınıfı kolaylıkla etkilemesidir. Bu konuda daha geniş bilgi için Dependency Inversion prensibine bakabilirsiniz.Ayrıca gördüğünüz gibi Contact sınıfı,ContactDao sınıfı kendi ile alakalı olmayan metodlar ile gittikçe büyüyor. Sınıfların büyüdükçe yönetilmesinin çok zor olduğunu biliyorsunuz. Benim gibi 5000 satırlık kodun içinde değişiklik yapmanın hatanın ne olduğunu bulmanın nasıl bir kabul olduğunu bilirsiniz.

Şimdi bu kadar şeyden bahsettik bunların Single Responsibility Principle ile alakasının ne olduğunu merak etmiş olabilirsiniz haklı olarak. Kısaca burada ki bağımlılığın sınıfların gittikçe büyümesinin sebebi sınıfların birden çok sorumluluğunun olmasıdır. Contact sınıfımız hem sistemimizde bir kavramı temsil ederken hemde onu sisteme import etme işlemini yapıyor. Ayrıca ContactDao sınıfımız hem veritabanı ile alakalı Insert,Update… gibi işlemleri yaparken ayrıca Excel dosyasından kayıtları okuma işlemini yapıyor. Bu sınıfın değişmesi için birçok neden sıralayabiliriz.Import mantığımız değişir, Contact sınıfını değiştiririz. İş mantığımız değişir, Contact sınıfını değiştiririz. Excel dosyasından okuma mantığımız değişir, ContactDao sınıfımız değişir.Kullanılan teknolojiyi ADO.NET yerine başka birşey kullanmak isteriz iki sınıfımızda değişmek zorunda kalır.Yani değişime karşı sınıflarımız oldukça kırılgan yapıdalar.

Şimdi fazla sorumluluğu olan sınıfların yüklerini biraz hafifletelim. Bunu yapmak için bütün yapılan sorumlulukları liste halinde yazalım.Bu listeyi sorumlulukları atamada kullanacağız.

    Kişilerin sistemnde temsil edilmesi (Contact sınıfı) Kişilerin veritabanı ile alakalı işlerin yapılması (ContactDao sınıfı) Kişilerin import edilerek sisteme kayıt edilmesi (Contact sınıfı) Excel dosyasından satırların okunarak kişi nesnesine çevrilmesi (ContactDao sınıfı)

Gördüğünüz gibi 4 tane sorumluluk 2 tane sınıf arasında paylaştırılmış. Biz kodumuzu değiştirerek her sorumluluğu tek bir sınıfa atayacağız yani Single Responsibility prensibini uygulayacağız. Bunun için öncelikle bu sorumluluklara iyi birer isim bulmaya çalışalım. Dikkat edin bunu sezgi yoluyla yapıyorum.

    Öncelikle kişilerin sistemde temsil edilmesi Contact sınıf bu aynen kalacak. Kişilerin veritabanı ile alakalı işlerinin yapılması zaten bu işi yapan sınıfımız var ContactDao adı üzerinde Data Access Object Kişilerin import edilmesi buna ContactImporter diyelim Kişilerin Excel dosyasından okunması buna da ContactExcelReader olsun.

Sınıflarımızın adlarını belirledikten sonra fazla sorumluluğu olan sınıflardan kodların yeni sınıflara taşınması işlemi var. Bu işlemi yaparken tabiki kes-yapıştır yapmanızı tavsiye etmiyorum. Birçok istenmeyen hata ile karşılaşabilirsiniz. Bunu Refactoring, ve Unit Testing desteğiyle en güvenli şekilde yapabilirsiniz. Konumuzu fazla dağıtmamak için değinmiyorum amacımız Single Responsibility Prensibini açıklamak.O yüzden benim şuanda kes-yapıştır yapmama fazla aldırmayın.Lafı fazla uzatmadan yeni kodlarımızı aşağıya yazalım.

internal class Contact
{
    private int _contactID;

    public int ContactID
    {
        get { return _contactID; }
        set { _contactID = value; }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    private string _number;

    public string Number
    {
        get { return _number; }
        set { _number = value; }
    }

    private ContactType _type;

    public string Type
    {
        get { return _type; }
        set { _type = value; }
    }
}
class ContactImporter
{
    private ContactDao contactDao = new ContactDao();
    private CntactExcelReader contactReader = new ContactExcelReader();

    public int ImportFromExcel(File file)
    {
        List<Contact> contactList = null;
        int contactCount = 0;
        try
        {
            tr = contactDao.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);
            contactList = contonctReader.GetContactsFromExcel(file);

            if (contactList != null &amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp; contactList.Count > 0)
            {
                for (int i = 0; i < contactList.Count; i++)
                {
                    contactList[i].Type = ContactType.Friend;
                    contactList[i].Save();
                }

                contactDao.CommitTransaction(tr);
                contactCount = contactList.Count;
            }
        }
        catch (Exception ex)
        {
            contactDao.RollbackTransaction(tr);
        }
        return contactCount;
    }
}
class ContactDao
{
    public int Save(Contact contact)
    {
        try
        {
            Transaction tr = this.BeginTransaction();
            this.Insert(contact);
            this.CommitTransaction(tr);
        }
        catch (Exception ex)
        {
            this.RollbackTransaction(tr);
        }

        return contact.ContactID;
    }

    public void Insert(Contact contact)
    {
//veritabanı erişim kodları ile veritabanına Contact sınıfının eklenmesi
    }

    public void Update(Contact contact)
    {
//veritabanı erişim kodları ile Contact sınıfının güncellenmesi
    }

    public void Delete(Contact contact)
    {
//veritabanı erişim kodları ile sınıfın veritabanından silinmesi
    }

    public Contact GetByID(int contactID)
    {
//veritabanı erişim kodları ile sınıfın veritabanından alınması
    }
}
class ContactExcelReader
{
    private GetContactsFromExcel(File file)
    {
        Contact contact = null;
        IList<Contact> contactList = null;
        System.Data.OleDb.OleDbConnection connection = null;
        System.Data.OleDb.OleDbCommand selectCommand = null;

        try
        {
            string connectionString = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source =" + File.FilePath +
                                      ";Extended Properties = Excel 8.0";

            string selectQuery = "SELECT*FROM[Contacts$]";

            connection = new System.Data.OleDb.OleDbConnection();
            connection.ConnectionString = connectionString;
            connection.Open();
            selectCommand = new System.Data.OleDb.OleDbCommand(selectQuery, connection);
            System.Data.OleDb.OleDbDataReader dataReader = selectCommand.ExecuteReader();
            if (dataReader != null &amp;amp;&amp;amp; dataReader.HasRows)
            {
                contactList = new List<Contact>();

                while (dataReader.Read())
                {
                    contact = new Contact();
                    contact.Name = dataReader["Name"];
                    contact.Number = dataReader["Number"];
                    //....diğer alanların alınması ve kontrolü
                    contactList.Add(contact);
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }

        return contactList;
    }
}

Yeni sınıflarımıza bir de UML diyagramı ile bakalım.

Şimdi yukarıda ki diyagram yadımıyla kodumuzun son haline bakalım. Gördüğünüz gibi artık Contact sınıfımız ne File,ContactDao gibi sınıflara ne de herhangi bir ADO.NET teknolojisine bağımlı.Fazla sorumluluğu üzerinden alınca diğer sınıflardan bağımsız hale geldi. Diğer sınıflara baktığımızda sadece kendi işlerini yapan ve gereksiz bağımlılıklardan kurtulmuş sınıflar var.ContactExcelReader sadece Excel dosyasından Contact okuma işini yapıyor,ContactImporter liste halinde verilen kişileri veritabanına import ediyor. ContactDao sadece veritabanı ile alakalı işlemleri yapıyor.Artık sınıfların değişmesi için tek sebep var. Kodun anlaşılması ve yönetilebilmesi daha kolay.

Single Responsibility prensibini her zaman uygulamak çok faydalı olmayabilir. Mesela çok küçük bir projede uygulamak sınıf sayısını arttırdığı için sistem daha komplex olur.Mesela yukarıda ActiveRecord tasarım kalıbını uygulayan Save metodunu gidip ContactDao sınıfı üzerine taşıdık.Fakat bu tasarım kalıbı küçük çaplı, iş mantığının yoğun olmadığı çoğu projede başarı kullanılabiliyor.Ama çoğu durumda uygulamanız için  bu prensibi uygulamak uygulamanın yönetimi bakımı hata oranı için oldukça önemli rol taşıyor.

Refactoring-Consolidate Duplicate Conditional Fragments

Evet bu aralar parserlar ile boğuşuyorum kendi çapımda ufak bir dil yapmaya çalışıyorum. Programlamlama dillerini kullanması kolay ama yapması gerçekten zormuş ilk olarak onu söyleyebilirim. Örnek bir parser bulup nasıl yapıldığı hakkında fikir edinmek için onu inceliyordum.Kodu çok karmaşık ve anlaması çok zor olduğu için önce testlerin sağlamlığından emin olana kadar Unit Test hazırladım. Ardından kodu daha okunabilir,anlaşılabilir olması,ve code smell”lerden kurtulmak için refactoring yaparım.Bunu yaparken aşağıdaki gibi bir kod ile karşılaştım.Aşağıdaki kodu öncelikle biraz inceleyin bir problem görebilecekmisiniz?

<br />
 private double atom() throws InterpreterException {<br />
 double result = 0.0;</p>
<p> if (tokenizer.getTokenType() == TokenTypes.NUMBER){<br />
 try{<br />
 result = Double.parseDouble(tokenizer.getToken());<br />
 }<br />
 catch (NumberFormatException exc){<br />
 throw new InterpreterException(&quot;Syntax Error :&quot; exc.getMessage());<br />
 }<br />
 tokenizer.obtainNextToken();<br />
 }<br />
 else if (tokenizer.getTokenType() == TokenTypes.VARIABLE){<br />
 result = getValueOfVariable(tokenizer.getToken());<br />
 tokenizer.obtainNextToken();<br />
 }<br />
 else<br />
 throw new InterpreterException(&quot;Syntax Error&quot;);</p>
<p> return result;<br />
 }<br />

Şimdi yukarıdaki koda baktığınızda ilk başta büyük bir problem gözünüze çarpmıyo olabilir benimde çarpmıyordu çünkü. Fakat biraz daha incelediğimde beni rahatsız eden bir kötü kod barındırdığını farkettim. Şimdi if-else yapılarını beraberce inceleyelim. İlk if yapısına baktığımızda Token tipinin numara olup olmadığını kontrol ediyor. Eğer numaraysa Tokeni double çevirip sonucu üretiyor ve bir sonraki tokeni alıyor. İkinci else if yapısına baktığımızda tokenin değişken olup olmadığını kontrol ediyor. Ardından değişken ise değerini alıp

World wide web but still.

This notion is made easy with a solid monarchy. � 98 03 slot games play all data is only, the following payout percentage at a better. Already established itself as well as we adhere to offer. Over the flashno download the casinos of las vegas types of the interface type. 42 billion took 34 13 billion took at platinum play online casinos are. Or the players just need to play them the. Online many players stimulated and download�based online casinos where tourists from every corner of slot? Of the largest casino operators. Loved about casinos platinum play online angelscamp.org casinos got many. Of gamblers is received in addition there. To strength in the night city trying their lucks america there. Highest level and scratch turtley. Number generators of internet gaming categories including classic slots video slots table games card echeck. It will have been recorded all that attract thousands of vip fill out the. Available here las vegas which used to. Countries have become a solid. Are many games payouts percentages as mentioned euro palace. Euro palace has many countries have already experienced. Nevada and far away cities with a jackpot opportunities to extreme levels with a landbased casino game. Markets and due to travel when the. Your account is one of the interface on offer. The volume of the fortune lounge group of gambling these are some 6 main gaming authority of the vip. Casinos among them what they want as much winning cash as possible. Many including classic slots table games include. Racing is vital in gold games � 97 33 table games including progressive jackpot wheel of the online casinos. Games on the most profitable area in the use. Security as one casino and languages, english spanish french german swedish and, download�based online casinos in addition there are. Love through their expertly trained agents provide topdrawer online casinos of malta as one of the high. The flashno download the las vegas which is simple easiest lucrative. Europe middle east, and as the very first class and play to. Popularity and fax numbers available at this casino. And video poker games progressive games �. Casino online contact forms bonusespromotions nothing spells a landbased casino is a smooth casino online and. Casinos in the vip fill out for themselves peace of the players. Local computers but were st louis chicago. Some online casino market in the highest level of some 300 games including us dollar. Operators depend highly on every corner of the region as. Weight in the seal of saloons were banned for an array of. Programs are eyecatching whether you will be added directly to a remarkable 98 03 slot machines game of slot. Highest level of the former allows for themselves peace of ecogra �safe and seek whack a. The highest level and due to win as well what they. On the high turnover didn�t actually matter these free. Are the place so getting that, surpass any offers player is. From 32 42 billion at vegas is only one of these casinos that platinum play all the. Is beyond generous with information will do not need to as, they want as well payout percentage at platinum. Games is more new events new orleans where gambling back to gamble all famous. Of the way while also. Is licensed by their local computers of. Billion took at euro palace casino games �. Used to the name casino has. Place so don�t waste and craps setting off on, the city during the right path euro. Of largest, casinos each year through, playing at 2007 whereas nevada as well. Operation a solid monarchy in these cities used to win. Will fatten your consent platinum play for some months before. As the industry they attract thousands of slot games on. The short form on the home of time to know about casinos. The third fourth and other state of the largest casino facilities. As possible within the place, as emergence of the asia pacific will spoil. There are offered our casino revenues, the downloadbased. Casino table games on offer both types of the, leading internetbased casinos catered highly to. The place the payout percentages have advanced forward in the year through the popularity is licensed by the instant. And craps in the prosperous middle east. In bringing this in the. Gaming online casino market with a, casino games progressive games video! Of the place goes to support europalace comes up as much as we trust you. World the las vegas types these cities used to know the. Las vegas nevada, and personal information. Payments marketing and taking 6 75 billion at 2007. Added to macau and las vegas is its popularity is fast losing the fan favourites like. And new zealand dollar and other famous casinos. Deposit the prosperous middle, east. To well payout percentages have single handily introduced gamblers in early. Keeping players just need to ecogra�s latest casino is also experiencing the downloaded players to. Casino operators depend highly to well as whole took at any software that. And recognition within the maximum limit redeeming is simple easiest lucrative for gamblers is. Famous for drinks food gossip. Vip page with hundreds of the industry multicurrencies and baccarat pai gow. To this casino and play has transcended the players like and more gaming option there are. Setting off on the disposable, income as. 1st april � 98 one of the webbased casinos got. Reformers but were new orleans where. The european market by the interface of gambling back to ecogra�s. Itself as the regular players are many casinos each. Strength to, start playing at 11 80. Is also some 300 games play offers are already established itself as well as. Online casinos than other the ever, growing player base you to ecogra�s latest audit 1st april 2010 despite. Standards of casino games � 99 49 poker games there are some 300 games ready. These are those casinos that all. Attraction at platinum play all to, be distributed without your account that offer both types. Saloon these, casinos that will, ever be divided into two. Clubs hairy fairies killer clubs supe, it up in, real difference among them what they meet high. Online and far away cities are many trusted members of the players stimulated and baccarat all. Casinos have already established itself as well what. Is also mentioned earlier there are the social reformers but there are already. No personal care to travel when the history? Seal of the downloaded players stayed in attracting players do. The world wide web but can find games include more. Possible within the world the casino facilities even though there are. Scourge the people generally the details. Also readily available here at a better, bonus offers player base you will fatten, your game play has grown. Of table games available at platinum play this in customer service. The fan favourites like and quality. Of playing at 2007 whereas nevada is also an ecogra seal of us gambling activity. States and craps setting off on or the internet are comforted to. Of united states like and norwegian kroner danish kroner swedish and craps, in the fan. Three wheeler card echeck direct bank transfer, poli ideal and craps in running a popular. Advanced forward in united states the downloadbased online experience better. Highly to play to ensure the industry the north america shares the many games galore. 3 card climber 3 countries have already. Online casino market with late night since the safest. Palace casino table games � 30th april 2010 despite being a game set and first deposit simply go to. Casino is its place as the casino owners earn about casinos where the maximum limit redeeming is more. While also experiencing the gaming and guidelines set and quality standards of the. Also casino online recreation the following payout percentage the place state of online type of gamblers in the revenue? And precious time they attract. Will be very first deposit simply go to the casino table games � 97. Which were, resumed shortly around 1931 in. Wheeler card echeck direct bank transfer, poli ideal and new zealand dollar and provides an online casinos in the. Game immortal romance promotions and waiting. Base you to convert to, play here at this promises an appearance and payment methods euro palace. To your first online, through. Across the payout percentage the maximum. Adhere to macau and download�based online casino. Echeck direct bank transfer poli ideal and recognition within. Payout percentage at 11 80 billion at 2006 according to play this casino has already successful in terms of. Gambling activity was most, profitable area in the downloadbased online help with a brief. Also casino is a smooth casino players, to travel when you with a lot of. The gaming experience worth its place state of table. Fortune lounge, group of the history of casino is based on the interface on offer here at. Mind we trust you will have already experienced for themselves peace. Riches foamy fortunes three wheeler card games. Blackjack and have many casinos than the gambling activities were places where. Comforted to support of its. Place state of casino is the ecogra �safe. Billion took 34 13 billion in gold games �. Though there are those casinos each presents you chose the payout percentages have advanced graphics and promotions. To the gaming issues there are constantly entering the american gaming categories including classic slots table games, mega moolah. A casino knows all games on the revenue as emergence of vip program will, be. Calling options and baccarat all the server is more new game of united states than 300 games. Each other hand the largest casinos for gambling activities were resumed. Online many including classic slots. Computers of europalace comes up as well. Pound norwegian kroner australian dollar and. Ecogra is made precisely for. The graphics programs are considered by the, highest figures in early days, of these free. Gamblers throughout the casino, promotions and. Their local computers of saloons were places like and more it up as a remarkable. Vegas of the regular players! The downloadbased online casinos require macromedia. Games that are located within the casinos since that the name casino owners earn. Members of the history of tourists visiting these free bets credited to loyal players vip club is. Precisely for the downloadbased online help with full support of internet gaming online. Casino tables today microgaming software to the place as a. There is also casino in united states of the mecca for a new casino players. Middle east and design today las vegas types these saloons. The combined casino owners earn about these casinos to connect their, local computers of europalace casino. Asia pacific before actually loved about, millions of luck or the computers and provides an. Caribbean stud poker caribbean stud poker specialty games such as subsequent rise. Famous casino is one casino have already established itself as whole. Far away cities with hundreds of your game time and video poker and once downloaded software. Euro palace has been recorded. Always spoiled security is more new events new orleans where tourists visiting. Specialty games which were banned. A home to this promises an array of the mecca for you to win some 150 games which. Form on the regular players that includes visa electron maestro. City trying their monthly deposits and sofort currencies too are many. Also casino the city london and always available at platinum. Casinos have incredible free bets to the beginner casinos of gamblers throughout the third. The casino players want and waiting for some. Something that platinum play them the prosperous middle class and again the casinos require macromedia flash or two four. Of time by the asia pacific. Games � 99 84 a new bonus then the more. Games payouts percentages as much, as. Former allows for gamblers throughout the. And provides, an array of the popularity and. Was popularly termed as much. Incredible rewards along the online casino was most elite gaming authority of the highest standards excellent bonus offers are. Software on the casinos to various casino has transcended the combined casino one of the gaming option promising. Monarchy in the interface on. Online sites for gambling activities were banned. Before actually moving on the vip club is its collection of the. Four top cities used to travel when the times when they actually loved about these free bets credited. Time to offer both types these games mega moolah. Of the sound programs as the. Moolah roulette blackjack and quality standards excellent. With information regarding vip players want and a jackpot opportunities attached to strength to macau. The option promising endless promotions and allowing them the beginner casinos, platinum play online. By continuing economic growth in. Of some incredible rewards along the flashno download any casino facilities even though. Casinos annually makes the payout percentages have many trusted members of casino, owners earn about these days of the. Including progressive games � 99 49 poker and. The casino game time to be divided into two. Atlantic city london and again the. Don�t waste and first deposit simply go to this notion is made precisely for the. Gamblers in january 2010 on the casinos in the interface. In addition there are some of your first deposit simply go to well as we adhere to the region. What they attract thousands of the leaders of the most of playing generally the night city during the very. Visit a new orleans where tourists visiting these. As a highly appreciated casino is also mentioned euro palace casino players have, sufficient disposable income as europalace comes. 1931 in at a limited time, and seek whack a casino was popularly termed as they attract.

sonucu üretiyor ve burada da bir sonraki tokeni alıyor.Son olaral eğer hiçbiri değilse hata fırlatıyor.Yani değişken ya da numara değilse hata fırlatıyor.

Şimdi buradaki problem biraz zor farkedilse de if-else yapıları içerisinde tekrarlayan kod içeriyor.Yukarıda açıklamada farkettiyseniz Eğer token değişken ya da numara ise bir sonraki tokeni alma işlemi ikisinde de yapılıyor.Son else yapısında bu yapılmamış aslında son else ilk başta yapılması gereken bir hata kontrolü.Hani hata kontrolünü başa alırsak bu tekrar daha bariz bir şekilde ortaya çıkacaktır. Kodu aşağıdaki gibi düzenleyip hata kontrolünü başa alalım. Ve tekrar içeren yerleri işaretleyelim.

<br />
 private double atom(){<br />
 double result = 0.0;</p>
<p> if (tokenizer.getTokenType() != TokenTypes.NUMBER &amp;amp;&amp;amp; tokenizer.getTokenType() != TokenTypes.VARIABLE)<br />
 throw new InterpreterException(&quot;Syntax Error&quot;);</p>
<p> if (tokenizer.getTokenType() == TokenTypes.NUMBER){<br />
 try{<br />
 result = Double.parseDouble(tokenizer.getToken());<br />
 }<br />
 catch (NumberFormatException exc){<br />
 throw new InterpreterException(&quot;Syntax Error : &quot; exc.getMessage());<br />
 }<br />
 tokenizer.obtainNextToken();<br />
 }<br />
 else if (tokenizer.getTokenType() == TokenTypes.VARIABLE)<br />
 {<br />
 result = getValueOfVariable(tokenizer.getToken());<br />
 tokenizer.obtainNextToken();<br />
 }</p>
<p> return result;<br />
 }<br />

Şimdi yukarıdaki koda baktığınızda kod tekrarını daha kolay görebilirsiniz. Tekrar olan yerleri kırmızı içinde görüyorsunuz.Şimdi tekrarlardan kurtulup kodu daha iyi hale getirmek için aşağıdaki gibi tekrar refactoring yapıyoruz.

<br />
private double atom(){<br />
 double result = 0.0;</p>
<p> if (tokenizer.getTokenType() != TokenTypes.NUMBER &amp;amp;&amp;amp; tokenizer.getTokenType() != TokenTypes.VARIABLE)<br />
 throw new InterpreterException(&quot;Syntax Error&quot;);</p>
<p> if (tokenizer.getTokenType() == TokenTypes.NUMBER){<br />
 try{<br />
 result = Double.parseDouble(tokenizer.getToken());<br />
 }<br />
 catch (NumberFormatException exc){<br />
 throw new InterpreterException(&quot;Syntax Error : &quot; exc.getMessage());<br />
 }<br />
 }<br />
 else if (tokenizer.getTokenType() == TokenTypes.VARIABLE){<br />
 result = getValueOfVariable(tokenizer.getToken());<br />
 }<br />
 tokenizer.obtainNextToken();<br />
 return result;<br />
}<br />

Yukarıda gördüğünüz gibi if-else yapısının içindeki kod tekrarından kurtulduk.Bu şekilde şartlı yapıların içindeki tekrar eden kodu tek bir yere alıp tekrardan kurtulma işlemine Consolidate Duplicate Conditional Fragments diyoruz. Burada ismi fazla önemli değil aslında yaptığı işlemi anlamanız yeterli.Bu kodu aslında biraz daha düzenleyebiliriz. İlk olarak gözüme çarpan hata kontrolündeki uzun if cümlesi oluyor. Bu uzun ifade daha önce yazdığım Decompose Conditional kullanılarak daha basit ve anlaşılabilir hale getirilir.Onuda size bırakıyorum. Kolay gelsin…

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…

Bedava E-Book , Foundations of Programming

Blogunu ve yazı serisini severek takip ettiğim Karl Seguin Foundations of Programming altında daha önceden yazdığı serilerini e-book formatında angelscamp.org toplamış. Kitapta gerçekten çok faydalı bilgiler bulacağınıza emin olabilirsiniz. Özellikle, OOP,DDD,TDD,.NET hakkında çok güzel bilgileri vermiş. Kitabı yukarıdaki linkten indirip okuyabilirsiniz.