网淘吧来吧,欢迎您!

Portable Tools

2026-03-30 新闻来源:网淘吧 围观:9
电脑广告
手机广告

便携工具 - 跨设备开发方法论

构建能在不同设备、命名方案和配置下工作的工具的方法论。基于OAuth刷新器调试会话的经验教训(2026-01-23)。

核心原则

切勿假设你的设备是唯一设备。

Portable Tools

你的本地设置只是众多可能配置中的一种。为通用情况而构建,而非特定实例。


三大问题(在编写代码前)

1. "设备之间有何差异?"

在编写任何读取配置、数据或凭证的代码之前:

请思考:

  • 文件路径?(macOS与Linux,不同的主目录)
  • 账户名称?(user123与default与oauth)
  • 服务名称?(拼写/大小写的细微差异)
  • 数据结构?(不同版本,不同格式)
  • 环境?(不同的shell,可用的不同工具)

来自OAuth刷新器的示例:

  • ❌ 错误假设:账户始终是"claude"
  • ✅ 实际情况:可能是"claude"、"Claude Code"、"default"等。

操作:列出变量,使其可配置或可自动发现


2. "我如何证明这是有效的?"

在声明成功之前:

要求:

  • 具体的"之前"状态(确切值)
  • 具体的"之后"状态(确切值)
  • 证明它们不同(并排比较)

OAuth 刷新器的示例:

BEFORE:
- Access Token: POp5z1fi...eSN9VAAA
- Expires: 1769189639000

AFTER:
- Access Token: 01v0RrFG...eOE9QAA ✅ Different
- Expires: 1769190268000 ✅ Extended

操作:始终使用真实值展示数据转换过程


3. "当它出错时会发生什么?"

在推送到生产环境之前:

测试:

  • 错误配置(故意破坏配置)
  • 数据缺失(移除预期字段)
  • 多个条目(模糊情况)
  • 边界情况(空值、特殊字符)

OAuth 刷新器的示例:

  • 使用以下内容进行测试keychain_account: "wrong-name"回退机制应能正常工作
  • 测试密钥链数据不完整的情况 → 应能优雅地失败并给出有用的错误提示

操作:不仅要测试正常路径,还要测试故障模式


强制模式

模式1:显式优于隐式

❌ 错误:

# Ambiguous - returns first match
security find-generic-password -s "Service" -w

✅ 正确:

# Explicit - returns specific entry
security find-generic-password -s "Service" -a "account" -w

规则:如果命令可能产生歧义,应使其明确。


模式2:使用前验证

❌ 错误:

DATA=$(read_config)
USE_VALUE="$DATA"  # Hope it's valid

✅ 正确:

DATA=$(read_config)
if ! validate_structure "$DATA"; then
    error "Invalid data structure"
fi
USE_VALUE="$DATA"

规则:切勿假设数据具有预期的结构。


模式3:回退链

❌ 错误:

ACCOUNT="claude"  # Hardcoded

✅ 正确:

# Try configured → Try common → Error with help
ACCOUNT="${CONFIG_ACCOUNT}"
if ! has_data "$ACCOUNT"; then
    for fallback in "claude" "default" "oauth"; do
        if has_data "$fallback"; then
            ACCOUNT="$fallback"
            break
        fi
    done
fi
[[ -z "$ACCOUNT" ]] && error "No account found. Tried: ..."

规则:为常见变体提供自动回退机制。


模式4:有用的错误提示

❌ 错误:

[[ -z "$TOKEN" ]] && error "No token"

✅ 正确:

[[ -z "$TOKEN" ]] && error "No token found

Checked:
- Config: $CONFIG_FILE
- Field: $FIELD_NAME
- Expected: { \"tokens\": { \"refresh\": \"...\" } }

Verify with:
  cat $CONFIG_FILE | jq '.tokens'
"

规则:错误信息应帮助用户诊断和修复问题。


调试方法论(Patrick的方法)

第一步:获取精确数据

不要问:“它坏了吗?”
要问:“你看到的具体数值是什么?存在多少条记录?哪一条包含数据?”

示例:

# Vague
"Check keychain"

# Specific
"Run: security find-generic-password -l 'Service' | grep 'acct'"
"Tell me: 1. How many entries 2. Which has tokens 3. Last modified"

第二步:用具体实例证明

不要说:“现在应该可以了”
要展示:“这是之前的状态(POp5z...),这是之后的状态(01v0R...),它们不同”

模板:

BEFORE:
- Field1: <exact_value>
- Field2: <exact_value>

AFTER:
- Field1: <new_value> ✅ Changed
- Field2: <new_value> ✅ Changed

PROOF: Values are different

第三步:立即考虑跨设备情况

不要想:“在我机器上能运行”
要想:“如果他们的设置在[X]方面不同怎么办?”

检查清单:

  • 账户名是否不同?
  • 不同的文件路径?
  • 不同的工具/版本?
  • 不同的权限?
  • 不同的数据格式?

预发布检查清单(发布前)

发现阶段

  • 列出所有外部依赖(文件、命令、服务)
  • 记录每个依赖提供的内容
  • 识别哪些部分可能在设备间存在差异

实施阶段

  • 使变量可配置(并提供合理的默认值)
  • 为每个输入添加验证
  • 为常见变量构建回退链
  • 添加--dry-run--test模式

测试阶段

  • 使用正确配置测试 → 应正常工作
  • 使用错误配置测试 → 应回退或优雅地失败
  • 测试数据缺失的情况 → 应提供有用的错误信息
  • 测试多个条目 → 应能处理模糊性

文档编写阶段

  • 记录默认假设
  • 记录如何验证本地设置
  • 记录常见变体及其处理方法
  • 包含数据流图
  • 添加故障排除部分

真实案例:OAuth 刷新机制

原始(已损坏的)版本

# Assumes single entry, no validation, no fallback
KEYCHAIN_DATA=$(security find-generic-password -s "Service" -w)
REFRESH_TOKEN=$(echo "$KEYCHAIN_DATA" | jq -r '.refreshToken')
# Use token (hope it's valid)

问题:

  • 返回首个字母匹配项(错误条目)
  • 无验证(可能为空/格式错误)
  • 无回退机制(账户名称不同时即失败)

修复(可移植)版本

# Explicit account with validation and fallback
validate_data() {
    echo "$1" | jq -e '.claudeAiOauth.refreshToken' > /dev/null 2>&1
}

# Try configured account
DATA=$(security find-generic-password -s "$SERVICE" -a "$ACCOUNT" -w 2>&1)
if validate_data "$DATA"; then
    log "✓ Using account: $ACCOUNT"
else
    log "⚠ Trying fallback accounts..."
    for fallback in "claude" "Claude Code" "default"; do
        DATA=$(security find-generic-password -s "$SERVICE" -a "$fallback" -w 2>&1)
        if validate_data "$DATA"; then
            ACCOUNT="$fallback"
            log "✓ Found data in: $fallback"
            break
        fi
    done
fi

[[ -z "$DATA" ]] || ! validate_data "$DATA" && error "No valid data found
Tried accounts: $ACCOUNT, claude, Claude Code, default
Verify with: security find-generic-password -l '$SERVICE'"

REFRESH_TOKEN=$(echo "$DATA" | jq -r '.claudeAiOauth.refreshToken')

改进点:

  • ✅ 明确的账户参数
  • ✅ 验证数据结构
  • ✅ 自动回退至通用名称
  • ✅ 附带验证命令的有用错误提示

常见反模式

反模式一:"在我机器上能跑"

FILE="/Users/patrick/.config/app.json"  # Hardcoded path

修复方案:使用$HOME环境变量、检测操作系统,或使其可配置


反模式二:"但愿它在那里"

TOKEN=$(cat config.json | jq -r '.token')
# What if .token doesn't exist? Script continues with empty value

修复方案:使用前先验证

TOKEN=$(cat config.json | jq -r '.token // empty')
[[ -z "$TOKEN" ]] && error "No token in config"

反模式三:"首个匹配即正确"

# If multiple entries exist, which one?
ENTRY=$(find_entry "service")

修复方案:明确指定或枚举所有可能

ENTRY=$(find_entry "service" "account")  # Specific
# OR
ALL=$(find_all_entries "service")
for entry in $ALL; do
    validate_and_use "$entry"
done

反模式四:"静默失败"

process_data || true  # Ignore errors

修复方案:附带上下文信息明确报错

process_data || error "Failed to process
Data: $DATA
Expected: { ... }
Check: command_to_verify"

与现有工作流集成

在 sprint-plan.md 中

添加到测试环节:

## Cross-Device Testing
- [ ] Test with different account names
- [ ] Test with wrong config values
- [ ] Test with missing data
- [ ] Document fallback behavior

在 PRIVACY-CHECKLIST.md 中

发布前添加:

## Portability Check
- [ ] No hardcoded paths (use $HOME, detect OS)
- [ ] No hardcoded names (use config or fallback)
- [ ] Validation on all inputs
- [ ] Helpful errors for common issues

在技能创建器中

构建新技能时:

  1. 列出设备间的差异项
  2. 使其可配置或能自动发现
  3. 使用错误配置进行测试
  4. 文档问题排查

快速参考卡

编写代码前:

  1. 设备间有何差异?
  2. 如何证明此方案有效?
  3. 发生故障时会出现什么情况?

强制性模式:

  • 显式优于隐式
  • 使用前验证
  • 回退链
  • 有用的错误信息

测试:

  • 正确配置 → 正常工作
  • 错误配置 → 回退机制或有用的错误信息
  • 数据缺失 → 清晰的诊断信息

文档:

  • 数据流程图
  • 常见变体
  • 故障排查指南

成功标准

当工具具备以下特性时:可移植性即视为:

  1. ✅ 无需修改即可在不同设备上运行
  2. ✅ 自动发现配置中的常见变体
  3. ✅ 优雅失败并提供可操作的错误信息
  4. ✅ 通过阅读错误输出即可调试
  5. ✅ 文档涵盖“如果我的设置不同怎么办”

测试:交给配置不同的人使用。如果他们需要向你提问,说明该工具尚未具备可移植性。


起源故事

该方法论源于调试OAuth刷新器时(2026-01-23):

  • 脚本读取了错误的钥匙串条目(未指定账户)
  • 假设存在单一条目(实际存在多个)
  • 缺乏验证(使用了空数据)
  • 没有备用方案(在不同账户名称上失败)

帕特里克的方法:

  1. 要求提供精确数据(有多少条目,哪个包含令牌)
  2. 要求提供证明(显示刷新前/后的令牌)
  3. 考虑跨设备情况(如果命名方式不同怎么办?)

结果:该工具从仅限单设备/故障状态升级为通用/生产就绪状态。

关键洞察:问题不在逻辑本身——而在于预设条件。


何时使用此技能

适用于以下情况:

  • 构建读取系统配置的工具时
  • 处理密钥链、凭证、环境变量时
  • 创建在多台机器上运行的脚本时
  • 在ClawdHub发布技能时(供他人使用)

实施步骤:

  1. 实施前:回答三个问题
  2. 实施中:采用强制模式
  3. 测试前:执行起飞前检查清单
  4. 测试后:记录差异与故障排除方案

牢记:您的设备只是特例。请为通用情况构建解决方案。

免责申明
部分文章来自各大搜索引擎,如有侵权,请与我联系删除。
打赏
文章底部电脑广告
手机广告位-内容正文底部
上一篇:Codesession 下一篇:TRMNL Display

相关文章

您是本站第321874名访客 今日有133篇新文章/评论