I don't have a great understanding of the reasoning behind Flux architecture. I understand that it is nice to have all of the state in one place. I don't have a great understanding of other things though.

My question here is about where, exactly, the mutation logic should be. I get the impression that Flux architecture wants you to do have all of the mutation logic in one place - the store - because it gives you a good separation of concerns. Ie. when you want to know where mutation logic is, you know where to look.

But I find that it is nice to have classes and use instance methods to deal with state change. I think user.computeAndSetKarma() looks a lot nicer than storeHelper.computeAndSetKarmaForUser(user). Robert Martin talks about this in his book Clean Code:

A function with two arguments is harder to understand than a monadic
function. For example, writeField(name) is easier to understand than
writeField(output-Stream, name). Though the meaning of both is
clear, the first glides past the eye, easily depositing its meaning.
The second requires a short pause until we learn to ignore the first
parameter. And that, of course, eventually results in problems because
we should never ignore any part of code. The parts we ignore are where
the bugs will hide.

...

Dyads aren’t evil, and you will certainly have to write them. However,
you should be aware that they come at a cost and should take advantage
of what mechanims may be available to you to convert them into monads.
For example, you might make the writeField method a member of
outputStream so that you can say outputStream.writeField(name). Or
you might make the outputStream a member variable of the current class
so that you don’t have to pass it. Or you might extract a new class
like FieldWriter that takes the outputStream in its constructor and
has a write method.

You could perform the logic inside of the mutation, or you could just call user.computeAndSetNewKarma() inside of the mutation, delegating the logic to the users instance method. The latter seems preferable to me, but I'm not sure if this violates convention, and I'm not sure if I am thinking about it properly.

As written, both of your approaches mutate the object in place, and so neither approach follows Vue's reactivity rules, right? (I haven't done Vue, but I have done React, and it looks like Vue follows a similar approach of discouraging in-place mutations.)
– Josh KelleyJun 15 '18 at 21:37

@JoshKelley Vue(x) does let you mutate the object in place while maintaining the reactivity. There are a few caveats to this though, and that's what the link was discussing. Eg. if you have let person = { name: 'John Doe' };, you can't do person.age = 30, you'd have to either initialize person.age = null upfront or do Vue.set(person, 'age', 30) if you want person to continue to be reactive.
– Adam ZernerJun 16 '18 at 16:19