Perşembe, Ağustos 09, 2007

Nesne Yönelimli Programlama İlkeleri I

Sadece nesneler kullanarak program yazdığımızda nesne yönelimli programlama yapmış olmuyoruz. Programımız geliştikçe bakıyoruz ki sınıf çorbası kodlamışız. Sınıfları oluştururken uyumluluğu yüksek, bağımlılığı düşük tasarımlar yapmak OOP'de hayati önem taşır. Bir sınıfın sorumlulukları birbirleri ile alakalı ise uyumluluğu yüksektir. Bir sınıf başka sınıflara bağımlı olmadan işlevini yerine getirebiliyorsa bağımlılığı düşüktür. Bunu hemen şöyle örnekleyelim. Bu sınıf hem dosya okuma ve yazma hem de dizin yaratma ve silme gibi işlerden sorumlu olsun.


class IOWorks()
{
string ReadFromFile(string path);
void WriteToFile(string path, string content);
void CreateDirectory(string directoryName);
void DeleteDirectory(string directoryName);
...
}


IOWorks sınıfının uyumluluğu düşük çünkü hem dosya hem de dizin ile ilgili işlevler içeriyor. Başka bir projede sadece dizin yaratma ve silme işi için bu sınıfı kullanmak istersek dosya ile ilgili işlevleri de ihtiyacımız olmasa da taşımış olacağız. En iyisi sınıfımızı ikiye bölerek uyumluluğu arttırmak.

class FileWorks()
{
string ReadFromFile(string path);
void WriteToFile(string path, string content);
}

class DirectoryWorks()
{
void CreateDirectory(string directoryName);
void DeleteDirectory(string directoryName);
}


Sorumlulukları dağıtarak sınıflardaki uyumluluğu arttırmış olduk. Normalde FileWorks nesnesinde WriteToFile ile kayıt yaptırmak istediğimizde eğer dosyayı kaydedeceğimiz dizin önceden yaratılmamışsa bir istisna (exception) üretiyoruz. Bazen bu istisnalarla uğraşmamak için şu tür kısayollar yaparız.

class FileWorks()
{
string ReadFromFile(string path);
void WriteToFile(string path, string content, bool autoCreateDirectory);
}

Nesnemizin dosyayı kaydederken dizini bulamadığında hemen yaratabilmesi güzel bir özellik. Ancak bu özelliği kodlayabilmek için FileWorks() sınıfı içinden DirectoryWorks() sınıfını kullanmak gerekir. Bu durumda iki sınıf arasında bir bağımlılık oluşturmuş oluyoruz. Aslında FileWorks() sınıfının ana sorumluluğu dosya kaydetmek ve bunu yerine getirebilmek için böyle bir bağımlılığa ihtiyacı yok. FileWorks() sınıfı gelişecekse imaj veya video içeren başka türde dosyalarla da çalışabilecek şekilde gelişmeli. En iyisi FileWorks() sınıfına hiç dokunmadan istediğimiz davranışı gösteren üçüncü bir sınıf tasarlamak.

class Writer()
{
void WriteToFile(string path, string content, bool autoCreateDirectory);
}

Bu sınıfımız içinden hem FileWorks() hem de DirectoryWorks() sınıfına erişerek ihtiyacımız olan davranışı elde ederiz. Writer() sınıfı FileWorks() ve DirectoryWorks() sınıflarının ikisine birden bağımlı gibi görünüyor. Aslında biz burada özel bir sorumluluğa sahip bir yeni sınıf üretmiş oluyoruz. Bu sınıfımızın sorumluluğu dosya kaydederken dizin bulunamazsa otomatik olarak açmak. Bu güzel tasarımı bozabilecek en büyük hata FileWorks veya DirectoryWorks sınıfı içerisinden Writer sınıfını kullanmak olur. Bir anda çok yüksek karşılıklı bağımlılık oluşturarak çorba tasarım yapma yolunda önemli bir adım atmış oluruz. Sınıflarımızı tasarlarken ve geliştirirken sorumluluk, bağımlılık ve uyumluluk konusunu aklımızın bir kenarında tutmak iyi bir alışkanlık olacaktır.

Hiç yorum yok: