公司动态
如何用好Facade模式封装外部工具:atcoder-cli集成online-judge-tools完整代码剖析
如何用好Facade模式封装外部工具atcoder-cli集成online-judge-tools完整代码剖析【免费下载链接】atcoder-cliAtCoder command line tools项目地址: https://gitcode.com/gh_mirrors/at/atcoder-cliatcoder-cli命令为acc是面向 AtCoder 竞赛平台的命令行工具一条命令创建比赛项目目录、获取比赛与题目信息并与开源工具online-judge-tools下称 OJ深度集成实现免 URL 提交代码、自动下载样例测试用例。本文将剖析它如何用经典的Facade门面模式仅用不足 50 行代码把外部命令行工具封装成一个简单、可靠、可优雅降级的统一接口。想阅读完整源码可先克隆仓库git clone https://gitcode.com/gh_mirrors/at/atcoder-cli一、门面模式解决什么问题从 acc 的两条命令说起acc有两条核心命令依赖外部工具 OJacc submit把本地代码提交到 AtCoder 题目页acc new/acc add创建问题目录时顺带下载样例输入/输出如果不用门面模式业务代码里会散落着OJ 装没装装在哪Linux 还是 Windows调用失败怎么提示这些横切逻辑。而 atcoder-cli 把所有这些细节收拢到一个类里——src/facade/oj.ts业务层只调用三个方法完全不需要知道 OJ 是怎么找到的。这就是门面的价值用简单接口隔离子系统复杂度。二、核心门面类 OnlineJudge 逐行剖析门面实现集中在 src/facade/oj.ts#L7-L47只有三个静态方法职责单一清晰。2.1 getPath()智能定位 oj 可执行文件getPath() 的查找策略是两段式的先读全局配置项oj-path见 src/config.ts#L6-L13 中的默认配置未配置时按操作系统选择命令——Windows 用where oj其他平台用which oj——在 PATH 中查找。const command process.platform win32 ? where oj : which oj;找不到时返回null而不是抛异常把是否可用的判断权交给调用方——这是门面做优雅降级的关键设计。2.2 checkAvailable()可用性探测 路径缓存checkAvailable() 会真正执行一次oj -h以标准输出非空作为可用的判据。精妙之处在于一旦验证通过且配置里还没有记录该路径就立即写回配置if (result config.get(oj-path) ! path) config.set(oj-path, path);这就是自动探测 记忆缓存首次使用时付出一次which的探测成本后续启动直接命中配置无需重复查找。用户也可用acc config oj-path path手动指定帮助文本见 src/help.ts#L26。2.3 call()共享标准输入输出的透明代理call() 用child_process.spawn启动 oj 进程stdio: inherit让 oj 的输入输出直接透传到用户终端——比如 oj 提交后的交互确认、进度提示原样呈现const oj child_process.spawn(path, args, {stdio: inherit});注意它对未安装的情况显式抛出online-judge-tools not installed.与checkAvailable()形成先探测、后调用的防御组合。三、两个真实集成点门面在业务层如何被使用3.1 acc submit先校验 URL再委托提交提交逻辑在 src/commands.ts#L197-L241 的submit()中步骤体现了门面的典型用法智能推断提交目标文件未指定时从当前目录的项目文件反查 contest/task无需用户手敲参数门禁检查if (!await OnlineJudge.checkAvailable())直接友好报错并返回而不是等到调用时才崩溃平台侧校验用 AtCoder API 确认题目 URL 真实存在避免把无效 URL 交给 oj一行委托await OnlineJudge.call([s, url, filename, ...facade_options])把 oj 的s子命令包装为acc submit。另外facade_options是透传参数acc submit main.cpp -- -w 10可把任意额外参数传给 oj实验特性说明见 src/help.ts#L40-L46。3.2 acc new / acc add下载样例用例目录创建逻辑在 src/project.ts#L178-L198 的installTask()中。当用户未加--no-tests时它先探测可用性再决定是否下载if (OnlineJudge.checkAvailable()) { await OnlineJudge.call([dl, task.url, -d, testdir]); } else { console.error(online-judge-tools is not available. downloading of sample cases skipped.); }这里展示了门面的第二重价值依赖是可选的。没装 oj 也能正常建目录只是跳过下载并给出明确提示——用户体验不中断。CLI 侧的命令定义含--no-tests开关与check-oj诊断命令在 src/cli/index.ts#L11-L43 和 src/cli/index.ts#L110-L118acc check-oj对应的实现是 checkOJAvailable()。四、为什么这个设计值得学习设计点收益所有 oj 交互收敛于OnlineJudge一个类业务代码零污染升级/替换工具只改一处getPath()配置优先、PATH 兜底跨平台 可手动覆盖安装路径探测成功后回写oj-path配置一次探测终身免检stdio: inherit透传外部工具的交互体验原封不动可用性检查前置 友好降级可选依赖不破坏主流程一句话总结Facade 模式让 atcoder-cli 把外部工具集成压缩成checkAvailable()/getPath()/call()三个动词新手读一遍 src/facade/oj.ts 就能掌握全部集成逻辑 。五、延伸阅读相关源码地图门面实现src/facade/oj.ts提交命令与门禁检查src/commands.ts#L197-L241样例用例下载集成src/project.ts#L190-L198全局配置项含oj-pathsrc/config.tsCLI 命令注册src/cli/index.ts帮助文案src/help.ts项目说明与使用示例README.md模板 Schema 定义schema/acc-project-schema.json掌握了这套模式后你可以在自己的项目中同样用一个小小的门面类把任何外部命令行工具变成三行调用的干净依赖。【免费下载链接】atcoder-cliAtCoder command line tools项目地址: https://gitcode.com/gh_mirrors/at/atcoder-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考