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

Simplify the whole Model serialization story #2

Merged
merged 5 commits into from
Mar 21, 2021

Conversation

uint
Copy link
Contributor

@uint uint commented Mar 13, 2021

I initially called this an overhaul, but it's rather simple.

Introducing enum_dispatch helped get rid of some code, make things DRYer, resolve the issues you mentioned and probably make this faster by avoiding dynamic dispatch.

@uint
Copy link
Contributor Author

uint commented Mar 14, 2021

I should mention there's one downside to this approach: the list of possible models is still closed. A user of the library won't be able to extend it with their own implementors. Does that matter?

@codecov-io
Copy link

Codecov Report

Merging #2 (5d277a3) into main (08fb1ae) will increase coverage by 2.11%.
The diff coverage is 50.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main       #2      +/-   ##
==========================================
+ Coverage   78.87%   80.98%   +2.11%     
==========================================
  Files          17       17              
  Lines        1704     1604     -100     
==========================================
- Hits         1344     1299      -45     
+ Misses        360      305      -55     
Impacted Files Coverage Δ
src/models/exclusive_gateway.rs 68.62% <ø> (+4.99%) ⬆️
src/models/gate.rs 64.36% <ø> (+2.82%) ⬆️
src/models/generator.rs 69.62% <ø> (-0.26%) ⬇️
src/models/load_balancer.rs 71.18% <ø> (+4.51%) ⬆️
src/models/model.rs 100.00% <ø> (+41.02%) ⬆️
src/models/parallel_gateway.rs 67.10% <ø> (+3.35%) ⬆️
src/models/processor.rs 68.96% <ø> (-0.17%) ⬇️
src/models/stochastic_gate.rs 65.71% <ø> (+3.55%) ⬆️
src/models/storage.rs 59.72% <ø> (-0.81%) ⬇️
src/simulator/mod.rs 67.01% <33.33%> (ø)
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 08fb1ae...5d277a3. Read the comment docs.

@uint
Copy link
Contributor Author

uint commented Mar 14, 2021

I let myself push one more thing in here! I think it's better if the id field and getter don't live in each specific model type, but in a more general wrapper around those.

This does introduce a little boilerplate though with the extra implementation of AsModel for Model. We could revert that last commit if you don't like it.

@ndebuhr
Copy link
Owner

ndebuhr commented Mar 16, 2021

This is awesome, @uint.

I should mention there's one downside to this approach: the list of possible models is still closed. A user of the library won't be able to extend it with their own implementors. Does that matter?

It would be wonderful if users could use "sim" as a standard Cargo dependency, but also use custom models that they write. We can't do this with the crate today, so there is no regression. However, making this easier to implement in the future is valuable. The enum dispatch approach is great. Is there any way that this solution could be adapted in the future to accommodate user-defined models? Could metaprogramming/macros maybe work?

@uint
Copy link
Contributor Author

uint commented Mar 20, 2021

This is awesome, @uint.

I should mention there's one downside to this approach: the list of possible models is still closed. A user of the library won't be able to extend it with their own implementors. Does that matter?

It would be wonderful if users could use "sim" as a standard Cargo dependency, but also use custom models that they write. We can't do this with the crate today, so there is no regression. However, making this easier to implement in the future is valuable. The enum dispatch approach is great. Is there any way that this solution could be adapted in the future to accommodate user-defined models? Could metaprogramming/macros maybe work?

I don't think we can use macros for this. There's no supported way of collecting all trait implementations and using that list during macro expansion (to build an enum of all possible models). typetag does some magic (using the inventory crate) to construct that kind of list, but that list is a static var - which is also not usable during macro expansion, only in runtime.

The way I see it there are two ways to make this extensible to Rustaceans using the library:

  1. You found this one - just using the typetag crate to handle this dynamically, once typetag is supported on WASM. This is probably the most fuss-free option.
  2. We could do some work to make the Simulation type generic over the AsModel trait. Chances are Rustaceans who use the library don't even need the (de)serialization functionality anyway. We could give them a choice: use the built-in enum, use a Box<dyn AsModel> or create your own enum with more model types. As long as it implements the AsModel trait, it can be used in simulations. I have a sort of prototype for this locally, though I think it would be good to think through the API design for it so that it doesn't end up overcomplicated and confusing with the different options. It's something I could definitely work on. If the users really need to support serialization, they can provide their own implementation of it for their custom enum.

@ndebuhr
Copy link
Owner

ndebuhr commented Mar 21, 2021

Thanks @uint. Option 2 sounds great - I don't expect the typetag wasm support soon. Also, I've noticed that cloning can also be tricky when we get into the trait object territory. We can remove the Clone requirements on simulations and models, if that's helpful in any way.

I'm not sure if you want to split this up into multiple PRs, or just use one - I have no preference. I'll just keep watch for anything new.

@ndebuhr
Copy link
Owner

ndebuhr commented Mar 21, 2021

@uint Would it be a valid simplification to handle the model type field via #[serde(tag = "type")], as proposed in #7? Or would that introduce some undesirable side effects?

@uint
Copy link
Contributor Author

uint commented Mar 21, 2021

@uint Would it be a valid simplification to handle the model type field via #[serde(tag = "type")], as proposed in #7? Or would that introduce some undesirable side effects?

This is already a part of this PR: see here! I don't think this should introduce any bad side effects.

@uint
Copy link
Contributor Author

uint commented Mar 21, 2021

Thanks @uint. Option 2 sounds great - I don't expect the typetag wasm support soon. Also, I've noticed that cloning can also be tricky when we get into the trait object territory. We can remove the Clone requirements on simulations and models, if that's helpful in any way.

I'm not sure if you want to split this up into multiple PRs, or just use one - I have no preference. I'll just keep watch for anything new.

I was hoping for option 2 as well. I always feel like trait objects can introduce some quirks, and that they're more of a "last resort" or "quick" solution. With Rust, I tend to prefer things that incur no runtime cost (or it's optional) and encode more information in the type system, to be statically analyzed by the compiler - if that makes sense? Feels Rustier.

I think I'd prefer to do it in a separate PR, once this (or #7?) is merged - I like dividing work up into smaller chunks. I'm not picky though.

@smallstepman
Copy link

I always feel like trait objects can introduce some quirks, and that they're more of a "last resort" or "quick" solution. With Rust, I tend to prefer things that incur no runtime cost (or it's optional) and encode more information in the type system, to be statically analyzed by the compiler - if that makes sense? Feels Rustier.

I fully agree, I too prefer having things on static dispatch

@ndebuhr ndebuhr merged commit 2c7c087 into ndebuhr:main Mar 21, 2021
@ndebuhr
Copy link
Owner

ndebuhr commented Mar 21, 2021

Thanks @uint and @smallstepman

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

Successfully merging this pull request may close these issues.

4 participants