DISCUSSION 1: ObserverSpy API - Methods vs getters
See original GitHub issueFollowing #12 by the amazing @ThomasBurleson we had a discussion and realized this PR could be separated into several PRs, and before that we need to discuss them.
This discussion is about the possible changes to the ObserverSpy API to make it more “getters” focused.
The suggested API changes to ObserverSpy
-
private _state: ObserverState<T> = {
values: [],
errorValue: undefined,
called: {
next: false,
error: false,
complete: false,
},
};
get state(): ObserverState<T> {
return {
...this._state,
values: [...this._state.values],
};
}
get values(): T[] {
return this._state.values;
}
get hasValues(): boolean {
return this._state.values.length > 0;
}
get isComplete(): boolean {
return this._state.called.complete;
}
readFirst(): T | undefined {
return this.hasValues ? this._state.values[0] : undefined;
}
readLast(): T | undefined {
return this.hasValues ? this._state.values[this._state.values.length - 1] : undefined;
}
The upsides (IMO) -
-
Read only values (that’s a good idea to implement regardless of the api)
-
Reduces the need to call a method which might make it shorter and more straightforward to read the state of the spy
-
(probably more that I’m missing…)
The downsides (IMO) -
State
object usage might make the expectation longer and requires remembering more of api. For example:
expect(observerSpy.state.called.next).toBeTruthy();
// VS
expect(observerSpy.receivedNext()).toBeTruthy();
// AND
expect(observerSpy.getError()).toBe('OMG AN ERROR!');
// VS
expect(observerSpy.state.errorValue).toBe('OMG AN ERROR!');
-
I prefer to reduce the nesting, so If we’ll decide to go for getters, I would suggest flattening the api of “state” to exposed from the root, something like
observerSpy.errorValue
etc) -
Intuitively (for me), methods feel (at first glance) more “Read only” than properties, but maybe it’s just me.
-
It’s true that with TypeScript you’ll see a compile time error if you try to assign
values
some other value, but with JS you’ll get a run time error which is no fun. It might be tempting for developers in some scenarios to try and doobserverSpy.values[2] = 'some other value';
, but then again, maybe I’m wrong here.
Because this is a BREAKING_CHANGE, I wanted to get as much opinions as possible about it, before we decide whether we should break it into it’s own PR.
So @ThomasBurleson @katharinakoal @edbzn @burkybang @yjaaidi (and anyone else who’d like to chime in) -
WHAT ARE YOUR THOUGHTS?
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (5 by maintainers)
Top GitHub Comments
Hey everyone! +1 for flat in favor of nested.
Concerning properties vs methods, I like how properties are shorter… but even if we ignore extensibility by adding parameters, the problem we get is the inconsistency between using props for
values
and methods for things likegetValueAt()
.I think that the most important thing here is consistency. For instance,
hasReceivedNext() & getValues()
vsreceivedNext() & values()
.I generally prefer the latest as it’s shorted but we have to make sure that we’ll never use any properties to be the least surprising.
Hey Guys!