12 KiB
处置:presentation 层封装修复批(2026-11-04)
性质:设计讨论段过程稿(裁决记录+取证事实)。接收方=reports/需求卡片-架构审查presentation层封装修复批-2026-11-04.md + 待办清单条目「架构审查余项——闸面缺口、豁免存废、零测试点名与架构文档漂移」。寿命:需求卡片成立即退役(吸收即死——结论吸收进卡片,未决迁待办清单)。 输入:reports/审计-全库架构审查-2026-10-29.md §5.1 扩面普查(presentation 层私取面,初读约 227 行)+ 2026-11-04 设计讨论会话用户逐项裁决 + 2026-11-04 会话逐文件取证(worktree archpres-card,基点 61995733,复核零漂移)。
一、总判据(用户 2026-11-04 裁,本批一切设计遵循)
- 修复框架=每处先答「该不该访问」,再定公开形态:访问该存在的,把被访问方需要暴露的东西做成正式公开面(表达操作或契约的公开方法/公开数据成员),访问方改走公开面;访问不该存在的,改设计(逻辑归位、依赖交付),禁把违规调法直接改名合法化。
- 三个内部数据类按登记表定位(改法A,用户裁):它们是只被宿主文件填读的登记表,字段转公开数据成员。
- 全部一批做完(方案一,用户裁):四族修法一张卡、一个实现批、一次合回。
- 零行为变更:同 core 5.1 批口径——玩家可观测面逐位不变;职责归属零改动(代码位置不动,只改往来方式)。
- 修复依据=code-conventions §1.6(拆分交接定义+封装边界:任何代码不得访问其他对象的下划线成员,跨对象往来只走公开方法与属性)。
二、数字换代(2026-11-04 实查,取代初读口径)
初读「约 227 行/8 文件」作废。现行口径=剔除注释行与 self._ 后的码行计数:443 行/14 文件。取证 grep:grep -rnE '\._[a-zA-Z]' game/presentation --include='*.gd' 后剔除注释行与 self._;行号与逐行账以写卡段复核为准(5.1 卡同款义务)。
| 文件 | 码行 | 归族 |
|---|---|---|
| views/level_map_screen.gd | 88 | A1(87)+C(1,UiKit) |
| main_ui_build.gd | 70 | B |
| views/battle_end_overlay.gd | 69 | A1 |
| views/standee_body.gd | 55 | A2 |
| views/debug_overlay.gd | 50 | A1 |
| main.gd | 45 | B |
| main_adventure_flow.gd | 26 | B |
| main_overlay_flow.gd | 15 | B |
| main_debug_flow.gd | 11 | B |
| views/board_view.gd | 7 | A2 |
| views/settings_overlay.gd | 2 | C(UiKit) |
| views/cell_mark_overlay.gd | 2 | C |
| main_esc_flow.gd | 2 | B |
| ui_assembler.gd | 1 | C(UiKit) |
四族合计:A1=206 行/42 字段;A2=62 行/16 字段+6 成员;B=169 行/80 名字;C=6 行/4 名字。
三、逐族裁决
A1·三个内部数据类——字段公开化(用户裁改法A)
| 宿主文件 | 内部类 | 被宿主摸的字段(42 个,今日逐文件 grep 提取) |
|---|---|---|
views/level_map_screen.gd:37 _MapState |
实例 _map(:59) |
_abandon_timer _attr_value _bonus_row _bonus_value _canvas _drawn_disp _feat_value _gp_value _hp_bar _hp_value _layer_decor _level_label _runner _title |
views/battle_end_overlay.gd:15 _EndOverlayState |
实例 st(:32) |
_board_rect _bonus_name _bonus_row_l _bonus_val _cele _crest_bricks _dim _fx_counts _ks_name _ks_row _ks_val _rows_box _seal _verdict |
views/debug_overlay.gd:16 _DebugState |
实例 st(:33) |
_atk _atk_val _base_atk _base_hp _ctx_locked _db _eff _hp _hp_val _run_data _run_labels _sim_count _sim_out _sim_running |
裁决与依据:三个类只被宿主文件填读(全 presentation 域 grep _MapState|_EndOverlayState|_DebugState|._map\.,文件外消费者零命中,2026-11-04 实证),内容全是宿主的界面控件引用与运行数值,没有需要保护的处理规则——按改法A,42 个字段去下划线转公开数据成员,宿主 206 处访问点随改。字段公开后访问本就合法,规约零改动。内类自用、宿主不碰的字段维持下划线不动。附回归义务:三个类的「文件外零消费者」落成 sweep 断言。
A2·拆件子件——构造交付+行为归位+读投影
standee_body.gd → st(standee_vitals.gd 实例,9 字段),逐字段归属(2026-11-04 逐行判读):
| 字段 | 现役访问 | 归属 |
|---|---|---|
| _kind | :39 写(生成时);:265/:275/:300/:309/:365/:409 读 | 身份——构造期一次交付;读走公开读法 |
| _display_name / _enemy_id / _armor / _hp_max | :82-85/:96 写(配置/重置时);:48/:53/:66-69/:340-342/:419/:465-482 读 | 同上——构造/配置公开口一次交付;读走公开读法 |
| _order | :131 写;:410 读 | 同上 |
| _dead | :173/:262 写(击杀/复活);:91/:98/:138/:171/:248/:277 读 | 生命周期行为——归位为子件公开方法(标记死亡/复位),宿主停写 |
| _hp_cur | :419 读 | 子件自管(宿主零直写)——读走公开读法 |
| _hp_flash_tw | :254-258 宿主自建 tween 改宿主自身 modulate | 归位为子件行为方法 play_hp_flash()——vitals 已自持 _owner: Node2D 与 tween 先例(apply_hp/_hp_tween 同型),句柄留 vitals,宿主成员零增 |
standee_body.gd → mo(standee_motion.gd 实例,7 字段):_hero_state :40 写(生成时置 IDLE)→ 走既有公开方法 apply_hero_state(:300 在役先例);_intent_visible/_glyph/_col/_scale/_rot 写 :140/:145/:159-161/:181、读 :58/:431-458 → 意图显示是演出行为——归位为子件公开方法(显示/隐藏/复位),绘制所需状态经一个公开读取口交付(宿主 _draw 消费,:439-458 现役);_portrait_sprite :284/:431 读、生成期挂载 → 挂载走公开口,绘制读取走公开读法。
board_view.gd → _hover_comp(board_hover.gd 实例,6 成员/7 行)::249 每战重绑 _minesweeper → 公开重绑口(bind_save_manager 先例);:260 复位 _hover、:309 _refresh_hover_after_paint()、:464 _hover_at、:479 _detect_chord、:146 连接 _on_shell_mouse_exited、:828 读 _hover → 各自公开化(悬停操作本来就是该件对外职责,公开化=给应有的身份)。
B·组合根与五个分文件——正式交接面(169 行/80 名)
结构判定(2026-11-04 实查):main 与五个分文件(main_ui_build/main_adventure_flow/main_overlay_flow/main_debug_flow/main_esc_flow——main 拆出的分步执行件,main 侧留同名单行转发)之间是成对的单行转发关系:分文件把信号接到 main 的 _on_xxx 处理器,main 里该处理器一行转调分文件同名方法(例:main_adventure_flow.gd:12 connect(root._on_adventure_finished) ↔ main.gd:234 MainAdventureFlow._on_adventure_finished(self, summary))。需求是真的(互相需要对方的服务),错在服务没有正式公开身份。
设计规则(六条,全部落卡):
- 分文件入口方法公开化:main 转发调到的
MainXxxFlow._方法去下划线公开化(45 行方向)。各分文件公开方法现值 0,公开化后 3–15 个,全部在默认阈值 ≤20 内。 - main 的 on_ 处理器保持私有*(探针/测试按 main.on* 名字引用 104 处,保名=测量面零波及);分文件接线语句里的
connect(root._on_xxx)改收 Callable 束:main 调用分文件接线入口时以参数交付处理器束(键=用途名,值=main 自建 Callable——main 内自引合法),分文件 connect 语句消费束值。引用束注入先例=architecture.md:124 BoardInstaller、5.1 卡束形态。 - main 的服务方法被分文件调的,去下划线公开化(_refresh_presentations 11 次、_sync_status_entry 5 次、_fatal_screen 4 次、_quit_game 2 次、_begin_session 2 次、_start_debug_levels、_check_board_hints、_show_board_fx_for_node、_replay_locked_click、_sync_settlement_visuals、_wire_battle、_sync_debug_overlay、_open_settings、_open_save_select、_status_data、_gp_summary_text、_tune_sim 等)。
- main 的句柄成员被分文件读写的,成员保持私有,补公开读投影/设置方法(BreakpointStore 先例):_camp_pres(24 次)、_bonus(9 次)、_debug(6 次)、_confirm_consumer(4 次)+_confirm_consumer_slot、_treasure_ui(3 次)、_seed_value、_current_master_seed 等读写面逐名落卡。
- 探针/测试独占、互调不涉及的名字零触碰(_is_settling 等)——测量面直构既有例外维持。
- main.gd 指标例外申报:公开方法现值 1,规则 3+4 落地后预计 25–30(T1 实数)——组合根服务面超默认阈值 ≤20,理由与先例=level_runner.gd(公开方法 33 在册基线);基线落法=实现批
python tools/gdstyle_gate.py --refresh人工专用通道。
80 名完整清单=写卡段逐名 grep 实核落卡(本次会话已提取:main 侧被摸 60 名+分文件侧被摸 20 名,按上述规则 1–5 逐名归位)。
C·杂项(6 行)
- UiKit 三个私有工厂方法被跨文件调:_gradient_base(level_map_screen.gd:69)、_beams_rect(ui_assembler.gd:106)、_switch_toggle(settings_overlay.gd:88/:105)→ 去下划线公开化(无状态工厂本来就是公用设施,公开化=给应有的身份)。
- cell_mark_overlay.gd:13-14 摸宿主 board_view 的 _glow_layer:board_view 是贴顶件(基线在册 27 公开方法/31 成员,禁再增面)→ 走构造交付:board_view 建 cell_mark 时把标记遮罩下发口(引用或 Callable)一并交付,cell_mark 持自有引用,宿主零新增公开面。
四、S13 预算核查(触件现值与预期,2026-11-04 实测)
| 触件 | 公开方法现值 | 成员现值 | 本批预期 |
|---|---|---|---|
| main.gd | 1 | 15(默认顶) | 公开方法升 28–32(构成=既有 1+服务 17+句柄口 12)——指标例外申报(规则 B6);成员零增 |
| 五分文件 | 各 0 | 各 0 | 公开方法 3–15,预算内 |
| level_map_screen / battle_end_overlay / debug_overlay | 8/6/19 | 7/5/4 | A1 只改字段名,两键零变化 |
| standee_body | 20(顶) | 10 | 公开方法与成员双零增(flash 行为归位 vitals 自持) |
| standee_vitals / standee_motion | 1/6 | 12/11 | 行为归位+读投影公开方法净增(各 ≤20 内);成员零增 |
| board_view | 27(基线在册) | 31(基线在册) | 零净增(C 族走构造交付;A2 走 board_hover 公开面) |
| board_hover | 0 | 9 | 公开方法 +6,预算内 |
| ui_kit / cell_mark_overlay | 0/5 | 0/13 | ui_kit +3;cell_mark 成员 +1(构造交付的引用),预算内 |
基线在册 5 键(tools/gdstyle_baseline.txt)中 board_view 两键与本批相关:达成「只降不升」=board_view 零新增面;main.gd 例外键经申报落基线。
五、探针与测试连带面(2026-11-04 实测)
grep -rE 'main\._[a-zA-Z]' game/probe game/tests=104 处引用/36 个名字/14 个文件(ui_probe、system_test.gd、ui_input_probe、shot_probe、layout_probe、ui_tune_probe、ui_struct_probe、screen_flow_probe、t17_defer_probe、ui_click_probe、fx_shot_probe、probe_ui_util、unit/presentation/pacing_queue_test、unit/core/breakpoint_resume_test)。设计规则 B2 保 on_* 处理器名不变 → 连带替换面收敛为「探针引用名字 ∩ 公开化名字」的交集(预计 10–20 处,T1 落精确底账);替换属「随被测改动同步的引用形态迁移」,按测试削弱申报登记,断言内容零改动。
六、验证框架
- 结构性主证:presentation 私取 sweep 测试(新增,1 件)——四族逐组「扫描面非空前置+私取模式零命中+新公开面正锚」,手法沿 5.1 卡 encapsulation_sweep_test(复用源 token 扫描手法不并件,同 5.1 卡 :257 论证)。
- 零行为变更证明:探针套件与渲染 golden 全程零转红(呈现面逐位同)+冒烟/单元既有套件零转红+探针/测试替换后当轮真实跑绿。
- 能力清单:本批零新增能力(零行为变更,玩家可观测能力面零变化),能力行全部「既有」,
game/tests/README.md零编辑。