MediaOrganizer 开发经验与教训总结

MediaOrganizer 开发经验与教训总结

动画

面向后续版本演进与新模块复用的实践记录(仅涉及过程与工程经验,不改变现有功能)

一、总体架构与演进

  • 模块边界清晰

    • 将图片、视频、音频分别以 ImagesViewModel, VideosViewModel, AudioViewModel 管理,UI 在 MainWindow.xaml 的 Ribbon 页签中组织。
    • 各模块内部都具备完整的“扫描/预览/执行/撤销/设置”闭环,便于独立开发与增量发布。
  • 数据驱动的预览重建

    • 预览列表统一从“缓存(宽高/时间/标签)→ 目标列”的重建路径生成,避免重复 I/O 与状态不一致。
    • 切换分类仅触发“基于缓存重建”,不做磁盘扫描;目标根变化时优先在内存内重建,必要时再扫描。
  • 发布与交付

    • 标准化 dotnet publish(win-x64、Release、依赖框架、单文件)到项目根 publish/,缩短测试闭环。

二、图片模块(Images)的关键经验

  • HEIC 两步转换策略

    • 当目标为 JPG:直接调用外部 heic2jpg
    • 当目标为 PNG 等:先 HEIC→临时JPG,后解码再编码到目标格式。
    • 教训:不要在执行环节“强制改扩展”;让预览与执行遵循同一命名逻辑,日志必须覆盖步骤与参数。
  • 独立拖拽(Standalone)一致性

    • 拖拽到列表的文件/目录,视为“独立个体”,其根目录按“各自源目录”处理,不依赖 UI 的源目录。
    • 切换标签走与拖拽相同的重建逻辑,确保 UI 体验一致。
    • 教训:不要把“拖拽时的目标计算”写死在拖拽函数里;统一抽象为“从缓存重建”的路径,拖拽仅负责缓存构建。
  • 预览刷新与缓存

    • 统一通过 RebuildPreviewsForModeFromCache/RebuildPreviewsForClassificationChange 完成重建;
    • 通过 _hasCachePreviews.Count 判断是否允许“基于缓存重建”。
    • 切换源/目标根时,先 ResetPreviewState 清空 _imageInfoCache/_imageMonthCache/_sessionExcluded/_standaloneDropped,保证干净重扫。
  • 小工具提炼

    • GetBaseRootForPath 统一决定“根目录”(独立拖拽/Source/TargetRoot)。
    • ResolveConflictName 统一处理“批内命名冲突自增”。
    • 教训:重复逻辑分散在多个分支很容易不一致,提炼工具方法能降低维护成本。

三、视频与音频模块的共性

  • 一致的重置/撤销与列表行为

    • 三个模块均提供 ResetAll(取消扫描、清空输入/列表/缓存、不变更分类、不触发扫描)。
    • 删除所选仅从预览移除并写 _sessionExcluded,避免扫描“复活”。
  • 缓存优先与最小化 I/O

    • 视频:首扫阶段尽量缓存分辨率,切换模式优先从缓存取。
    • 音频:重命名预览缓存目标名,切换模式时可快速恢复;清理/归一化预览不做 I/O。
  • 外部工具与可用性探测

    • 音频归一化基于 ffmpeg,可用性在激活时刷新;
    • 教训:外部工具调用需要“超时/退出码/错误消息”三要素,同时 UI 不要在启动时阻塞。

四、交互与 UX

  • 拖拽与扫描的差异化

    • 拖拽到“列表区域”与将目录放入“源目录”框的语义不同:前者是独立个体,后者是全盘扫描。
    • 状态文本、进度条与失败高亮(执行后闪烁)有效提升用户对系统状态的理解。
  • Ribbon 操作流

    • 分类、源目录、目标根、扫描、执行、撤销、批次、预览分组明确;新增“重置”按钮让用户能快速归零。

五、日志与诊断

  • 结构化&分级

    • Debug:细粒度步骤(如 HEIC 两步转换、外部进程参数)。
    • Info:关键阶段(扫描开始/结束、执行统计)。
    • Warn:可恢复异常(外部工具不可用、清理空目录失败等)。
    • Error:执行失败、不可恢复异常(并记录路径与上下文)。
  • 教训

    • catch {} 在复杂路径上隐藏问题;改为最少 Warn 能在不打扰用户的情况下留痕。

六、工程细节与陷阱

  • 避免魔法数字与重复分支

    • 分类索引(0..7)建议未来枚举化,减少错用成本。
  • 临时文件与资源回收

    • HEIC 临时 JPG 的清理必须覆盖所有返回路径(try/finally + 分支覆盖),避免残留。
  • 跨盘 Move/Copy 的一致性

    • 执行层统一用“同盘Move / 跨盘Copy”的语义,撤销时按批次记录回滚。
  • 发布脚本与说明

    • 约定 publish/ 输出,并在 README 中保留发布指令与参数,减少口头知识。

七、团队协作与流程

  • 小步提交、可验证增量

    • 每轮更改后形成可运行的发布包,用户侧可立即复测;
    • 对“切换/拖拽/执行”等关键交互,优先补日志再改逻辑,定位更快。
  • 统一代码风格与注释

    • 关键方法(预览重建、执行主循环)写清“输入/输出/副作用”;
    • 日志使用统一模板:_log.Debug/Info/Warn/Error 与结构化参数。

八、可复用的实践清单(Checklists)

  • 拖拽 & 切换一致性

  • 扫描与执行

  • 外部工具调用

  • 发布与验证


总结:本项目的成功在于“统一的数据驱动重建、可观测的日志、与严格区分拖拽/扫描语义”。建议在后续模块中延续该思路,并在适当时机将分类索引枚举化、提取更多共用工具函数,以进一步降低维护成本。

posted @ 2025-09-23 11:23  秋月的私语  阅读(13)  评论(0)    收藏  举报