Konular neden .NET Reaktif Uzantılarda önerilmiyor?


111

Şu anda .NET için Reactive Extensions çerçevesini kavramaya başladım ve bulduğum çeşitli giriş kaynakları (esas olarak http://www.introtorx.com ) üzerinde çalışıyorum.

Uygulamamız, ağ çerçevelerini algılayan bir dizi donanım arabirimini içerir, bunlar benim IObservable'larım olacak, daha sonra bu çerçeveleri tüketecek veya veriler üzerinde bir şekilde dönüşüm gerçekleştirecek ve yeni bir çerçeve türü üretecek çeşitli bileşenlere sahibim. Örneğin, her n'inci kareyi görüntülemesi gereken başka bileşenler de olacaktır. Rx'in uygulamamız için yararlı olacağına ikna oldum, ancak IObserver arayüzü için uygulama ayrıntılarıyla uğraşıyorum.

Okuduğum kaynakların çoğu (hepsi değilse de), IObservable arayüzünü kendim uygulamamam gerektiğini, ancak sağlanan işlevlerden veya sınıflardan birini kullanmam gerektiğini söyledi. Araştırmamdan, bir oluşturmanın Subject<IBaseFrame>bana ihtiyacım olan şeyi sağlayacağı anlaşılıyor, donanım arayüzünden verileri okuyan ve ardından örneğimin OnNext işlevini çağıran tek iş parçacığıma sahip olacaktım Subject<IBaseFrame>. Farklı IObserver bileşenleri daha sonra bildirimlerini bu Konudan alacaktır.

Benim kafa karışıklığım, bu öğreticinin ekinde verilen tavsiyeden geliyor :

Konu türlerini kullanmaktan kaçının. Rx, etkili bir şekilde işlevsel bir programlama paradigmasıdır. Özneleri kullanmak, şu anda potansiyel olarak mutasyona uğrayan durumu yönettiğimiz anlamına gelir. Aynı anda hem mutasyon durumu hem de eşzamansız programlama ile uğraşmak çok zor. Ayrıca, aboneliklerin ve dizilerin doğru ve tutarlı yaşam süresinin korunmasını sağlamak için operatörlerin çoğu (uzatma yöntemleri) dikkatlice yazılmıştır; konuları tanıttığınızda, bunu kırabilirsiniz. Nesneleri açıkça kullanırsanız gelecekteki sürümler de önemli performans düşüşü görebilir.

Benim uygulamam performans açısından oldukça kritik, açıkçası üretim koduna girmeden önce Rx modellerini kullanmanın performansını test edeceğim; ancak Subject sınıfını kullanarak Rx çerçevesinin ruhuna aykırı bir şey yaptığımdan ve çerçevenin gelecekteki bir sürümünün performansa zarar vereceğinden endişeleniyorum.

İstediğimi yapmanın daha iyi bir yolu var mı? Herhangi bir gözlemci olsa da olmasa da, donanım yoklama iş parçacığı sürekli olarak çalışacaktır (HW tamponu aksi takdirde yedekleyecektir), bu nedenle bu çok sıcak bir dizidir. Daha sonra alınan çerçeveleri birden fazla gözlemciye iletmem gerekiyor.

Herhangi bir tavsiye çok takdir edilecektir.


1
Konuyu anlamama gerçekten yardımcı oldu, sadece uygulamamda nasıl kullanacağıma dair kafamda bir şeyler var. Bunların doğru şey olduğunu biliyorum - çok itme odaklı bir bileşen boru hattına sahibim ve bir GUI'de görüntülemek için UI iş parçacığında her türlü filtreleme ve çağırma yapmam ve son alınan çerçeveyi arabelleğe almam gerekiyor. vb - Sadece ilk seferinde doğru yaptığımdan emin olmam gerekiyor!
Anthony

Yanıtlar:


70

Tamam, eğer dogmatik yollarımı görmezden gelirsek ve "özneler iyi / kötüdür" hep birlikte görmezden gelirsek. Sorun alanına bakalım.

Bahse girerim, nankörlük etmeniz gereken 2 sistem tarzından birine sahipsinizdir.

  1. Sistem, bir mesaj geldiğinde bir olay veya geri arama yapar
  2. İşlenecek herhangi bir mesaj olup olmadığını görmek için sistemi sorgulamanız gerekir.

1. seçenek için kolay, sadece uygun FromEvent yöntemiyle sarmalıyoruz ve işimiz bitti. Pub'a!

2. seçenek için, şimdi bunu nasıl sorguladığımızı ve bunu nasıl verimli bir şekilde yapacağımızı düşünmemiz gerekiyor. Ayrıca değeri aldığımızda, onu nasıl yayınlayacağız?

Oylama için özel bir konu isteyeceğinizi hayal ediyorum. Başka bir kodlayıcının ThreadPool / TaskPool'u çekiçlemesini ve sizi ThreadPool açlık durumunda bırakmasını istemezsiniz. Alternatif olarak, bağlam değiştirme zorluğunu istemezsiniz (sanırım). Öyleyse, kendi başlığımız olduğunu varsayın, muhtemelen oylama yapmak için oturduğumuz bir tür While / Sleep döngümüz olacak. Kontrol bazı mesajlar bulduğunda bunları yayınlıyoruz. Tüm bunlar Observable için mükemmel görünüyor. Şimdi muhtemelen bir While döngüsü kullanamayız çünkü bu, iptal etmeye izin vermek için bir Disposable döndürmemize izin vermez. Neyse ki kitabın tamamını okudunuz, bu yüzden Yinelemeli zamanlama konusunda bilgilisiniz!

Bunun gibi bir şeyin işe yarayacağını hayal ediyorum. #Test edilmedi

public class MessageListener
{
    private readonly IObservable<IMessage> _messages;
    private readonly IScheduler _scheduler;

    public MessageListener()
    {
        _scheduler = new EventLoopScheduler();

        var messages = ListenToMessages()
                                    .SubscribeOn(_scheduler)
                                    .Publish();

        _messages = messages;
        messages.Connect();
    }

    public IObservable<IMessage> Messages
    {
        get {return _messages;}
    }

    private IObservable<IMessage> ListenToMessages()
    {
        return Observable.Create<IMessage>(o=>
        {
                return _scheduler.Schedule(recurse=>
                {
                    try
                    {           
                        var messages = GetMessages();
                        foreach (var msg in messages)
                        {
                            o.OnNext(msg);
                        }   
                        recurse();
                    }
                    catch (Exception ex)
                    {
                        o.OnError(ex);
                    }                   
                });
        });
    }

    private IEnumerable<IMessage> GetMessages()
    {
         //Do some work here that gets messages from a queue, 
         // file system, database or other system that cant push 
         // new data at us.
         // 
         //This may return an empty result when no new data is found.
    }
}

Konuları gerçekten sevmememin nedeni, genellikle geliştiricinin problem üzerinde gerçekten net bir tasarıma sahip olmamasıdır. Bir konuyu ele geçirin, oraya ve her yere dürtün ve sonra zayıf destek geliştiricisinin WTF'deki devam ettiğini tahmin etmesine izin verin. Create / Generate vb yöntemlerini kullandığınızda, sekans üzerindeki etkileri yerelleştiriyorsunuz. Hepsini tek bir yöntemde görebilir ve başka hiç kimsenin kötü bir yan etkiye neden olmadığını bilirsiniz. Bir konu alanı görürsem, şimdi kullanıldığı bir sınıftaki tüm yerleri aramaya gitmem gerekiyor. Bazı MFer bir kişiyi kamuya açıklarsa, tüm bahisler kapanır, bu dizinin nasıl kullanıldığını kim bilir! Async / Concurrency / Rx zordur. Yan etkilerin ve nedensellik programlamasının kafanızı daha da fazla döndürmesine izin vererek işi zorlaştırmanıza gerek yok.


10
Şu anda bu cevabı okuyorum ama Konu arayüzünü açığa çıkarmayı asla düşünmeyeceğimi belirtmem gerektiğini hissettim! Mühürlenmiş bir sınıf içinde IObservable <> uygulamasını sağlamak için kullanıyorum (IObservable <> 'i açığa çıkaran). Konu <> arayüzünü göstermenin neden Bad Thing ™ olacağını kesinlikle anlayabiliyorum
Anthony

Hey, kalın konuştuğum için özür dilerim ama kodunu gerçekten anlamadım. ListenToMessages () ve GetMessages () ne yapıyor ve geri dönüyor?
user10479

1
Kişisel projeniz için @jeromerg, bu iyi olabilir. Bununla birlikte, deneyimlerime göre geliştiriciler WPF, MVVM, GUI tasarımını test etme ve ardından Rx'e atma, işleri daha karmaşık hale getirebilir. Özellik olarak Davranış-Konusu modelini denedim. Bununla birlikte, standart INPC özelliklerini kullanırsak ve ardından bunu IObservable'a dönüştürmek için basit bir Uzantı yöntemi kullanırsak, diğerleri için çok daha kabul edilebilir olduğunu gördüm. Ek olarak, davranış konularınızla çalışmak için özel WPF bağlamalarına ihtiyacınız olacak. Artık zavallı ekibinizin WPF, MVVM, Rx ve yeni çerçevenizi de öğrenmesi gerekiyor.
Lee Campbell

2
@LeeCampbell, bunu kod örneğiniz açısından ifade etmek gerekirse, normal yol, MessageListener'ın sistem tarafından yapılandırılmasıdır (muhtemelen bir şekilde sınıf adını kaydedersiniz) ve sistemin daha sonra OnCreate () 'i çağıracağı ve OnGoodbye () ve mesajlar üretilirken message1 (), message2 () ve message3 () 'ü çağıracaktır. MessageX [123] bir konuda OnNext'i arayacak gibi görünüyor, ancak daha iyi bir yolu var mı?
James Moore

1
@JamesMoore, çünkü bunları somut örneklerle açıklamak çok daha kolay. Rx ve Subject kullanan bir Açık Kaynak Android uygulaması biliyorsanız, daha iyi bir yol sağlayıp sağlamayacağımı görmek için belki zaman bulabilirim. Bir kaide üzerinde durmanın ve Konular kötü demenin pek yararlı olmadığını anlıyorum. Ancak IntroToRx, RxCookbook ve ReactiveTrader gibi şeylerin hepsinin Rx'in nasıl kullanılacağına dair çeşitli düzeylerde örnekler verdiğini düşünüyorum.
Lee Campbell

38

Genel olarak kullanmaktan kaçınmalısınız Subject, ancak burada yaptığınız şey için oldukça iyi çalıştıklarını düşünüyorum. Rx eğitimlerinde "konulardan kaçınma" mesajıyla karşılaştığımda da benzer bir soru sordum .

Dave Sexton'dan (Rxx'den) alıntı yapmak için

"Konular, Rx'in durum bilgili bileşenleridir. Bir alan veya yerel değişken olarak olaya benzer bir gözlemlenebilir yaratmanız gerektiğinde kullanışlıdırlar."

Bunları Rx'e giriş noktası olarak kullanma eğilimindeyim. Yani 'bir şey oldu' demesi gereken bir kodum varsa (sizin gibi), a Subjectve call kullanırdım OnNext. Sonra bunu IObservablebaşkalarının abone olması için ifşa edin ( AsObservable()hiç kimsenin bir Konuya yayın yapıp işleri karıştırmayacağından emin olmak için konunuzda kullanabilirsiniz).

Bunu bir .NET olayı ve kullanımıyla da elde edebilirsiniz FromEventPattern, ancak olayı sadece IObservableyine de bir olaya dönüştürecek olursam, bir olay yerine bir olay yapmanın faydasını görmüyorum Subject( burada bir şey)

Ancak, bir abone oluyor oldukça kuvvetli kaçınmak gerektiğini IObservablebir ile Subject, yani bir geçemiyor Subjectiçine IObservable.Subscribeyöntemle.


Neden eyalete ihtiyacınız var? Cevabımın gösterdiği gibi, sorunu ayrı parçalara ayırırsanız, durumu gerçekten yönetmeniz gerekmez. Denekler olmamalıdır bu durumda kullanılacak.
casperOne

8
@casperOne Konu <T> veya olay (her ikisinin de arayacak şey koleksiyonları, gözlemciler veya olay işleyicileri vardır) dışında bir duruma ihtiyacınız yoktur. Bir olay eklemenin tek nedeni onu FromEventPattern ile sarmalamaksa, Konu kullanmayı tercih ederim. İstisna şemalarında sizin için önemli olabilecek bir değişiklik bir yana, Özneden bu şekilde kaçınmanın bir yararı görmüyorum. Yine, burada olayın Konuya tercih ettiği başka bir şey eksik olabilir. Durumdan bahsedilmesi, alıntının sadece bir parçasıydı ve onu içeride bırakmak daha iyi görünüyordu. Belki o kısım olmadan daha nettir?
Wilka

@casperOne - ama aynı zamanda sadece FromEventPattern ile sarmalamak için bir olay oluşturmamalısınız. Açıkçası bu korkunç bir fikir.
James Moore

3
Bu blog yazısında alıntımı daha derinlemesine açıkladım .
Dave Sexton

Bunları Rx'e giriş noktası olarak kullanma eğilimindeyim. Bu benim için kafadaki çiviyi vurdu. Çağrıldığında, reaktif işleme ardışık düzeninden geçmek istediğim olaylar üreten bir API'nin olduğu bir durumum var. FromEventPattern RxJava AFAICT'de bulunmadığından Konu benim için cevaptı.
scorpiodawg

31

Genellikle bir Konuyu yönetirken, aslında sadece zaten Rx'de bulunan özellikleri yeniden uyguluyorsunuz ve muhtemelen o kadar sağlam, basit ve genişletilebilir bir şekilde değilsiniz.

Bazı eşzamansız veri akışlarını Rx'e uyarlamaya çalıştığınızda (veya şu anda eşzamansız olmayan bir veri akışından eşzamansız bir veri akışı oluşturmaya), en yaygın durumlar genellikle şunlardır:

  • Veri kaynağı bir olaydır : Lee'nin dediği gibi, bu en basit durumdur: FromEvent'i kullanın ve pub'a gidin.

  • Veri kaynağı eşzamanlı bir işlemdendir ve sorgulamalı güncellemeler istiyorsunuz (örneğin, bir web hizmeti veya veritabanı çağrısı): Bu durumda Lee'nin önerilen yaklaşımını veya basit durumlarda, benzer bir şeyi kullanabilirsiniz Observable.Interval.Select(_ => <db fetch>). Kaynak verilerde hiçbir değişiklik olmadığında güncellemelerin yayınlanmasını önlemek için DistinctUntilChanged () kullanmak isteyebilirsiniz.

  • Veri kaynağı, geri aramanızı çağıran bir tür zaman uyumsuz api'dir: Bu durumda, gözlemcide OnNext / OnError / OnComplete'i çağırmak için geri aramanızı bağlamak için Observable.Create kullanın.

  • Veri kaynağı, yeni veriler mevcut olana kadar bloke eden bir çağrıdır (örneğin, bazı eşzamanlı soket okuma işlemleri): Bu durumda, Observable.Create komutunu soketten okuyan ve Observer'da yayımlayan zorunlu kodu sarmak için kullanabilirsiniz. veriler okunduğunda. Bu, Konu ile yaptığınız şeye benzer olabilir.

Observable.Create kullanmak ve bir Konu yöneten bir sınıf oluşturmak, getiri anahtar sözcüğünü kullanmakla IEnumerator uygulayan bütün bir sınıf oluşturmakla oldukça eşdeğerdir. Elbette, getiri kodu kadar temiz ve iyi bir vatandaş olmak için bir IEnumerator yazabilirsiniz, ancak hangisi daha iyi özetlenir ve daha zarif bir tasarım hisseder? Aynı şey Observable için de geçerlidir.

Observable.Create, tembel kurulum ve temiz sökme için size temiz bir model sunar. Bunu bir Konuyu sarmalayan bir sınıfla nasıl başarırsınız? Bir çeşit Başlatma yöntemine ihtiyacınız var ... onu ne zaman arayacağınızı nasıl bileceksiniz? Yoksa kimse dinlemese bile her zaman mı başlıyorsunuz? Ve işiniz bittiğinde, soketten okumayı / veritabanını sorgulamayı vb. Nasıl durduracaksınız? Bir tür Durdurma yöntemine sahip olmanız gerekir ve yalnızca abone olduğunuz IObservable'a değil, aynı zamanda Konuyu ilk başta oluşturan sınıfa da erişiminiz olmalıdır.

Observable.Create ile hepsi tek bir yerde toplandı. Observable.Create gövdesi, birisi abone olana kadar çalıştırılmaz, bu nedenle kimse abone olmazsa kaynağınızı asla kullanmazsınız. Ve Observable.Create, kaynağınızı / geri aramalarınızı vb. Temiz bir şekilde kapatabilen bir Disposable döndürür - bu, Observer abonelikten çıktığında çağrılır. Gözlemlenebilir'i oluşturmak için kullandığınız kaynakların yaşam süreleri, Gözlemlenebilir'in kendisinin yaşam süresine düzgün bir şekilde bağlıdır.


1
Observable.Create'in çok net açıklaması. Teşekkür ederim!
Evan Moran

1
Bir aracı nesnenin gözlemlenebilir olanı açığa çıkardığı bir özne kullandığım durumlar var (diyelim ki onun sadece değiştirilebilir bir özelliği). Farklı bileşenler, bu özelliğin ne zaman değiştiğini (bir yöntem çağrısıyla) ve bu yöntemin bir OnNext yaptığını söyleyen aracıyı çağırır. Tüketiciler abone olur. Bu durumda bir BehaviorSubject kullanacağımı düşünüyorum, bu uygun mu?
Frank Schwieterman

1
Bu duruma bağlıdır. İyi Rx tasarımı, sistemi eşzamansız / reaktif bir mimariye dönüştürme eğilimindedir. Küçük reaktif kod bileşenlerini, zorunlu tasarıma sahip bir sistemle temiz bir şekilde entegre etmek zor olabilir. Yara bandı çözümü, zorunlu eylemleri (işlev çağrıları, özellik kümeleri) gözlemlenebilir olaylara dönüştürmek için Konuları kullanmaktır. Sonra küçük reaktif kod cepleri elde edersiniz ve gerçek bir "aha!" an. Tasarımın veri akışını modellemek ve ona tepki vermek için değiştirilmesi genellikle daha iyi bir tasarım sağlar, ancak bu yaygın bir değişikliktir ve bir zihniyet değişikliği ve ekip katılımı gerektirir.
Niall Connaughton

1
Burada (Rx deneyimsiz olarak) şunu belirtmek isterim: Konular'ı kullanarak, gelişmiş bir zorunlu uygulama dahilinde Rx dünyasına girebilir ve onu yavaşça dönüştürebilirsiniz. Ayrıca ilk deneyimleri kazanmak için .... ve kesinlikle daha sonra kodunuzu baştan nasıl olması gerektiğine göre değiştirin (lol). Ama başlamak için konuları kullanmanın faydalı olabileceğini düşünüyorum.
Robetto

9

Alıntılanan blok metni hemen hemen neden kullanmamanız gerektiğini açıklar Subject<T>, ancak daha basit bir ifadeyle, gözlemci ve gözlemlenebilir işlevlerini birleştirirken, arada bir tür durum enjekte edersiniz (ister kapsüllü ister genişliyor olun).

Burada sorun yaşarsınız; bu sorumluluklar birbirinden ayrı ve farklı olmalıdır.

Bununla birlikte, özel durumunuzda, endişelerinizi daha küçük parçalara ayırmanızı tavsiye ederim.

İlk olarak, sıcak olan iş parçacığına sahipsiniz ve her zaman için bildirimleri yükseltecek sinyaller için donanımı izliyorsunuz. Bunu normal olarak nasıl yaparsınız? Etkinlikler . Öyleyse bununla başlayalım.

EventArgsEtkinliğinizin ateşleneceğini tanımlayalım .

// The event args that has the information.
public class BaseFrameEventArgs : EventArgs
{
    public BaseFrameEventArgs(IBaseFrame baseFrame)
    {
        // Validate parameters.
        if (baseFrame == null) throw new ArgumentNullException("IBaseFrame");

        // Set values.
        BaseFrame = baseFrame;
    }

    // Poor man's immutability.
    public IBaseFrame BaseFrame { get; private set; }
}

Şimdi, olayı başlatacak sınıf. Unutmayın, bu statik bir sınıf (her zaman donanım tamponunu izleyen bir iş parçacığına sahip olduğunuz için) veya buna abone olan istek üzerine çağırdığınız bir şey olabilir . Bunu uygun şekilde değiştirmeniz gerekecektir.

public class BaseFrameMonitor
{
    // You want to make this access thread safe
    public event EventHandler<BaseFrameEventArgs> HardwareEvent;

    public BaseFrameMonitor()
    {
        // Create/subscribe to your thread that
        // drains hardware signals.
    }
}

Artık bir olayı ortaya çıkaran bir sınıfınız var. Gözlemlenebilirler olaylarla iyi çalışır. O kadar ki içine olayların akışı dönüştürmek için birinci sınıf destek (bir olayın Çok sayıda fırınlama gibi bir olay akışının düşünün) var olduğunu IObservable<T>sen aracılığıyla, standart olay biçim kullanılıyorsa uygulamaları statik FromEventPatternyöntemine üzerine Observablesınıfa .

Olaylarınızın kaynağı ve FromEventPatternyöntemle, aşağıdaki gibi IObservable<EventPattern<BaseFrameEventArgs>>kolayca bir oluşturabiliriz ( EventPattern<TEventArgs>sınıf , bir .NET olayında göreceğiniz şeyi, özellikle de türetilen bir örneği EventArgsve göndereni temsil eden bir nesneyi içerir):

// The event source.
// Or you might not need this if your class is static and exposes
// the event as a static event.
var source = new BaseFrameMonitor();

// Create the observable.  It's going to be hot
// as the events are hot.
IObservable<EventPattern<BaseFrameEventArgs>> observable = Observable.
    FromEventPattern<BaseFrameEventArgs>(
        h => source.HardwareEvent += h,
        h => source.HardwareEvent -= h);

Elbette, bir projeksiyon oluşturmak için sınıfta uzantı yönteminiIObservable<IBaseFrame> kullanmak istiyorsunuz , ancak bu kolay (aynı LINQ'da yaptığınız gibi ve tüm bunları kullanımı kolay bir yöntemle özetleyebiliriz):SelectObservable

public IObservable<IBaseFrame> CreateHardwareObservable()
{
    // The event source.
    // Or you might not need this if your class is static and exposes
    // the event as a static event.
    var source = new BaseFrameMonitor();

    // Create the observable.  It's going to be hot
    // as the events are hot.
    IObservable<EventPattern<BaseFrameEventArgs>> observable = Observable.
        FromEventPattern<BaseFrameEventArgs>(
            h => source.HardwareEvent += h,
            h => source.HardwareEvent -= h);

    // Return the observable, but projected.
    return observable.Select(i => i.EventArgs.BaseFrame);
}

7
Yanıtınız için teşekkür ederim @casperOne, bu benim ilk yaklaşımımdı ancak sırf Rx ile paketleyebilmek için bir olay eklemek "yanlış" geldi. Şu anda temsilciler kullanıyorum (ve evet, bunun tam olarak bir olayın bu olduğunu biliyorum!) Yapılandırmayı yüklemek ve kaydetmek için kullanılan koda uymak için, bu bileşen boru hatlarını yeniden oluşturabilmeli ve delege sistemi bana en çok esneklik. Rx şu anda bu alanda bana bir baş ağrısı veriyor, ancak çerçevedeki diğer her şeyin gücü, yapılandırma problemini çözmeyi çok değerli hale getiriyor.
Anthony

@Anthony Kod örneğini çalıştırabilirseniz harika, ama yorumladığım gibi, bu hiç mantıklı değil. "Yanlış" hissetmeye gelince, olayları mantıksal parçalara ayırmanın neden "yanlış" göründüğünü bilmiyorum, ancak orijinal gönderinizde bunu nasıl en iyi şekilde çevireceğinizi belirtmek için yeterince ayrıntı vermediniz, IObservable<T>" re şu anda bu bilgi ile sinyal verilir.
casperOne

@casperOne Size göre, Konuların kullanımı bir Mesaj Veriyolu / Etkinlik Toplayıcı için uygun olur mu?
kitsune

1
@kitsune Hayır, neden yaptıklarını anlamıyorum. "Optimizasyon" u düşünüyorsanız, sorunun bu olup olmadığını sormanız gerekir, sorunun nedeni olarak Rx'i ölçtünüz mü?
casperOne

2
Burada casperOne'a, endişeleri bölmenin iyi bir fikir olduğu konusunda hemfikirim. Donanımdan Olaya Rx modeline giderseniz, hata anlamını kaybedeceğinizi belirtmek isterim. Kaybolan bağlantılar veya oturumlar vb. Tüketiciye maruz kalmayacaktır. Artık tüketici yeniden denemek, bağlantıyı kesmek, başka bir diziye abone olmak veya başka bir şey isteyip istemediğine karar veremez.
Lee Campbell

0

Konuların genel bir arayüz için kullanılmasının iyi olmadığını genellemek kötüdür. Kesinlikle doğru olsa da, reaktif bir programlama yaklaşımının görünmesi gereken yol bu değil, kesinlikle klasik kodunuz için iyi bir geliştirme / yeniden düzenleme seçeneğidir.

Genel küme erişimcisi olan normal bir mülkünüz varsa ve değişiklikleri bildirmek istiyorsanız, onu bir BehaviorSubject ile değiştirmeye karşı hiçbir şey söylemez. INPC veya diğer etkinlikler o kadar temiz değil ve kişisel olarak beni yıpratıyor. Bu amaçla, normal özellikler yerine genel özellikler olarak BehaviorSubjects kullanabilir ve INPC veya diğer olayları atabilirsiniz ve kullanmalısınız.

Ayrıca Konu arayüzü, arayüzünüzün kullanıcılarını mülklerinizin işlevselliği hakkında daha bilinçli hale getirir ve sadece değeri almak yerine abone olma olasılıklarını artırır.

Başkalarının bir mülkteki değişiklikleri dinlemesini / bunlara abone olmasını istiyorsanız kullanmak en iyisidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.