Aydın Koca
Neyasis Technology
Published in
4 min readMay 27, 2020

--

.Net Reactive Programming

Herkese merhabalar bu yazımızda reaktif programlamanın ne olduğundan, hangi durumlarda kullanıldığından bahsedecek ve Reactive Extensions kullanarak örnek uygulama yapacağız. Günümüz programlama dillerinin bir çoğu temelinde prosedürel programlama temelinde çalışmaktadır. Prosedürel programlama, işlemleri, prosedür veya rutin olarak adlandırılan, alt işlem gruplarına bölerek çözümünün kolaylaştırılması yöntemidir. Prosedürel programlama yukarıdan aşağı yaklaşımlı bir yapıya sahiptir. Kod adım adım çalıştırılır. Ancak uygulama ihtiyaçların artmasıyla birlikte cevap süreleri düşük, kullanıcı deneyimi yüksek uygulamaların geliştirilmesi gerekmektedir. Bu durumda ilgili satırların çalıştırılmasını beklemek yerine bir olay gerçekleştiğinde veya uzun süren bir işlem tamamlandığında çalışacak şekilde kodlarımızı yazabiliriz. Bu sayede cevap süreleri daha düşük ve daha yüksek kullanıcı deneyimine sahip uygulamalar geliştirmiş oluruz.

Prosedürel programlama yapısı

Reactive Programlama Nedir?

Uygulama çalışırken kodu meydana getiren satırların akış sırasını değil çalışan kodun olaylarını takip eden ve bu olayların yan etkilerinide işleyebilen programlama yaklaşımına denir. Yapılan işlemlerde asenkron veri akışlarını kullanmayı ve olay bazlı çalışmayı ilke edinen bir yaklaşıma sahiptir.

Neden Asenkron İşlemler Kullanılmalıdır?

Asenkron işlemler genellikle uzun zaman alan işlemlerdir. Uygulamalar daha duyarlı hale getirilmek için kullanılmalıdır. Örneğin siz sistem üzerinden sipariş oluştururken sistem arka taraftan farklı bir web servis ile haberleşiyor olabilir. Sipariş sonucunu görüntülemek için web servis cevabını beklemeden işlem yapılmasını sağlar. Bu sayede dış kaynakta geçirilen süre kullanıcıya yansıtılmadan sorunsuz bir kullanıcı deneyimi sunmayı sağlar.

OOP (Nesne Yönelimli Programlama) ve Reactive Programming Arasındaki Fark Nedir?

Oop gerçek hayattaki nesneler baz alınarak modelleme yapılarak tasarlanır. Reactive programlamada ise gerçek hayattaki olaylar baz alınarak tasarlanır.

Rx (Reactive Extensions System.Reactive)

Rx, .Net için geliştirilmiş bir reactive programlama kütüphanesidir.

Rx çalışma yapısı

Örnek uygulamalara geçmeden önce rx’in temel unsurlarından bahsedecek olursak. Bunlar Observable, Observer, Subject ve Stream

Observable ve Observer

Reaktif programlama yaklaşımı gözlenebilir olarak tasarlandığından akış içerisinde bildirim yapıldığında yapılan bildirime tepki verilebilmektedir. Gözlemlenebilir veri akışı nesneleri Observable, tepki nesneleri ise Observer olarak adlandırılır.

Subject

Observable ve observer ortak özelliklerini içerir. SubjectBase sınıfından kalıtılmıştır. Hem IObserver hemde IObservable interfacelerini implemente etmektedir.

Stream

Uygulamalar genellikle birden fazla olayı ele aldığından olaylar dizisi oluşturulabilir. İşte bu olaylar dizisi stream olarak adlandırılır.

Bir örnek ile inceleyecek olursak aşağıdaki kodun ekran çıktısını incelediğimizde, kodumuz bloklanmadan arkaplan işlemimizi çalıştırabildiğimizi görüntülemekteyiz.

dotnet add package System.Reactive 

Reactive kütüphanesi içerisinde yer alan Observable sınıfını kullanabilmek için Package console aracılığıyla projeye System.Reactive kütüphanesini projemize dahil ediyoruz.

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Ana iş parçacığı başladı.");
var o = Observable.Start(() =>
{
Console.WriteLine("Ana iş parçacığı blocklanmadı");
Thread.Sleep(4000);
Console.WriteLine("Arkaplan işlemi tamamlandı");
}).Finally(() => Console.WriteLine("Ana iş parçacığı tamamlandı"));
Console.WriteLine("Main thread devam ediyor");
o.Wait();
Console.WriteLine("Arka plan işlemi sonlandı");
}
}

Ekran çıktısı

Ana iş parçacığı başladı.
Main thread devam ediyor
Main Thread blocklanmadı
Arkaplan işlemi tamamlandı
Main thread tamamlandı
Arka plan işlemi sonlandı

Console uygulaması içerisinde belirli bir olay gerçekleştiğinde Subscribe olan eventleri kodu bloklamadan çalıştırabileceğimiz bir örnek inceleyelim. Öncelikle event modelini oluşturuyoruz.

public class ProductEvent
{
public string Message { get; set; }
}

Eventi bu model ile subscribe ederek publish edeceğiz.

dotnet add package System.Reactive

Reactive kütüphanesi içerisinde yer alan Observable sınıfını kullanabilmek için Package console aracılığıyla projeye System.Reactive kütüphanesini projemize dahil ediyoruz.

Publish ve subscribe işlemlerini yapacağımız EventHandler<T> sınıfını oluşturuyoruz.

public class EventHandler<T> 
{
private readonly Subject<T> _subject;
public EventHandler()
{
_subject = new Subject<T>();
}
public void Publish(T eventMessage)
{
_subject.OnNext(eventMessage);
}
public void Subscribe(Action<T> a)
{
_subject.Subscribe(a);
}
}

EventHandler ile T tipinde Subscribe ve Publish işlemini gerçekleştireceğiz. Consumer nesnelerini tanımlıyoruz. Consumerlar ile subscribe olarak event gerçekleştiğinde çalışması istenilen methodu göndereceğiz.

public class ProductConsumer
{
private readonly EventHandler<ProductEvent> _eventHandler;
public ProductConsumer(EventHandler<ProductEvent> eventHandler)
{
_eventHandler = eventHandler;
}
public void Subscribe()
{
_eventHandler.Subscribe( async (e) => {
await Task.Run(() => { Console.WriteLine("Product Consumer: " + e.Message); });
});
}
}
public class BasketConsumer
{
private readonly EventHandler<ProductEvent> _eventHandler;
public BasketConsumer(EventHandler<ProductEvent> eventHandler)
{
_eventHandler = eventHandler;
}
public void Subscribe()
{
_eventHandler.Subscribe(async (e) => {
await Task.Run(() => { Console.WriteLine("Bakset Consumer: " + e.Message); });
});
}
}

İlgili consumer sınıflarında eventhandler nesnesini kullanarak asenkron subscribe edecek methodlarımızı tanımladık. Publish işlemi gerçekleştiğinde eventler ana kodu bloklamadan işlem gerçekleştirecek. Main methodu içerisinde eventhandler ve consumerları create ederek publish işlemini gerçekleştiriyoruz.

static void Main(string[] args){var eventHandler = new EventHandler<ProductEvent>();ProductConsumer pc = new ProductConsumer(eventHandler);pc.Subscribe();BasketConsumer dd = new BasketConsumer(eventHandler);dd.Subscribe();eventHandler.Publish(new ProductEvent() { Message = “Product Event” });//İlgili event taskları background task olarak çalışacağından console uygulamasını bekletme amaçlı yeni thread Thread s = new Thread(()=> { Thread.Sleep(9000); });s.Start();}

Ekran Çıktısı

Basket Consumer: Product Event 
Product Consumer: Product Event

--

--