15

So I keep reading everywhere that use of Subject<T> is "bad" - and I kind of agree with the reasoning.

However, I am trying to think of the best way to avoid using it and have an example.

Currently I have an abstract class for my persisted configuration classes that has a protected Save() method on it which is called whenever changing a property should persist the class. This message pumps a message onto a Subject<T> which is exposed through IObservable<T> interface which the serialisation services listens to and serialises the class. This seemed the most obvious, simple and quickest way to implement this at the time.

So what would be the RX way to do this without using a Subject? Would I instead expose an event and use Observable.FromEventPattern() to subscribe to it? - as this seems a more complex way to go about it.

Todd Menier
  • 37,557
  • 17
  • 150
  • 173
Cheetah
  • 13,785
  • 31
  • 106
  • 190
  • 1
    As a matter of interest, can you link to some of those arguments? I don't think I know enough Rx to answer the question, but this is the first I've heard that you should try to avoid using `Subject`. – anton.burger Feb 17 '14 at 08:47
  • 2
    @shambulator Check this link for a quick explanation: http://introtorx.com/Content/v1.0.10621.0/18_UsageGuidelines.html – jnovo Feb 17 '14 at 09:31

2 Answers2

18

It's not so much that the use of Subject<T> is bad - there has to be some way of "entering the monad" - that's the academic way of saying "get an IObservable<T>". You need to start somewhere.

The problem with Subject<T> arises more when it's used from a subscription instead of chaining existing observables together. Subjects should just exist at the edges of your Rx machinery.

If none of the provided entry points (e.g. FromEvent, FromEventPattern, FromAsync, Return, ToObservable() and so on) work for you then using Subject<T> is perfectly valid. And there's no need to add extra complexity just to facilitate using one of the above - most of them use subjects or subject-like constructs under the covers anyway.

In your case, sounds like Subject<T> is just fine. You might what to look at exposing it via AsObservable() in order to hide the implementation details.

James World
  • 29,019
  • 9
  • 86
  • 120
3

A simple way to enter the observable is via an Action

private Action<ObservableArgs> _action;

Create the observable

public IObservable<ObservableArgs> GetObservable()
{
    return Observable.FromEvent<ObservableArgs>>(
                ev => _action += ev, 
                ev => _action -= ev);
}

Then add to the observable using

public void OnNext(ObservableArgs args)
{
    _action?.Invoke(args);
}
benthemos
  • 195
  • 6
  • 2
    Upvoted for providing a direct answer to the question, and for showing why you *shouldn't* avoid the use of `Subject`s. Because otherwise you end up with needlessly complex code, that confuses everyone about its intention, probably including the author themself a couple of months later. – Theodor Zoulias Dec 03 '20 at 00:43