docs(app-iced): M101 r4 —— 订正共享点成本数字(3 / 不可行 / 3 处)与三处 p3 措辞
r3 复审:那段「仍然共享」的成本数字与代码事实不符(三条填页线据此取 scope,故按 p1 处理)。 本轮**只改文档/注释**,无产品代码与测试逻辑改动(唯一非注释改动是 t2 断言的 message 字符串)。 - 第 4 条「读页外真值」:`States` 没有 `Default`,加字段会让 4 处 struct literal 全部 E0063 (`pages/mod.rs:154/177/232` + `app/view.rs:70`)⇒ 把 model 塞进 `States` 是 **3 个共享文件** (含 M104 的落点 `app/view.rs`);改推「给 `settings::view` 加 `model` 形参」这个**真·2 个文件** 的形状。并订正「在 `app/state.rs` 用真值初始化(1 个文件)」——今天没有语言真值源 (`AppearancePrefs` 无 language 字段,唯一值是 `app/view.rs:128` 硬编码 `Lang::En`)。 - 第 5 条第 ② 条路(改 `Body` 返回 `Task`)**删掉**:`settings::view` → `pages::render` → `App::view` 一路返回 `Element`(iced 0.14 的 view 亦然,且 `view(&self)` 改不了状态),view 期间产出的 `Task` 没有出口;真做要 `settings/mod.rs` + `pages/mod.rs` + `app/view.rs` 三处且另造旁路,明确写「不建议」。 只留第 ① 条(`app/update.rs` 的 `Message::Boot` → `on_boot`,1 个文件)。 - 第 6 条与 `state.rs::demo_groups` 文档:「harness 侧改两处」→ **三处** (`pages/mod.rs` 的 `page` / `page_with_appearance` / `app_with_appearance`,行 156/179/234)。 - p3:`message.rs` 里守门路径改成 `app/update/settings/tests.rs`(并点名 `settings.rs` 只是 mod 声明点); `appearance_section.rs` 的「绞线」错字改「绊线」;断言 message 的 `Some(appearance::body)` 改成源码 实际的 `Some(body)`(本地 fn);`app/update/settings/tests.rs` 的「抓不住 #2」改成两种洞分开说 (`|` 续行放行;花括号形状的多行 pattern 是**静默跳过**,不是误红)。
This commit is contained in:
1 parent
c166944c8e
commit
d3e959e754
5 files changed
+35
-23
No files matched your search
@@ -30,8 +30,10 @@
|
||||
//! 抓不住(老实列出来):
|
||||
//! 1. **嵌套 match 里的兜底**——深度 ≥2 的臂不看。这是刻意的:嵌套 match 的穷尽性由它自己的类型
|
||||
//! 保证,跟 `GroupMessage` 漏接线无关;代价是没人守「嵌套 match 自己写了个 `_ =>`」;
|
||||
//! 2. **跨行 pattern**(除 `|` 续行)——把 struct 字段拆成多行、`=>` 落在第 3 行那种写法会被
|
||||
//! 当成「前缀不对」而误判兜底。当前代码风格不出现;真出现时放宽规则,别把守门删掉;
|
||||
//! 2. **跨行 pattern 分两种,别当一种**:以 `|` 开头的 or-pattern 续行**放行**(不误红);
|
||||
//! 但**花括号形状**的多行 pattern(例如 `Message::SetRuntime {` 折成多行、`=>` 落在后面)
|
||||
//! 会被**静默跳过**——那一行不带 `=>`,于是既不算臂也不算违规(臂数 0、零违规),是**漏检**
|
||||
//! 而不是误红。两种都是洞,当前代码风格都不出现;真要用这种写法时把规则补上,别把守门删掉;
|
||||
//! 3. **字符串/字符字面量里的 `{` `}`** 会扰乱深度计数(本文件与四个 handler 都没有这种写法);
|
||||
//! 4. handler 忽略消息(`let _ = message; Task::none()`)、两个 handler 身体写反或写成一样
|
||||
//! ——类型对得上就编得过,只有人读能看出来;
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
//! ## 测试
|
||||
//!
|
||||
//! 本文件的 [`tests::each_group_owns_its_own_message_type`];dispatch 侧的
|
||||
//! `the_group_dispatch_has_no_wildcard_fallback` 在 `app/update/settings.rs`。
|
||||
//! `the_group_dispatch_has_no_catch_all_arm` 在 `app/update/settings/tests.rs`(`app/update/settings.rs`
|
||||
//! 只是 `#[cfg(test)] mod tests;` 的声明点,别去那里找)。
|
||||
|
||||
use super::{ai_about, download, java, language_appearance};
|
||||
|
||||
|
||||
@@ -90,27 +90,35 @@
|
||||
//! 2. 本文件的 [`GROUPS`] —— 只有 ai+about 线**上第 5 组**时加一行(页面上多一组本来就是整页的变化)。
|
||||
//! 3. `tests/mod.rs` —— ai+about 线新建 `tests/ai_section.rs` 时要加一行 `mod ai_section;`
|
||||
//! (测试文件不挂 `mod` 就不编译),以及「左列顺序」那条字面量断言会连带红,需要人确认。
|
||||
//! 4. **读页外真值**(r2 复审 P1 补的,上一版漏了)—— [`States`] 只有 `appearance` + `groups` 两格,
|
||||
//! 组正文读不到 `pages::Model`,也读不到 presenter 的设置快照。最典型的是 language+appearance 线:
|
||||
//! 「当前语言」的唯一来源是 `Model.lang`(`pages/model.rs`),General 分组要显示真值就得让值进
|
||||
//! `States`,那要改 `settings/state.rs` + `pages/mod.rs`(`render` 现在只拿 `model` 算 metrics,
|
||||
//! **2 个共享文件**);或者反过来在 `app/state.rs` 用真值初始化 `Groups.language_appearance`
|
||||
//! (**1 个共享文件**)。建议形状:**一次性**给 `States` 加一格 `model: &'a Model`(并让
|
||||
//! `render` 把 `model` 传下去),此后四条线都不必再碰这两个文件——这是「谁先撞谁付一次钱」的
|
||||
//! 那类代价,不是永久性的四路撞车。
|
||||
//! 4. **读页外真值**(r2 复审 P1 补的)—— [`States`] 只有 `appearance` + `groups` 两格,组正文读不到
|
||||
//! `pages::Model`(「当前语言」的值在 `Model.lang`,`pages/model.rs`),也读不到 presenter 的设置
|
||||
//! 快照。两条路的**真实成本**(`States` 没有 `Default`,加字段必然 E0063,已实测):
|
||||
//! - 把 `model` **塞进 [`States`]** ⇒ struct literal 有 **4 处**(`pages/mod.rs:154/177/232` 与
|
||||
//! `app/view.rs:70`),四处都要补字段 ⇒ **3 个共享文件**:`settings/state.rs`、`pages/mod.rs`、
|
||||
//! **`app/view.rs`**(最后这个正是 M104 的落点,本 mission 反复设锚点要避开的就是它);
|
||||
//! - 给 `settings::view` **加一个 `model: &Model` 形参**(`pages/mod.rs` 的 `render` 本来就拿着
|
||||
//! `model`,直接往下传)⇒ **2 个共享文件**(`settings/mod.rs` + `pages/mod.rs`),
|
||||
//! `app/view.rs` 不用动 —— **推荐这个形状**。
|
||||
//!
|
||||
//! 顺带订正 r3 之前那句「在 `app/state.rs` 用真值初始化 `Groups.language_appearance`(1 个文件)」:
|
||||
//! 今天 `App` / `app/state.rs` 里**没有**任何语言真值源(`presenter::prefs::AppearancePrefs` 无
|
||||
//! language 字段;唯一的值是 `app/view.rs:128` 里硬编码的 `Lang::En`),要先有真值源才谈得上
|
||||
//! 初始化位置。两种形状都是「谁先撞谁付一次钱」的一次性代价,不是永久性四路撞车。
|
||||
//! 5. **首帧取数 / 异步发起**(同上,r2 复审 P1 补)—— [`Body`] 是
|
||||
//! `fn(&Ui, States) -> Option<Element>`,**返回不了 `Task`**,而 `view` 是纯函数:一组想在自己
|
||||
//! 的首帧就发起探测(java 的「探测本机 JVM」、download 的「测源可用性」)有两条路:
|
||||
//! ①在 `app/update.rs` 的 `Message::Boot` 分支里补一次首帧派发(**1 个共享文件**);
|
||||
//! ②把 `Body` 的返回类型改成 `Option<(Element, Task<Message>)>` 或 `Option<Task>` 旁路
|
||||
//! (改本文件 + `form`,**1 个共享文件**,一次性)。不改的代价是:首屏显示演示值,等用户点一次
|
||||
//! 才变真值——四条线都能接受,就不必动。
|
||||
//! `fn(&Ui, States) -> Option<Element>`,返回不了 `Task`;而且 `settings::view` → `pages::render`
|
||||
//! → `App::view` **一路都返回 `Element`**(iced 0.14 的 `view` 也只返回 `Element`,`view(&self)`
|
||||
//! 又改不了状态),**view 期间产出的 `Task` 没有出口**。所以只有一条路:在 `app/update.rs` 的
|
||||
//! `Message::Boot` 分支补一次首帧派发(**1 个共享文件**——`on_boot` 本来就在派
|
||||
//! `AppCommand::RefreshAll`)。想让「组自己」发起首帧探测,得先在 app 侧另造一条旁路
|
||||
//! (`settings/mod.rs` + `pages/mod.rs` + `app/view.rs` 三处都要动),**不建议**。不改的代价:
|
||||
//! 首屏显示演示值、等用户点一次才变真值——四条线都能接受就不必动。
|
||||
//! 6. **隐性代价:`Groups` 必须是 `Sync + Default`**(r2 复审 P3 指出)——
|
||||
//! [`demo_groups`] 用 `static LazyLock<Groups>` 撑着 harness 路径,所以某个组的 `State` 里一旦
|
||||
//! 放了 `Rc` 这类非 `Sync` 字段,编译会在**本模块**(`settings/state.rs`)红。选择 `LazyLock`
|
||||
//! 是为了让 `page()` / `page_with_appearance()` 的返回 `Element<'a>` 借得到一个 `'static` 的默认
|
||||
//! 状态;如果哪天必须放非 `Sync` 状态,改法是把默认状态改成「每个调用点自己造一个 `Groups`」
|
||||
//! (harness 侧改两处,同样是**一次性**代价)。
|
||||
//! ——`pages/mod.rs` 的**三个**调用点都要改(`page` / `page_with_appearance` /
|
||||
//! `app_with_appearance`,行 156 / 179 / 234),同样是**一次性**代价。
|
||||
|
||||
// 四条填页线的文件要能被**各自那条落点**(`app/update/settings/<线>.rs`)与状态架子
|
||||
// (`state::Groups`)命名,所以是 `pub(crate)`:最小面,不是 crate 公开 API。
|
||||
|
||||
@@ -76,8 +76,9 @@ pub struct States<'a> {
|
||||
///
|
||||
/// **隐性代价(r2 复审 P3)**:`static` 要求 `Groups: Sync + Default`,于是某个组的 `State` 里一旦
|
||||
/// 放了 `Rc` 这类非 `Sync` 字段,编译会红在**本文件**(共享)而不是那一组自己的文件。真需要
|
||||
/// 非 `Sync` 状态时的改法:去掉这个 `static`,改成每个 harness 调用点自己造一份 `Groups`
|
||||
/// (`pages/mod.rs` 的两个入口各一处,一次性代价),见 [`super`] 文档「仍然共享」第 6 条。
|
||||
/// 非 `Sync` 状态时的改法:去掉这个 `static`,改成每个调用点自己造一份 `Groups`——`pages/mod.rs` 的
|
||||
/// **三个**调用点都要改(`page` / `page_with_appearance` / `app_with_appearance`,行 156 / 179 / 234),
|
||||
/// 一次性代价,见 [`super`] 文档「仍然共享」第 6 条。
|
||||
pub fn demo_groups() -> &'static Groups {
|
||||
static DEMO: LazyLock<Groups> = LazyLock::new(Groups::default);
|
||||
&DEMO
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//!
|
||||
//! **归 language+appearance 线**:这是设置页唯一接了真控件的一组,真控件实现全在
|
||||
//! `pages/appearance/section.rs`;本文件只守「注册表这一侧的接线」。
|
||||
//! 本组已经把 `body` 接上了;`tests/mod.rs` 那条「只有一组有真控件」的**聚合绞线已在 M101 r2 删除**
|
||||
//! 本组已经把 `body` 接上了;`tests/mod.rs` 那条「只有一组有真控件」的**聚合绊线已在 M101 r2 删除**
|
||||
//! (被四条 per-group 断言完全蕴含——代价是「唯一性」从此没人守,那段说明写在 `tests/mod.rs` 同处)。
|
||||
|
||||
use super::super::appearance;
|
||||
@@ -46,7 +46,7 @@ fn the_appearance_group_keeps_its_icon() {
|
||||
fn the_appearance_group_keeps_a_real_control_body() {
|
||||
assert!(
|
||||
appearance::GROUP.body.is_some(),
|
||||
"外观分组必须是挂了真控件的那一组(`settings/appearance.rs` 的 `body: Some(appearance::body)`;\
|
||||
具体渲染器由那一行源码 + 截图担保,函数指针相等性断言不了)"
|
||||
"外观分组必须是挂了真控件的那一组(`settings/appearance.rs` 里是 `body: Some(body)`,\
|
||||
`body` 是本文件那个本地 fn;具体渲染器由那一行源码 + 截图担保,函数指针相等性断言不了)"
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user