Паттерны проектирования и лучшие практики для навыков
Паттерны проектирования навыков, отточенные обширной практикой, помогают быстро принимать верные решения при появлении новых требований.
В этой статье собраны 7 самых часто используемых паттернов проектирования и сценарии их применения.
Паттерн 1: Навык с единственной ответственностью
Каждый навык делает одно дело и делает его хорошо.
Чем более сфокусирована функциональность, тем точнее описание, тем выше точность срабатывания и тем проще сопровождение.
| Подход | Пример |
|---|---|
| Правильно: единственная ответственность | pdf-to-text (занимается только извлечением текста) |
| Неправильно: смешанные обязанности | pdf-tools (чтение, конвертация, объединение, нанесение водяных знаков... всё в одном месте) |
Если вы обнаружите, что описание навыка должно быть очень длинным, чтобы прояснить, чего он «не делает», это обычно означает, что он взял на себя слишком много обязанностей и его следует разделить.
Паттерн 2: Защитная проверка входных данных
Выполняйте всю проверку входных данных централизованно в точке входа скрипта навыка и переходите к бизнес-логике только после успешной проверки.
Пример
# Шаблон: Защитная проверка входных данных — централизованная валидация в точке входа, пропуск после успешного прохождения проверки
import sys
import os
import json
def validate(args) -> list:
"""Централизованно проверить все входные данные и вернуть список ошибок (пустой список означает, что все проверки пройдены)"""
errors = []
if not args.file:
errors.append("Отсутствует аргумент --file")
elif not os.path.exists(args.файл):
errors.append(f"Файл не существует: {args.file}")
elif os.path.getsize(args.file) == 0:
errors.append("Содержимое файла пусто")
if args.limit < 1:
errors.append("--limit должен быть больше 0")
return errors
def run(args):
"""Точка входа в бизнес-логику, вызывается только после успешной валидации"""
# Выполнить фактическую обработку...
return {"status": "success", "file": args.file}
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--file", required=False, default="")
parser.add_argument("--limit", type=int, default=100)
args = parser.parse_args()
# 1. Централизованная валидация
errors = validate(args)
if errors:
result = {"status": "input_error", "errors": errors}
print(json.dumps(result, ensure_ascii=False))
sys.exit(1)
# 2. Выполнить бизнес-логику после успешной валидации
result = run(args)
print(json.dumps(result, ensure_ascii=False))
Шаблон 3: Постепенный вывод
Для навыков, выполнение которых занимает более 5 секунд, прогресс должен выводиться поэтапно, а не оставлять пользователя в молчаливом ожидании.
## 执行流程(渐进式输出示例) ### 步骤一:读取文件 运行读取脚本后,立即告知用户: > 已读取文件:example_data.csv(1,024 行,8 列)正在进行数据清洗... ### 步骤二:数据清洗 清洗完成后,告知用户: > 数据清洗完成:删除重复行 3 条,空值填充 12 处。正在生成报告... ### 步骤三:生成报告 报告生成后,展示下载链接并说明内容: > 报告已生成,包含统计摘要和数据质量评估。
Шаблон 4: Идемпотентные операции
Результаты выполнения навыка должны быть идемпотентными: при одном и том же входе, сколько бы раз он ни выполнялся, вывод должен быть одинаковым.
Неидемпотентные операции (например, добавление содержимого при каждом выполнении) могут вызвать путаницу при повторных попытках пользователей.
Пример
import os
from datetime import datetime
OUTPUT_DIR = "/mnt/user-data/outputs"
def get_output_path(base_name: str, suffix: str = ".xlsx") -> str:
"""
Сгенерировать детерминированный путь вывода
Идемпотентный подход: перезаписывать одноимённый файл при каждом выполнении (вместо добавления или создания нового файла)
Обеспечить, чтобы один и тот же вход всегда соответствовал одному и тому же выходному файлу
"""
# Метод A: Фиксированное имя файла (один и тот же вход всегда перезаписывает)
return os.path.join(OUTPUT_DIR, f"{base_name}_report{suffix}")
# Метод B (отметка времени): генерировать новый файл каждый раз (неидемпотентно, но сохраняет историю)
# ts = datetime.now().strftime("%Y%m%d_%H%M%S")
# return os.path.join(OUTPUT_DIR, f"{base_name}_{ts}{suffix}")
Шаблон 5: Явный сигнал завершения
После завершения выполнения Skill он должен подать чёткий "сигнал завершения", чтобы пользователь знал, что задача завершена и не нужно продолжать ждать.
## 任务完成后的输出规范 无论成功还是失败,最后一步必须输出一个明确的状态行: 成功时: > 任务完成:报告已生成,共处理 1,024 行数据,耗时约 3 秒。 失败时: > 任务中断:在"数据清洗"步骤遇到错误(原因:文件编码不是 UTF-8)。 > 建议:将文件另存为 UTF-8 格式后重新上传。
Шаблон 6: Декларация совместимости версий
Объявляйте совместимые версии модели в frontmatter файла SKILL.md, чтобы предотвратить неожиданное поведение в неподдерживаемых средах.
---
name: data-analyzer
version: 1.2.0
description: 分析 CSV/Excel 数据,生成统计报告。
compatibility:
claude_models:
- claude-sonnet-4-20250514 # 经过验证的模型版本
- claude-opus-4 # 同样支持
python: ">=3.8"
platforms:
- linux # Claude 计算机使用环境
---
Шаблон 7: Быстрый отказ
Как только обнаружена ошибка, препятствующая продолжению, немедленно остановитесь и чётко сообщите об этом, вместо того чтобы продолжать выполнение с ошибкой и выдавать бессмысленный вывод.
Пример
import sys
import json
def assert_condition(condition: bool, message: str, hint: str = ""):
"""Если условия не выполнены, немедленно вывести ошибку и выйти (шаблон Fail Fast)"""
if not condition:
result = {
"status": "error",
"message": message,
"hint": hint
}
print(json.dumps(result, ensure_ascii=False))
sys.exit(1)
# Выполнить все предварительные проверки централизованно в начале скрипта
import os
file_path = sys.argv[1] if len(sys.argv) > 1 else ""
assert_condition(bool(file_path),
"Отсутствует аргумент пути к файлу",
"Использование: python script.py <путь к файлу>")
assert_condition(os.path.exists(file_path),
f"Файл не существует: {file_path}",
"Пожалуйста, проверьте, правильно ли указан путь, или загрузите файл заново")
assert_condition(file_path.endswith(".csv"),
"Формат файла не поддерживается, ожидается .csv",
f"Фактический файл: {file_path}")
# Все проверки пройдены, выполните фактическую логику
print(json.dumps({"status": "ok", "file": file_path}))
Краткий справочник по шаблонам
| Паттерн | Основной принцип | Решаемая проблема |
|---|---|---|
| Единственная ответственность | Один Skill делает одну вещь | Неточное срабатывание, сложно поддерживать |
| Защитная проверка входных данных | Централизованная валидация в точке входа | Ошибки сообщаются только на середине выполнения |
| Постепенный вывод | Сообщать о прогрессе поэтапно | Пользователи не знают, выполняется ли процесс |
| Идемпотентные операции | Тот же вход — тот же выход | Повторные попытки дают запутанные результаты |
| Явный сигнал завершения | Предоставлять уведомление о конечном состоянии по завершении | Пользователи не знают, завершена ли задача |
| Декларация совместимости версий | Объявите поддерживаемые среды выполнения | Аномальное поведение при несовпадении среды |
| Быстрый отказ | Немедленно останавливаться при ошибке | Продолжение работы при ошибках приводит к некорректному выводу |