Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rx Guideline 6.5: Subscribe implementations should not throw #278

Closed
Treora opened this issue May 26, 2013 · 2 comments
Closed

Rx Guideline 6.5: Subscribe implementations should not throw #278

Treora opened this issue May 26, 2013 · 2 comments

Comments

@Treora
Copy link
Contributor

Treora commented May 26, 2013

Some flavours of subscribe seem to ignore this guideline in the case that the given final Object onNext is null, for example: (Observable.java:366)

public Subscription subscribe(final Object onNext, final Object onError) {
    // lookup and memoize onNext
    if (onNext == null) {
        throw new RuntimeException("onNext must be implemented");
    }
    final FuncN onNextFunction = Functions.from(onNext);

This behaviour could be deliberately chosen, but then I wonder why other flavours of subscribe (those where an Action1<T> is passed) do neatly follow this guideline and only throw when onNext is actually being called: (Observable.java:428)

        public void onNext(T args) {
            if (onNext == null) {
                throw new RuntimeException("onNext must be implemented");
            }
            onNext.call(args);
        }

Moreover, I would actually expect both cases to call onError instead of throwing an Exception, though this could perhaps be defended, and for sure you would want to fix issue #198 first. It seems strange to me however that there is this difference in behaviour between passing an Object and passing an Action1 for onNext, or am I missing something?

@benjchristensen
Copy link
Member

The idea is that if calling a method with specific arguments for handlers that null should not be passed in and that this is considered a programmer error, thus throwing an exception rather than invoking onError. In short, this is argument validation.

Any difference between Action1 or Object being passed in is a bug, they should behave the same (and we're actively working on getting rid of the Object overloads while still supporting the various languages).

While glancing through the code I see for example what appears to be the result of refactoring placing the null check inside the onNext call instead of at the top of the method as an argument validation: https://github.com/Netflix/RxJava/blob/master/rxjava-core/src/main/java/rx/Observable.java#L428

I consider that incorrect, as these are basically intended to be checking that the handlers passed in are valid and thus should be done before any actual Observable logic is invoked.

@Treora
Copy link
Contributor Author

Treora commented May 31, 2013

Okay, it's clarifying to hear the incongruity between Objects and Action1's is an error.

Whether they should throw an exception or call onError is defensible in favor of either, and perhaps not very important. I would actually choose the latter as it allows to handle all errors in one place and makes calling subscribe a bit simpler (try&catch never needed), but having to do a null check before calling subscribe sounds tolerable.
If both onNext and onError are null, then an exception will still be thrown anyway (if #198 gets fixed).

rickbw pushed a commit to rickbw/RxJava that referenced this issue Jan 9, 2014
As brought up in ReactiveX#278 there were inconsistencies in how arguments were being validated on subscribe methods.

All arguments to subscribe are now validated correctly at the beginning of method invocation and IllegalArgumentException thrown if null arguments are injected.

According to Rx Guideline 6.5 a null argument is considered "a catastrophic error occurs that should bring down the whole program anyway" and thus we immediately throw. A null argument should be caught immediately in development and has nothing to do with subscribe invocation which is what guideline 6.5 is talking about (since a null Observer can't have onError called on it anyways).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants