These are chat archives for jdubray/sam

30th
Oct 2017
Jean-Jacques Dubray
@jdubray
Oct 30 2017 08:51

Stencil components update when props or state on a component change. For performance and simplicity, Stencil only compares references for changes, and will not re-render when data inside of an array or object changes.

I was wondering what people think about that change detection mechanism.

Victor Noël
@victornoel
Oct 30 2017 09:48
Funny how some of the patterns made explicit by SAM are rediscovered when using stuffs like ngrx where they are implicit:
https://medium.com/@m3po22/stop-using-ngrx-effects-for-that-a6ccfe186399
I'm thinking in particular of "Duplicate/derived state" which is actually the natural separation between model and state in SAM.
Paolo Furini
@pfurini
Oct 30 2017 10:29
That's one of the main reasons redux/ngrx scared me away from the beginning
It felt fundamentally wrong to me
Jean-Jacques Dubray
@jdubray
Oct 30 2017 11:16
@victornoel thank you for sharing, for me the problem is finding all these recipes without looking at the foundation, I'd argue that you are likely to get 50% right at best.
Note that SAM provides an elegant solution to cancellation since it decouples the actions from the mutations. (SAM-SAFE)
Do you feel the terrible coupling?
@Effect getUsers$ = this.actions$
  .ofType('GET_USERS', 'CANCEL_GET_USERS')
  .withLatestFrom(this.userSelectors.needUsers$)
  .filter(([action, needUsers]) => needUsers)
  .map(([action, needUsers]) => action)
  .switchMap(action => action.type === 'CANCEL_GET_USERS' ? 
    Observable.of() :
    this.getUsers()
      .map(users => ({type: 'RECEIVE_USERS', users}))
  )
Victor Noël
@victornoel
Oct 30 2017 11:38
actually the code you are quoting is what shouldn't be done :)
I suppose that's what we hould look at:
public requireUsers$ = this.userSelectors.needUsers$
  .filter(needUsers => needUsers)
  .do(() => this.store.dispatch({type: 'GET_USERS'}))
  .switchMap(() => this.getUsers())
  .do(users => this.store.dispatch({type: 'RECEIVE_USERS', users}))
  .finally(() => this.store.dispatch({type: 'CANCEL_GET_USERS'}))
.share();`
Victor Noël
@victornoel
Oct 30 2017 11:45
(but I agree with the premises)
Jean-Jacques Dubray
@jdubray
Oct 30 2017 11:50
Still, there should not be a "cancel_users", once you keep track of "Steps" a cancel action is simply presenting a proposal that advances the step such that any other proposal for that set is cancelled, whatever it is, no one should know that you need to "cancel_get_users"
I was thinking this past few weeks about what Dr. Lamport was saying, he noticed that "counters are very important" to programming, he said in one of his videos that he was puzzled as to why.
yesterday, I think I found the reason, I looked at the STAR quadrant and asked what is a counter? is it missing from the quadrant? or does it belong to one of the categories? if yes, which one?
Can you guess the answer?
Victor Noël
@victornoel
Oct 30 2017 12:17
I would have said the counter is in the model but… :)
or in state if it's derived from the model
Jean-Jacques Dubray
@jdubray
Oct 30 2017 13:54
My thoughts were that it is a relatioship, a temporal relationship like PK / FK (which, not surprisingly is also (often) using a counter)! When my value is 1 and your value is 2, it expresses a relationship. What do you think?
Victor Noël
@victornoel
Oct 30 2017 14:24
yes, I actually thought that if there was a tricky anwer it was "relationship" but I didn't dare say it because I wasn't clear why it was the correct answer :P
it's relationships between the things that are counted
and by the way, it is interesting that usually in event-oriented systems, there is no counters (instead of saying "there is N products because we counted every time we created one" we will say "because we have N product created events, thus we can infer that there is N products"
Janne Siera
@jannesiera
Oct 30 2017 14:44

.filter(needUsers => needUsers)

Could someone explain to me what this does?

Fred Daoud
@foxdonut
Oct 30 2017 14:45
@jannesiera I'm guessing it filters out null or undefined values
probably .filter(needUser => needUser) (instead of plural) is better naming. Keeps "truthy" values.
Victor Noël
@victornoel
Oct 30 2017 14:46
I'm, I would have thought it was a boolean
already
Janne Siera
@jannesiera
Oct 30 2017 14:47
Ah, right
that's the kind of stuff I add comments to
Victor Noël
@victornoel
Oct 30 2017 14:47
I thought it is meant to be true if the user were not already retrieved
I suppose that's not very important in the article :)
Janne Siera
@jannesiera
Oct 30 2017 14:48
mhm
seems like that's how you do it with functional programming if you don't have 'if' statements?
makes sense, but I wouldn't exactly call it intuitive either
actually the question of state vs derived state I find quite interesting
Janne Siera
@jannesiera
Oct 30 2017 14:58

Stencil components update when props or state on a component change. For performance and simplicity, Stencil only compares references for changes, and will not re-render when data inside of an array or object changes.

I was wondering what people think about that change detection mechanism.

Reactive render on state/props change is great. I'm wondering what they recommend of doing when data in an array changes though. Seems very weird to only have referential checks. If my component displays a list of todos, and one of them changes, it won't re-render? Wth?

Paolo Furini
@pfurini
Oct 30 2017 16:26

I'm wondering what they recommend of doing when data in an array changes though.

That's an old recurring problem coming up again and again.. when I was following the work of Rob Eisenberg on Aurelia (former author of Angular 2), there were debates on shallow or deep change detection. In the early days of the binding engine, only shallow change tracking was done, so to react on array changes you had to do smt like this.myObservedArray = newArray, otherwise the change were not detected at all

Victor Noël
@victornoel
Oct 30 2017 16:27
Usually the idea is to use immutable datastructure in this context: if you want to modify an array, you produce a new array. It is highly coherent with the redux approach of having an immutable datastructure for the store.
Paolo Furini
@pfurini
Oct 30 2017 16:32
or do the old slice(0) trick.. JS browser engines are simply NOT developed with deep cloning in mind. I'd NEVER do deep cloning of large arrays/nested data structures, if that's not really needed. a shallow copy is thousand of times faster, and probably will not hang my customer's browser
@jannesiera regarding deep watch of nested data structures, just to react on changes, is simply "evil".. it has always been the biggest bottleneck of data-binding libraries in frameworks like Aurelia, and other classic MVC oriented ones. If I had to choose one technique, I'll always go for the simplest solution, and a referential check is the more efficient one
zevenbergm
@zevenbergm
Oct 30 2017 19:21
Hi all, any thoughts on how to implement an editor like https://github.com/yabwe/medium-editor/blob/master/dist/js/medium-editor.js using the SAM pattern (vanilla js)? In my opinion, it's a little overkill to re-render the whole editor after a state change... do you guys have any ideas?
Paolo Furini
@pfurini
Oct 30 2017 20:16
@zevenbergm if you treat the editor as a black box component (much like a big and fat input text), then you should bother only with the actual content of the control.. so your model will contain only a string with the content of the editor, and that's it
Paolo Furini
@pfurini
Oct 30 2017 20:22
but personally (after having read the docs briefly) I do NOT like this control.. you'll have more luck if you find an editor that's more oriented toward a web component architecture, with clear separation between DOM manipulation and exposed API. This medium-editor is an old-school javascript control, ala JQuery style, even if it's not using it underneath
zevenbergm
@zevenbergm
Oct 30 2017 20:50
@pfurini Thanks! Do you have any suggestions for a modern text editor?