Pub/Sub vs Observer: Gözlemciyi bilmek ya da bilmemek, işte tüm mesele bu

Koray Durudoğan
hesapkurdu-development
5 min readNov 26, 2020

Bugün sıklıkla birbirine karıştırılan iki design patterndan bahsedeceğim. En popüler GoF design patternlardan biri olan Observer nedir? Ne işe yarar? Pub/Sub nedir? Hangi sorunları çözmeyi vaad ediyor bunlara değineceğiz ve finali de ikisini karşılaştırarak yapacağız.

Observer Pattern

“The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.”

— Head First Design Patterns

Observer Pattern; Bir objenin durumu değiştiğinde, bu objeye subscribe olmuş objeleri haberdar eden bir design patterndır. DoFactory’ye göre kullanım oranı %100 olan bu patternin;

  • Uçaktan “iniş gerçekleşti” bilgisi geldiğinde kuledeki ilgili birime bildirim atılması.
  • Server odasındaki sıcaklığın belli bir derecenin üstüne çıktığında soğutma sistemine “start” komutunun yollanması.

gibi birçok yazılım çözümünde kullanım alanı olabilir. Biz de kendi örneğimizi kurgulayalım;

Bir e-ticaret sitesi geliştiriyor olalım. Üzerinde çalıştığımız özellik istek listesi olsun. İstiyoruz ki kullanıcıların birer istek listesi olsun ve istek listesindeki ürünlerden biri indirime girerse, istek listesinde o ürüne sahip tüm kullanıcılara e-mail gitsin.

Kodlamadan anlaşılmaz, başlayalım!

ObserverPattern isminde bir console app oluşturalım, müşterinin yapısını tanımladığımız abstract bir sınıf yaratalım ve bu sınıfa observe etme (gözlemleme) özelliğini ekleyelim. Sonra da somut müşteri sınıfımız oluşturalım.

Müşterinin observe edeceği ürün sınıflarımızı oluşturalım. Her ürünün kendisine ait, observe edebilme becerisine sahip sınıflardan oluşan bir List’i olacak. Ürünün fiyatında bir düşüş meydana geldiğinde listteki tüm observerları notify edecek.

Aquaman observerını bildiği için mutlu. Notify geliyor !

Her şey hazır gibi, bir ürün ve bu ürüne subscribe olacak bir grup müşteri yaratalım ve ürünü indirime sokalım.

Projeyi çalıştırdığınızda tüm kullanıcılara mail atıldığına dair konsol çıktısını görüyoruz.

Pub/Sub Pattern

Enable an application to announce events to multiple interested consumers asynchronously, without coupling the senders to the receivers.

https://docs.microsoft.com/

Bir projenin kendi içinde olan değişiklikleri, kendisine subscribe olmuş projelere haber verdiği bir design patterndır. Pub/Sub patternin

  • Evin güvenlik sistemi alarm durumuna geçtiğinde güvenlik firmasındaki ilgili birime, polise, ev sahibi ve ev sahibinin dinamik olarak ekleyip çıkarabildiği yakınlarının iletişim bilgilerine çağrı atılması gibi major hizmeti notify etmek olan sistemlerde
  • TL/USD değeri değiştiğinde bankalara, firmalara, yatırımcılara, haber kanallarına, gazetelere, döviz değişimini loglayan uygulamalara ve ileride eklenmesi/çıkarılması muhtemelen olan birçok subscribera hizmet veren sistemlerde

kullanımı uygundur. Biz iki patterni karşılaştırmak adına aynı örnek üzerinden gidelim ama bu sefer üç farklı projeden oluşan bir mimari kurgulayalım. Üç farklı proje içeren bir mimari tercih etmemizin sebebi; Bu patternin tercih edileceği mimari ölçeğin daha büyük olması ve buna uygun loosely coupled bir yapı kurmak diyebilirim. Bu tercihimizi yazımızın sonundaki karşılaştırma bölümünde detaylandıracağız.

Öncelikle ürünlere subscribe olmak isteyen müşterileri ileten bir proje (Subscriber) yazacağız. Ardından ürün fiyatındaki düşüşü haber verecek bir proje (Publisher) yaratacağız. Son olarak da iki proje arasındaki iletişimi sağlayan, subscribtionları topiclere göre bölen, hangi müşterinin hangi ürüne subscribe olduğunu yönetmekten sorumlu bir proje (Broker) geliştireceğiz.

Image source: https://docs.microsoft.com

Hadi başlayalım! Öncelikle Subscriber isminde bir web app oluşturuyorum ve dışarıdan gelecek e-mail, device bilgilerini karşılayacak bir model oluşturuyorum.

Ardından subscribtion isteğini Broker’a iletecek controller sınıfımı yaratıyorum.

Sıra geldi Broker’a ürün indirimini haber verecek olan projeye. Publisher isminde bir web app oluşturuyorum ve indirimi iletmekten sorumlu controller sınıfını yaratıyorum. Burada önemli olan noktalardan biri Publisher’ın kendisine subscribe olan kişiler hakkında hiçbir bilgisi olmadığı.

Aquaman kendisine subscribe olanları bilmediği için kızgın. Kendisi daha çok observer pattern adamı !

Son olarak iki proje arasında bağlantıyı sağlayan, hangi kullanıcının hangi ürüne subscribe olduğu bilgisini tutan Broker projesini yaratıyoruz. Bu projeye farklı kaynaklarda event bus ya da message broker dendiğini de görebilirsiniz.

SubscribeRequest sınıfını bu projede de yaratıyorum ve subscribe & notify görevlerini üstlenen servis sınıflarımı oluşturuyorum. Laptop ve Phone için iki ayrı servis yaratıyorum ve dışarıdan gelen device bilgisine göre uygun servisi döndüren bir Factory yazıyorum. Ben servisleri Singleton yarattım çünkü subscribtion bilgisini veritabanı ya da başka bir veri kaynağına yazarak karmaşa yaratmak istemedim, uygulama yaşam döngüsü boyunca aynı servis instanceı üzerinden çalışıyor olacağız. Örneği uzatmamak için notify ile direk mail atımını gerçekleştirdim, isterseniz siz Subscriber projesine e-mail bilgilerini dönebilir ve mail atma sorumluluğunu o projeye yükleyebilirsiniz.

E-mail subscribtion’ı ve indirim notify’ı için gerekli controller sınıfımı da oluşturuyorum ve artık teste hazırız!

AbsSubscribeService’in altındaki Notify methoduna breakpoint koyuyorum ve üç projeyi de ayağa kaldırıyorum.

https://localhost:44320/subscription adresine aşağıdaki iki data ile ayrı ayrı POST çağrısı atıyorum.

Ben phone ve laptop için birer subscription gerçekleştirdim. Siz örneği zenginleştirmek için daha fazla e-mail ile subscribe olabilirsiniz.

Koray telefon, Ted laptop için olacak indirimlere subscribe oldu. Sıra geldi notify almaya.

https://localhost:44312/notifier/laptop adresine GET çağrısı yaparak laptop için indirim gerçekleştiğini bildiriyorum. Breakpointe düştüğümüzde List’e bakarsak Ted’in mail adresini göreceğiz.

İki pattern ile de aynı sonucu elde etmiş olsak da yapısal olarak birçok değişiklik fark ettiğinize eminim.

  • Tüm yazı boyunda üzerinde durmaya çalıştığımız en önemli fark; Observer patternde Publisher sınıflar, kendilerine subscribe olmuş observerların bilgisine sahip. Eğer ki Publisher katmanında kaç observerın hangi publishera subscribe olduğu bilgisi kıymetli ise Observer pattern tercih etmelisiniz. Eğer bu bilginin anlamlı olmadığı bir kurgunuz var ise Pub/Sub tercih edilebilir.
  • Observer patternde publisherlar IObserver interfaceini tanırlar ve bu interfacei taşıyan sınıfları notify ederler. Her ne kadar bir interface’e bağımlı olmak Dependancy Inversion’ı sağlasa da, Pub/Sub da publisher ve observer sadece endpoint bilgisi ile bağlandığı için daha da loosely coupled bir yapı vaad ediyor.
  • Observer pattern tek bir solution içerisinde geliştirilir. Pub/Sub ise farklı domainler altında bulunan farklı yazılım çözümleriyle dağıtık olarak çalışabilir. Dolayısıyla Pub/Sub’da aynı yapı ile birden fazla Subscriber projesine destek verebilir veya ileride bir projeyi çıkarıp yerine aynı işi yapacak başka bir proje koymak gibi infra düzenlemeleri çok daha eforsuz yapabilirsiniz. Eğer yazılımınızdaki major hizmetlerden biri notifying ise yada notifyingi ayrı bir projede yürütmenizin daha maintainable olacağı ölçekte bir yazılım kurguluyorsanız Pub/Sub’ı tercih etmenizi öneririm.
  • Son olarak Pub/Sub patternde observerları farklı topiclere ayırarak kategorize etmek mümkün. Benzer bir yapıyı observer ile de kurabilirsiniz tabii ama tek seçim kriteriniz topic ise Pub/Sub’ı tercih etmenizi öneririm. Pub/sub’da topic yapısını kurmanın ve maintaine etmenin daha kolay olduğunu düşünüyorum.

Observer ve Pub/Sub patternleri açıklamaya, örneklendirmeye ve farklarını elimden geldiğince aktarmaya çalıştım. Bu tür konular ile ilgili destek almak veya bizlerle görüşmek isterseniz dev@hesapkurdu.com adresinden bizimle iletişime geçebilirsiniz. Projeyi incelemek isteyenler için aşağıya GitHub linkini bırakıyorum.

Eğer buraya kadar okuduysanız desteğiniz için teşekkürler. Hesapkurdu ve Koalay’dan sevgilerle! Yeniden görüşmek üzere, saygılarımla.

Referanslar

--

--