Reactive Extensions Kullanım Alanları

Reactive Extensions  getirdiği kolaylıkları ve avantajlarıyla giderek daha da yaygınlaşıyor. Artıları sayesinde Event-driven programming’inden daha iyi olduğu tartışılmaya başlanmış durumda.

Şimdi bunu biraz açalım. Ödeme yapıldığında tetiklenecek event mekanizmasını hemen hemen şöyle tasarlarız:

    public class Order2

    {

        public DateTime? PaidDate { get; set; }

        public Action PaidServiceEvent;

        public void MarkPaid(DateTime paidDate)

        {

            PaidDate = paidDate;

            PaidServiceEvent.Invoke();

        }

    }

Kullanırken de,

_order2 = new Order2();

_order2.PaidServiceEvent = () => MessageBox.Show(_order2.PaidDate.ToString());
       _order2.MarkPaid(
DateTime.Now);
gibi bir şey yaparız. Şimdi RX ile nasıl yapacağımıza bakalım ve artılarını inceleyelim:

    public class Order

    {

        public DateTime? PaidDate;

 

        private readonly Subject<Order> _paidSubj = new Subject<Order>();

        public IObservable<Order> PaidServiceEvent { get { return _paidSubj.AsObservable(); } }

 

        public void MarkPaid(DateTime paidDate)

        {

            PaidDate = paidDate;

            _paidSubj.OnNext(this);

        }

     }

RX’in kullanımı ise,
         _order =
new Order();
         _order.PaidServiceEvent.Subscribe(t =>
MessageBox.Show(string.Format("ödeme yapıldı {0}", _order.PaidDate)));
şeklinde olacaktır.

İlk bakışta efor ve mantık olarak aralarında pek fark yokmuş gibi görünebilir. Ama kod okunabilirliği ve yorumlanması, kodun yönetilebilirliği ve geliştirmeye açık olması gibi konular göz önüne alındığında çok daha avantajlı olduğu görülecektir. Bu, yalnızca aynı işi yapan Event-driven ve Reactive programming örnekleri. Ama PaidServiceEvent’inden scheduler, asenkron çalışma, UI’ı kilitlememe, thread yönetimi, veya Order nesnesindeki bir değere göre event’ın tetiklenip tetiklenmeyeceğine karar veren bir kriter eklenmek istendiğinde, RX ile Event-driven programming arasındaki fark giderek açılıyor. RX’i kullanmak için bir sürü sebep çıkıyor.

Hal böyle olunca bir çok Microsoft teknolojisinde RX kullanılmaya başlandı. RX’in kullanıldığı teknolojiler arasında, Windows Forms, Web Applications, WPF, Silverlight, Mobile ve hatta çeşitli robotlar bulunmakta. En son Kasım 2010’da XNA ve Windows Phone 7 desteği geldi. Bununla birlikte RX gerçek hayatta da kullanılmaya başlandı.

Örneğin vardiyaları yönetmek için yazılan bir time tracking programı olan Timecard projesinin koordinatörlerinden biri olan Samuel McAravey RX’e oldukça önem veriyor. Öyle ki teknik dökümanda teknolojiler kısmında ASP.Net ve WCF RIA ile birlikte RX de üçüncü olarak yerini almış durumda. Burada RX’in, karmaşık dataların yüklenmesi ve yönetimi konusunda sağladığı kolaylıklardan bahsedilmiş. Bununla birlikte UI tarafındaki web service çağırımlarında yine RX tercih edilmiş. Bu sayede web service’ten gelen data’ların işlenmesini kolaylaştırmışlar.

Samuel ilk olarak Silverlight’ı tercih ettiklerini söylüyor. Ama bunun az data yüklerken tercih edilebileceğini; Timecard gibi büyük data’ların döndüğü bir yazılımda bunun problem olduğundan bahsediyor. Çünkü Timecard’da 18 tip yüklenirken ekranın kilitlenmesi isteniyor, diğer tipler yüklenirken ise asenkron bir şekilde yüklenmesi isteniyor. Bunu tabi ki şu anki teknolojilerle yapmak mümkün ama oldukça zahmetli ve maliyetli bir iş. RX ise burada devreye girip data’ların yüklenmesini paralel bir şekilde gerçekleştiriyor.

Bununla birlikte bir entity base nesnesi kaydedildiğinde, değiştirildiğinde veya yüklendiğinde, Load Action’unun başlatılması isteniyor. Yani Load Action’u, Entity Base içindeki Observable nesnesine subscribe ediliyor. Bu sayede nesne üzerinde bir değişiklik olduğunda, subscribe edilen load action’u asenkron olarak çağırılabiliyor. Kod ise şöyle:

this.Users.Load.Subscribe(users => {/*Load Action olarak yapılması istenen işler.*/});

Yukarda bahsetmiştim, bu işi birçok nesne yüklendiğinde yapmak istiyorlar. Bunun için ise Observable’ın ForkJoin metodu kullanılmış. Şöyle:

Observable.ForkJoin(

    this.UserSummaries.Load,

    this.ProjectSummaries.Load,

    this.CategorySummaries.Load,

    this.MilestoneSummaries.Load,

    this.CustomerUserSummaries.Load,

    this.ProjectMemberSummaries.Load,

    this.ProjectCategorySummaries.Load,

    this.CustomerProjectSummaries.Load)

    .Subscribe(unit => {/*Tüm nesnelerde istenen event tetiklenip bittiğinde çalışacak olan Load Action*/});

ForkJoin metodu bir başka ihtiyaçları olan sıralı çağırımlar sonunda gelen veriler içinde sorgulama yapma konusunda sorunu çözmüş.

from loadData in Observable.ForkJoin(

     App.Model.Roles.Load,

     App.Model.UserTypes.Load)

from user in this.users.Query(this.users.GetUserByIDQuery(userID))

select user;

Burada, Roles ve UserTypes yüklendikten sonra, dönen User’lar içinde GetUserByIDQuery metodu çağırılıyor.

Son olarak RX’in Queue mekanizması da Timecard’da kullanılmış. Bu sayede Observable nesnelerinin birbirini bozmasının önüne geçilmiş.

Aynı zamanda Reactive Programming, akademik geliştirmelerde de yerini almış durumda. Yale Üniversitesi ile organik olarak bağlı “The Yale Haskell Group” tarafından geliştirilen bir domain specific language olan Haskell’de Reactive Programming’e oldukça önemli görevler düşmüş. Haskell’in RP ile ilgilenen kısmı, dilin içersine gömülmüş bir dil olan Yampa.

Yampa’nın Reactive Programming olmasının nedenini ise birincil olarak performans sorunlarına bağlamışlar. Çünkü spesifik alanı olan robotic programming’de performans oldukça önemli bir konu. Çünkü bu tür çalışmalarda birçok farklı ortamdan veri alınarak bunların işlenmesi, değerlendirilip buna göre bir aksiyon yaratılması gerekmekte. Yani bir robot için, bir sensörden gelen veriyi işlerken aynı zamanda teker kontrolü, robotun duvara olan uzaklığı gibi verilerin de alınıp işlenmesi gerekmektedir.

Son olarak her uygulamada yerini alan RX kullanımlarından bazıları ise şöyle:

-          Twitter veya Facebook API’lerini kullanarak bazı verilere ulaşmak.

-          SuggestionTextBox yapmak(TextChangedEvent)

-          Mouse hareketi ile ekrana bir şeyler çizdirmek(MouseMoveEvent)

-          Drag and drop işlemleri(yine MouseMoveEvent ile)

Görüldüğü gibi veri kaynağında bir değişim olduğunda gerçekleşecek tüm olaylar için RX kullanılabilir. Bunu yaparken de sistemimize asenkron çalışma, throttle, gelen veri içinde sorgulama yapma gibi birçok yeteneği de kazandırmış oluyoruz.

Bir de ilgililerine, RX’in Mono üzerinde de çalıştığını söylemekte fayda var(http://maurits.wordpress.com/2012/11/21/using-reactive-extensions-with-mono/).

28.06.2013 edit: MassTransit: http://docs.masstransit-project.com/en/latest/overview/valueadd.html#rx-integration https://github.com/MassTransit/MassTransit/tree/master/src/MassTransit.Reactive
reactiveextensionscsharp
onur aykac tarafından yazıldı.

Yorumlar

17 Şub, 2017 01:01

great post , really good perspective on the subject and very well written, this certainly has put a spin on my day, many thanks from the UK and keep up the good work

Yorumlarınız

Yorum

Önizleme