Yazılım Mühendisliği

Ekim 20, 2008

Single Responsibility Pattern

Filed under: Metaforlar,Metodolojiler — Yahya KOÇ @ 6:02 pm
Tags:

“Single Responsibility Pattern”, adından da anlaşılacağı gibi her sınıfın sadece bir sorumluluğu yerine getirmesi anlamına geliyor. Cümleyi tersten okuduğumuzda çıkan anlam da doğrudur: Bir işi sadece bir sınıf yerine getirir.

Nesneye yönelik programlamanın temel mantığı, çalışan kodu yönetilebilir,anlamlı en küçük birimlere ayrımaya dayanır.Böylece modüler yapı sağlanmış olacak,yeni ihtiyaçlar ışığında değişmesi gerekecek ve bu değişimden etkilenecek birimler asgari seviyede tutulacaktır.
Konuyu bir örnek üzerinde inceleyelim:
Bir Haber ajansının güncel haberleri abonelerine gönderen şöyle bir kod parçası olsun.

static void Main(string[] args)
        {
            HaberYoneticisi haberYoneticisi =new  HaberYoneticisi();
            haberYoneticisi.HaberleriAbonelereGec();
        }

   public  class HaberYoneticisi
    {
        public void HaberleriAbonelereGec()
        {
            IList guncelHaberler=Haber.GetAll();
            foreach (Haber haber in guncelHaberler)
            {
                IList aboneListesi = haber.AboneListesi;
                foreach (Abone abone in aboneListesi)
                {
                    Mail mail=new Mail();
                    mail.From = "XXX AJANS";
                    mail.To = abone.mail;
                    mail.Subject = haber.Icerik;
                    mail.Server = "exchange";
                    mail.Port = 25;
                    mail.Send();
                }
            }
        }
    }

HaberYoneticisi sınıfı içerisinde yeralan HaberleriAbonelereGec metodunda iki işlem yapılıyor:

  • Güncel haberlerin abonelerini bulma
  • Bulunan abonelere mail atma

Burada yer alan iki iş, biribirine sıkı bir şekilde bağlı olsa örneğin “Aboneleri bul”,”Abonelerin puanını bir artır” gibi başka yerde tekrarlanmayacak iki iş olsa,bunları ayırmak her birine sınıf yazmak OverEngineering diye tabir edilen gereksiz kompleksliğe yol açar.Fakat burda geçen “…’a mail atma” işinin, başka bir çok sınıf içinde geçtiğini varsayalım*.(Abonelere,yöneticilere,diğer ajanslara mail atma)Bu durumda her sınıf içinde aynı işi yapan kodlar gereksiz kod tekrarına yol açar.Ek olarak mail atan sınıflarda “System.Net.Mail” gibi sistem sınıflarına gereksiz yere referans vermiş oluruz.İp yumaklarının biribirine karışmasına benzer bu durumdan aşağıdaki çözümle kurtulabiliriz.
————————————–
*Dikkat edin “ileride geçebilir” demiyorum. “İleride geçer” diye şimdiden sınıfları ayırıp,gruplama yapmıyoruz.Bu bizim Heuristic(deneme-yanılma) yöntemle kod yazma felsefemize uymuyor.İleride, ihtiyaç olduğunda gerekli refactoring işlemleriyle ayrıştırma yapılabilir.
————————————–
Çözüm:İkinci işin(mail atma) kod bloğunu ayrı bir sınıfa alıyoruz.O sınıfı, ilk sınıfımız içerisinde (use-a yada has-a ilişkisi) kullanıyoruz.Ya da bu kısmı bir arayüz(interface) içine alıp(is-a ilişkisi) sınıflarımızı bu arayüzü uygular hale getiriyoruz.Biz bu örnekte “use-a” ilişkisini tercih edelim.

Kodumuzun yeni durumuna bakalım:

 public  class HaberYoneticisi
    {
        public void HaberleriAbonelereGec()
        {
            IList<Haber> guncelHaberler=Haber.GetAll();
            foreach (Haber haber in guncelHaberler)
            {
                IList<Abone> aboneListesi = haber.AboneListesi;
                foreach (Abone abone in aboneListesi)
                {
                   MailSender.Send(abone, haber);
                }
            }
        }
    }
    public static class MailSender
    {
        public static void Send(Abone abone,Haber haber)
        {
            Mail mail = new Mail();
            mail.From = "XXX AJANS";
            mail.To = abone.mail;
            mail.Server = "exchange";
            mail.Subject = haber.Icerik;
            mail.Port = 25;
            mail.Send();
        }
    }

Kodu bu şekilde yazdığımızda,mail sınıfında meydana gelen bir değişiklik(port değişikliği,adres değişikliği..) diğer sınıfları etkilemeyecektir.

Yorum yapın »

Henüz yorum yapılmamış.

Bu yazıya yapılan yorumlar için RSS beslemeleri. URI'nin geri izlemesini yap.

Yorum yapın

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Değiştir )

Twitter picture

You are commenting using your Twitter account. Log Out / Değiştir )

Facebook photo

You are commenting using your Facebook account. Log Out / Değiştir )

Connecting to %s

Theme: Rubric. WordPress.com'dan blog alın.

Follow

Get every new post delivered to your Inbox.