~/
rust-munich
·
crux + gpui
# More on crux Optional reading. Skim if a slide raised a question. --- ## The MVU triplet, in one sentence `update(Event, &mut Model) -> Command
` — "given what happened and the current state, mutate the state and tell me what side effects (and follow-up events) you want next." It is Model-View-Update, the architecture popularised by **Elm**. --- ## Why a separate `ViewModel`? `Model` holds *everything* — internal flags, caches, transient state. `ViewModel` is the projection your UI needs. Two benefits: - You can refactor `Model` without breaking the shell, as long as `view()` still returns the same `ViewModel` shape. - The shell renders from a small, focused struct — easier to reason about. --- ## Why effects are *values*, not actions In the core, `Effect::FetchMunichWeather(req)` is a plain enum variant. It is **data**. The core never opens a socket. This is why our tests can do: ```rust let effects: Vec
= cmd.effects().collect(); assert!(effects.iter().any(|e| matches!(e, Effect::FetchMunichWeather(_)))); ``` We *inspect* what the core wanted, without ever performing it. Compare with a typical service that calls `http_client.get(...)` directly — you'd need a mock client, an async runtime, and a fixture for the response. --- ## `request_from_shell` + `then_send` ```rust Command::request_from_shell(FetchMunichWeather) .then_send(Event::WeatherLoaded); ``` Read as: *"Ask the shell to perform `FetchMunichWeather`. When the result comes back, wrap it in `Event::WeatherLoaded(...)` and feed it through `update` again."* That last step is how the async result re-enters the system as a new event. Everything stays MVU. --- ## `Core::process_event` vs `Core::resolve` - `process_event(event) -> Vec
` — for events that originated in the shell (a button click). - `resolve(&mut request, output) -> Result
, _>` — for events that originated inside the core via `request_from_shell`. The shell performed the effect; now it hands back the result. Both return more effects to drain. Hence the recursion in `handle_effects`. --- ## Why `app_core`, not `core`? Because rust-analyzer's macro expansion and the Rust prelude both share the name `core` and get confused by it. Renaming the crate to `app_core` made the warnings vanish. See `git log` for the gory details. --- ## Further reading - The official book:
- Examples: