4 ms·
There are several benefits to using enums as opposed to closures: 1. All your actions are in one place. Figuring out what can happen as a result of a series of
by Skinney 5y ago
There are several benefits to using enums as opposed to closures:
1. All your actions are in one place. Figuring out what can happen as a result of a series of user interactions can be done without navigating through a component hierarchy.
2. The history of a user interaction is simple to serialize. In case of error, you can dump the user interaction history for this session (just a list of enum values, right?) to disk. This can then be submitted in bug reports for easy re-production of an issue.
3. It's simple(r) to create a time-travelling debugger that can move backwards and forwards in time, since it can simply re-play the series of messages to a specific point.
4. Since you've seperated state changes from the UI, writing unit tests that ensures that a series of user interactions results in a specific state is pretty easy. You just send in the enum values representing a specific use interaction then check what state you've ended up with.
- verdagon 5y ago> 1. All your actions are in one place. Figuring out what can happen as a result of a series of user interactions can be done without navigating through a component hierarchy. I'd imagine it would be easier to just call a method on whatever we want to update, instead of lowering all our methods into enums. Why wouldn't we do that instead? Also, serializing usually isn't enough to get the benefits you describe. You need true determinism for that, and that's very difficult to achieve. If you ever e.g. query the current date without recording it you've just introduced nondeterminism. If we could really achieve deterministic replayability easily, then I might be okay with the drawback of turning methods into enums.
- Skinney 5y ago> I'd imagine it would be easier to just call a method on whatever we want to update, instead of lowering all our methods into enums. Why wouldn't we do that instead? Easier how? The difference in lines of code is minimal. It's not going to make any meaningful difference in how much time you spend on crafting a solution. > Also, serializing usually isn't enough to get the benefits you describe. You need true determinism for that, and that's very difficult to achieve. If you ever e.g. query the current date without recording it you've just introduced nondeterminism. It requires some thought, but it isn't terribly difficult. Most user interactions with a gui doesn't require a side effect, and those that do can usually be written in a way that it gets represented in the enum. Even when nondeterminism creeps in, it rarely cancels out all of the benefits of having a history of user interaction. Perfect nedn't be the enemy of good.
- verdagon 5y agoI'm afraid that when dealing with nondeterminism, you *do* need to be perfect. If even one call is nondeterministic, you've corrupted your entire replay. This is a common challenge with e.g. RTS games, and it means we have to very carefully discover and avoid nondeterministic functions. For example, did you know that C#'s string's hash code calculation is nondeterministic across runs? The same can be said for any floating point calculations, iterating Rust's/Go's default hash maps, etc. Also, IME most interactions with GUI do have side effects, GUI apps tend to be very stateful.
- Skinney 5y ago> For example, did you know that C#'s string's hash code calculation is nondeterministic across runs? ... iterating Rust's/Go's default hash maps, etc. I do, but I also know that in Java, C#, Rust and Go it's well documented that you should not rely on the iteration order of the values in a hashmap or hash-based collection, which (at least in Go) is one of the reasons hash-iteration order is randomized across runs. If a bug is caused by this kind of nondeterminism, you're likely to catch the bug by replaying the history multiple times. In other words, if the history isn't perfect due to nondeterminism, the history is still useful in tracking down bugs because that nondetermism will be revealed over multiple replays.