dontlaugh / rocket-yew-starter-pack

Example boilerplate for websites in pure Rust
MIT License
85 stars 11 forks source link

Why no type safety between client and server? #10

Open apatil opened 5 years ago

apatil commented 5 years ago

Hi @anxiousmodernman, thanks for putting this together, this is very useful for people like me who are curious about full-stack web apps in Rust. I was just wondering why you haven't had the typechecker check your client's API consumption at compile time.

For example, the client side Entry (https://github.com/anxiousmodernman/rocket-yew-starter-pack/blob/master/ui/src/lib.rs#L45) seems to be a duplicate of the server side Task (https://github.com/anxiousmodernman/rocket-yew-starter-pack/blob/master/server/src/main.rs#L57).

The compiler doesn't know that Task should be the same as Server, or that /tasks is statically guaranteed to return a list of Tasks.

Would it make sense to factor out a subset of server into a common package that defines the routes and their request and response types, and add it to both client's and server's cargo.toml?

anxiousmodernman commented 5 years ago

Thank you for the issue! You are correct, this is code duplication. And it could be solved by the method you describe: extracting a 3rd crate of pure data types. Some sort of protocol crate that both server and ui depend on.

Way back, I actually started down the road of having a unified build driven by cargo workspaces, but I ripped it out because I couldn't figure out how to make the cargo web build work (for the ui) in the same invocation as the regular cargo build. https://github.com/anxiousmodernman/rocket-yew-starter-pack/commit/c67cda4358556efce8d9ed387c9b9c503b5517c5

I haven't revisited the idea since, because Rocket will give us runtime checking of the shape of the JSON. Not as good as compile-time, but still robust. And, iirc, the name Entry was preserved from the original port of the yew/examples directory. But I'm not pulling in changes from that example, and really my strategy has been to occasionally build this thing and if it fails try to get it working. So at this point unifying the names makes sense.

I'd be interested in a PR that uses a `path = "../common" (or similar) in Cargo.toml to extract the few types that we actually need to share.

FWIW, now that Rocket 0.4 is out, I need to revisit this project anyway.

apatil commented 5 years ago

@anxiousmodernman thanks for getting back to me. I would love to offer to submit a PR but realistically, my track record shows that I won't get to it anytime soon. :)

IMO the delta between compile-time and runtime checking of API usage correctness increases with the size of the project. I've been involved in one multi-year effort with multiple developers and dozens of API endpoints, and it was hard to be confident that any change to the API wouldn't break something. Compile-time checking of API usage would have been a huge help, and I've found it to be a surprisingly uncommon feature even in safety-forward languages like Rust.

gjolund commented 4 years ago

This thread pretty much describes my interest in rust as a full stack language.

Has there been any additional development on this issue in the repo or other libraries you are aware of?