Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Time Travel" #23

Open
bryphe opened this issue Feb 9, 2019 · 4 comments
Open

"Time Travel" #23

bryphe opened this issue Feb 9, 2019 · 4 comments

Comments

@bryphe
Copy link
Contributor

bryphe commented Feb 9, 2019

Reading through #14 made me think about this - eventually, for Revery and beyond - I'd like to be able to have a 'time travel' development experience. Like Redux, but maybe without necessitating keeping a global app state.

I was curious if it'd be possible to hold on to past rendered trees, and call executeHostViewUpdates on old versions in order to rewind the tree to an earlier state.

The 'developer experience' I'm thinking about would be a sort of slider where you could rewind to any particular point in time, and see the UI in that 'rewound' state. I'm interested in this especially in the context of debugging animations (ie, frames where we hit a discontinuity). Implementation-wise, in debug mode, we'd record 'snapshots' of the rendered tree and hold them in memory for some amount of limit.

One challenge I see is that I'm not sure how 'effects' would play into this...

The nice thing about this developer experience - if it works with Brisk - is that this DX would apply to any brisk-reconciler powered app - which would be amazing 😄

I love the idea of this 'time travel' debugging experience, but it's always been finicky to set up and use - but I hypothesize the functional nature of Reason/Brisk would at least bring this closer to being a usable reality.

Would this be doable as-is with the current reconciler infrastruture, @wokalski ? Or do you see any deltas?

@wokalski
Copy link
Member

wokalski commented Feb 9, 2019

effects are notoriously hard in such cases. I'm not a big fan of time travel (I consider it kind of a gimmick) because it's really hard to implement right. That said, I'd be open to accept/brainstorm/even implement a solution to this if we can come up with a sensible non-leaky abstraction. My immediate thought is that one should try to implement it in the user space and we could back port it to the reconciler when it's satisfying. You could for instance record insertNode/deleteNode operations and apply inverse but practically it's extremely hard because tracking all side effects is almost impossible. Let's say that not only do I add a view but also make it red. Tracking insertNode/deleteNode is easy, but tracking all "side effects" and allowing unrolling them is extremely hard. Also, it's very backend specific.

And lastly; what's time travel without runtime introspection? It's just a screencast. Implementing runtime introspection together with time travel seems like an interesting idea... for a PhD 😃.

@bryphe
Copy link
Contributor Author

bryphe commented Feb 9, 2019

I'm not a big fan of time travel (I consider it kind of a gimmick)

It's definitely gimmicky in all the environments I've tried it in. But I think there's a potential for a unique trifecta to improve development:

  • Time-travel (state as just axis)
  • Live-code reloading (at least, for pure functions...)
  • ...and runtime introspection (like you called out 😄 ). But this could be something lighter weight - ie, a model like LightTable - where, we use some PPX transform to augment key places of the code with a 'reporter' that is surfaced in the IDE.

This trifecta is what I believe is enabled by the functional model for UI (and games), and where I believe a key value proposition is in this development environment vs incumbents. It's especially suited to real-time apps which are notoriously hard to debug transient issues, but would also be useful for less-real-time apps IMO

My immediate thought is that one should try to implement it in the user space and we could back port it to the reconciler when it's satisfying.

Sounds reasonable. I think there are different layers of abstraction for this - an alternate is to time-travel the 'state' of the app (the redux-style time-travel) - this is what I might start prototyping. Essentially it'd be 'above' the reconciler level and wouldn't track internal states, but I think this is a reasonable starting point - we can keep iterating from there.

Thanks @rauanmayemir and @wokalski for the thoughts!

@wokalski
Copy link
Member

wokalski commented Feb 9, 2019

@bryphe I agree. If we have runtime introspection and working live code reloading it becomes ground breaking. It has to be general enough to be able to freely use it without some weird restriction but cannot be "general enough to break". What I mean by that, is that solving this truly in the general case would probably require a fair amount of compiler hacking. Maybe we'll get there one day but for now we have to come up with some constraints so that the solution is useful and solid. Also, as an intermediate step for this we should take a look at live code reloading.

@wokalski
Copy link
Member

wokalski commented Feb 9, 2019

I'm not a big fan of time travel (I consider it kind of a gimmick)

btw, I take it back. I wanted to say

I'm not a big fan of existing time travel-like solutions. They are gimmicky. However, if you make it really good, it's easily a major DX improvement. In the reality where many people don't write tests (it's also hard with many UI apps) this can save a lot of time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants