Learning Output Style 交互式学习模式插件
Learning Output Style 插件结合了教育性见解和交互式学习,在关键决策点要求用户参与编写代码,将体验从"观看并学习"转变为"构建并理解"。
概述
Learning Output Style 插件是一个增强型学习工具,它不仅提供教育性见解(类似 Explanatory Output Style),还会在关键决策点要求用户亲自编写代码。这种"边做边学"的方式能够显著提升学习效果。
核心理念
mermaid
graph LR
A[观看并学习] --> B[构建并理解]
A1[Claude 编写代码] --> A
A2[用户被动观看] --> A
B1[Claude 识别学习机会] --> B
B2[用户主动编写代码] --> B
B3[Claude 提供反馈] --> B
style A fill:#ffcdd2
style B fill:#c8e6c9学习哲学:
"Learning by doing is more effective than passive observation." — 边做边学比被动观察更有效
与 Explanatory Output Style 的区别
| 特性 | Explanatory | Learning |
|---|---|---|
| 教育性见解 | ✅ | ✅ |
| 被动学习 | ✅ | ✅ |
| 主动编码要求 | ❌ | ✅ |
| 用户参与度 | 低 | 高 |
| 令牌消耗 | 中等 | 较高 |
安装与配置
插件安装
bash
# 安装 learning-output-style 插件
/plugin install learning-output-style@claude-plugins-official目录结构
plugins/learning-output-style/
├── .claude-plugin/
│ └── plugin.json
├── README.md
├── hooks/
│ └── hooks.json # 钩子配置
└── hooks-handlers/
└── session-start.sh # 会话启动脚本配置文件 (plugin.json)
json
{
"name": "learning-output-style",
"version": "1.0.0",
"description": "Interactive learning mode that requests meaningful code contributions at decision points (mimics the unshipped Learning output style)",
"author": {
"name": "Boris Cherny",
"email": "boris@anthropic.com"
}
}工作原理
交互式学习流程
mermaid
sequenceDiagram
participant U as 用户
participant C as Claude
U->>C: 请求功能实现
C->>C: 分析任务,识别学习机会
alt 有学习机会
C->>U: 🎯 请尝试编写这部分代码
C->>U: 提供指导和上下文
U->>C: 提交代码尝试
C->>U: 反馈和改进建议
else 无学习机会(样板代码)
C->>U: 直接实现代码
end
C->>U: 完成任务 + 教育性见解识别学习机会
Claude 会在以下决策点请求用户参与:
| 类别 | 示例 |
|---|---|
| 业务逻辑 | 有多个有效实现方法的逻辑 |
| 错误处理策略 | 如何处理不同类型的错误 |
| 算法选择 | 选择哪种排序/搜索算法 |
| 数据结构决策 | 使用数组、Map 还是 Set |
| 用户体验决策 | 表单验证时机、错误消息展示 |
| 设计模式选择 | 策略模式 vs 状态模式 |
直接实现的情况
Claude 不会在以下情况要求用户参与:
| 类别 | 示例 |
|---|---|
| 样板代码 | 导入语句、配置文件 |
| 重复代码 | 已有模式的复制 |
| 明显实现 | 没有有意义选择的代码 |
| 配置代码 | 环境设置、工具配置 |
| 简单 CRUD | 基础的增删改查操作 |
输出示例
示例 1:错误处理策略
用户请求:添加 API 调用的错误处理
Claude 输出:
★ Insight ─────────────────────────────────────
1. 错误处理是区分初级和高级开发者的关键技能
2. 好的错误处理应该区分不同类型的错误并采取相应措施
─────────────────────────────────────────────────
🎯 学习机会:请尝试编写错误处理逻辑
这是一个很好的学习机会!请尝试实现 fetchUserData 函数的错误处理。
上下文:
- API 可能返回 401(未授权)、404(未找到)、500(服务器错误)
- 网络可能断开
- 用户需要看到有意义的错误消息
请在下方编写你的实现:
async function fetchUserData(userId) {
// 你的代码在这里
// 提示:考虑使用 try-catch 和不同的错误类型处理
}用户提交:
javascript
async function fetchUserData(userId) {
try {
const response = await api.get(`/users/${userId}`);
return response.data;
} catch (error) {
if (error.response?.status === 401) {
throw new Error('请先登录');
}
throw error;
}
}Claude 反馈:
很好的开始!你正确地使用了 try-catch 并处理了 401 错误。
💡 改进建议:
1. 处理更多错误类型:
async function fetchUserData(userId) {
try {
const response = await api.get(`/users/${userId}`);
return response.data;
} catch (error) {
if (!error.response) {
// 网络错误
throw new NetworkError('无法连接到服务器,请检查网络');
}
switch (error.response.status) {
case 401:
throw new AuthError('请先登录');
case 404:
throw new NotFoundError('用户不存在');
case 500:
throw new ServerError('服务器错误,请稍后重试');
default:
throw new ApiError('请求失败');
}
}
}
★ Insight ─────────────────────────────────────
1. 区分网络错误(无 response)和 API 错误(有 response)
2. 使用自定义错误类可以让调用者更容易处理不同情况
3. 用户友好的错误消息比技术性消息更有帮助
─────────────────────────────────────────────────示例 2:数据结构选择
用户请求:实现一个去重功能
Claude 输出:
🎯 学习机会:数据结构选择
去重是一个常见需求,有多种实现方式。请思考并选择一种:
需求:
- 输入:可能包含重复项的数组
- 输出:去重后的数组
- 保持原始顺序
请实现这个函数:
function removeDuplicates(array) {
// 你的实现
}
提示:考虑 Set、filter + indexOf、reduce 等方法用户提交:
javascript
function removeDuplicates(array) {
return [...new Set(array)];
}Claude 反馈:
✅ 优秀!这是最简洁的解决方案!
★ Insight ─────────────────────────────────────
1. Set 自动去重且保持插入顺序(ES6+)
2. 展开运算符 [...] 将 Set 转回数组
3. 时间复杂度 O(n),比 filter + indexOf 的 O(n²) 更优
─────────────────────────────────────────────────
扩展思考:如果要去重对象数组呢?
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice' } // 重复
];
// Set 不能直接用于对象,需要不同策略
function removeDuplicateUsers(users) {
const seen = new Map();
return users.filter(user => {
if (seen.has(user.id)) return false;
seen.set(user.id, true);
return true;
});
}示例 3:业务逻辑决策
用户请求:实现购物车折扣计算
Claude 输出:
★ Insight ─────────────────────────────────────
1. 折扣逻辑是典型的业务规则,需要仔细设计
2. 好的实现应该易于扩展和修改
─────────────────────────────────────────────────
🎯 学习机会:业务逻辑设计
请实现购物车折扣计算逻辑:
规则:
- 订单满 100 元,打 9 折
- 订单满 200 元,打 8 折
- VIP 用户额外 95 折
- 折扣可叠加
function calculateDiscount(order) {
// order = { items: [...], total: 250, isVip: true }
// 返回最终价格
}
思考:如何让这个逻辑易于维护?如果未来要添加更多折扣规则呢?配置与自定义
调整学习频率
可以通过修改 session-start.sh 来调整请求用户编码的频率:
默认:在所有有意义的决策点请求
保守:仅在关键决策点请求
bash
#!/bin/bash
cat << 'EOF'
Learning mode active. Request user code contributions only for:
- Core business logic with multiple valid approaches
- Algorithm implementation choices
- Architecture decisions
Skip code contribution requests for:
- Utility functions
- Standard patterns
- Minor implementation details
EOF禁用特定场景
如果某些场景不需要学习模式:
bash
# 在提示词中说明
"请直接实现代码,不需要我参与编写"
# 或临时禁用插件
/plugin disable learning-output-style成本考虑
⚠️ 注意:此插件会显著增加令牌消耗
令牌影响
| 类型 | 额外消耗 |
|---|---|
| 输入令牌 | 会话启动指令 ~400 令牌 |
| 输出令牌 | 每个学习机会 ~200-300 令牌 |
| 交互轮次 | 增加 50-100% |
使用建议
- 有目的地使用:确认是学习场景再启用
- 会话管理:完成学习后可以禁用
- 混合使用:学习任务用此插件,生产任务用常规模式
与 Explanatory 插件的选择
选择指南
mermaid
graph TD
A{需要学习吗?} -->|是| B{愿意编码吗?}
A -->|否| C[不使用插件]
B -->|是| D[Learning Output Style]
B -->|否| E[Explanatory Output Style]
D --> D1[主动学习<br/>高参与度<br/>高令牌成本]
E --> E1[被动学习<br/>低参与度<br/>中等令牌成本]
style D fill:#c8e6c9
style E fill:#e3f2fd
style C fill:#f5f5f5场景对照
| 场景 | 推荐插件 |
|---|---|
| 学习新技术/框架 | Learning |
| 理解现有代码 | Explanatory |
| 培训新团队成员 | Learning |
| 日常开发(需要解释) | Explanatory |
| 日常开发(快速完成) | 无 |
| 技术面试准备 | Learning |
常见问题
Q: 如何跳过某个学习机会?
A: 直接告诉 Claude:
- "请直接给我答案"
- "这个我已经熟悉了,请直接实现"
Q: 我的代码写错了怎么办?
A: Claude 会提供反馈和改进建议,这正是学习的好机会!
Q: 可以同时使用两个输出风格插件吗?
A: 不建议。Learning 已经包含了 Explanatory 的所有功能。
Q: 如何最大化学习效果?
A:
- 在提交代码前先思考
- 阅读 Claude 的反馈
- 尝试理解改进建议背后的原因
- 在其他项目中应用学到的模式
总结
Learning Output Style 插件将 Claude Code 转变为交互式学习工具:
- 主动学习 - 在关键点要求用户编写代码
- 智能识别 - 区分有意义的学习机会和样板代码
- 即时反馈 - 对用户代码提供改进建议
- 教育性见解 - 保留 Explanatory 的所有功能
适合希望在使用 Claude Code 时真正掌握编程技能的开发者。
参考资源
- GitHub 源码 - 官方插件仓库
- Explanatory Output Style - 对比参考
本文档基于 learning-output-style 插件 v1.0.0 编写