Closed bartelink closed 2 months ago
I'm okay with this, it's not my personal preference, but then neither is a type with members :). Given that we're already using that, it does make some sense to lean more into it. Consistency is more important than preference.
Thanks for reviewing - I can imagine it's a hard sell in the small (though I do think type
s with actual methods are very underrated!)
Note other thing that should be taken from the top in an article series, given I had and/or made the time to do such a thing is that the Service's resolve
function cna be fulfilled by a relatively simple wiring to the MemoryStore like in https://github.com/jet/equinox/blob/8c257d4463530149f90003eacc77586f3a176234/samples/Tutorial/Favorites.fsx
Then to test with a real store, you just hook the same Service to a concrete store as in https://github.com/jet/equinox/blob/8c257d4463530149f90003eacc77586f3a176234/samples/Tutorial/Todo.fsx
For testing cross-category reactions, I have tests that
Those tests are then driven by FsCheck varying sequences or mixes of actions
That same test suite can then also be run against a concrete store with it's concrete reactions channel (i.e. for Cosmos, a ChangeFeedProcessor pulling from the container, for ESDB, a subscription to an ephemeral instance wired to a volatile disk, for MessageDb, a real reader connected to the table)
What a Service might do only becomes properly interesting once the methods don't all return Async<unit>
though, which is harder to explain
There's a sample that goes quite a bit down this road in https://github.com/jet/dotnet-templates/tree/master/propulsion-hotel
Removes usage of the Command pattern - while most event sourcing 101s use it as the goto example (and Equinox itself is, as the initial example showed, perfectly fine with the pattern), over time I've found that trying to use that as the dominant pattern constrains one's thinking for some of the following reasons:
Async
/Task
I added some notes and examples in the docs over time covering some of the reasoning: https://github.com/jet/equinox/blob/master/DOCUMENTATION.md#commands-interpret-signature (though sadly I've yet to get to the point where I write a short article with a proper example and tighter example).
Triggered by https://medium.com/@tonyx1/equinox-vs-sharpino-comparing-the-counter-example-0e2bd6e9bbf2 - the counter example (as toy examples probably will) has lots of stuff that does not represent a good example to work from cc @voronoipotato (Unfortunately the ubiquitous Todo one is not that much better) cc @tonyx
Apologies to @voronoipotato - I've probably destroyed the simplicity of the original, but I do feel strongly that the Command pattern, while it does fit quite well for simple cases (and hence is useful in enabling someone familiar with that way of doing the sample to map to Equinox and/or F#), it tends to IMO also paint people into a corner in a way that the notion of using
Decider.Transact
to apply a 'decision function' to the State of the Decider doesnt.I won't merge it immediately in case either of you have the time or interest to review and/or suggest ways of doing it that make for a better example