写了 10 个 Agent Skill 后,我把 300 行重复代码压到了 30 行
1. 引言在最近的一个 AI Agent 项目中我陆续编写了 10 个不同的 Agent Skill。每个 Skill 都负责一个独立的业务能力比如查询天气、发送邮件、调用内部 API、解析文档等。写第一个 Skill 时很顺畅写第二个也还行但写到第五个时我发现自己陷入了 CtrlC / CtrlV 的泥潭。每个 Skill 都包含几乎相同的模板代码参数校验、错误处理、日志记录、结果格式化……10 个 Skill 下来光这些重复的“骨架”代码就堆了将近 300 行。这不仅让代码库变得臃肿更可怕的是——每次要修改公共逻辑比如统一日志格式就得手动改 10 个文件。于是我决定重构。最终通过抽象公共基类和装饰器模式我把这 300 行重复代码压缩到了 30 行。这篇文章就来分享我是怎么做到的。2. 问题重现一个典型的 Agent Skill 长什么样先看一个典型的 Skill 实现。假设我们有一个WeatherSkill用于查询天气classWeatherSkill:def__init__(self,name:strweather):self.namename self.loggerlogging.getLogger(self.name)defcan_handle(self,intent:str)-bool:returnintentquery_weatherdefexecute(self,params:dict)-dict:# 参数校验ifcitynotinparams:return{success:False,error:Missing city parameter}# 业务逻辑try:resultself._query_weather(params[city])# 结果格式化return{success:True,data:result}exceptExceptionase:self.logger.error(fFailed to query weather:{e})return{success:False,error:str(e)}def_query_weather(self,city:str)-dict:# 实际的 API 调用return{temperature:25,condition:sunny}看起来还不错但当你写出第 2 个、第 3 个 Skill 时你会发现__init__、can_handle、execute里的参数校验、异常捕获、日志记录、返回格式——这些代码几乎一模一样。3. 重复代码的统计与分析我整理了 10 个 Skill 的代码统计了重复部分重复模块每个 Skill 行数10 个 Skill 总行数__init__初始化3 行30 行can_handle意图匹配3 行30 行execute参数校验5 行50 行executetry-except 包裹6 行60 行日志记录4 行40 行结果格式化3 行30 行其他类型注解、文档字符串等6 行60 行合计30 行300 行核心业务逻辑真正的 API 调用、数据处理只占每个 Skill 的 20% 左右。80% 的代码都是“基础设施”。4. 重构方案抽象基类 装饰器我的目标是让每个 Skill 只写业务逻辑其余全部由框架自动完成。4.1 定义抽象基类首先创建一个BaseSkill把公共逻辑全部收进来importloggingfromabcimportABC,abstractmethodfromfunctoolsimportwrapsclassBaseSkill(ABC):def__init__(self,name:strNone):self.namenameorself.__class__.__name__.lower()self.loggerlogging.getLogger(self.name)defcan_handle(self,intent:str)-bool:# 默认通过类名匹配子类可覆盖returnintentself.namedefexecute(self,params:dict)-dict:# 统一的执行入口自动包裹校验和异常处理try:self._validate(params)resultself._execute(params)returnself._format_result(result)exceptExceptionase:self.logger.error(fExecution failed:{e},exc_infoTrue)return{success:False,error:str(e)}def_validate(self,params:dict):子类可重写默认不做校验passabstractmethoddef_execute(self,params:dict)-dict:子类必须实现真正的业务逻辑passdef_format_result(self,result:dict)-dict:子类可重写默认包装为成功响应return{success:True,data:result}4.2 用装饰器处理参数校验对于需要参数校验的 Skill我写了一个装饰器避免在每个_execute里写 if-elsedefrequire_params(*required_keys):defdecorator(func):wraps(func)defwrapper(self,params:dict,*args,**kwargs):missing[kforkinrequired_keysifknotinparams]ifmissing:raiseValueError(fMissing required parameters:{missing})returnfunc(self,params,*args,**kwargs)returnwrapperreturndecorator4.3 重构后的 Skill 长什么样现在一个 Skill 只需要 3 行核心代码classWeatherSkill(BaseSkill):require_params(city)def_execute(self,params:dict)-dict:return{temperature:25,condition:sunny}另一个 Skill 也类似classEmailSkill(BaseSkill):def__init__(self):super().__init__(namesend_email)require_params(to,subject,body)def_execute(self,params:dict)-dict:# 真正的发邮件逻辑return{message_id:12345,status:sent}5. 效果对比重构前后对比指标重构前重构后每个 Skill 平均代码行数30 行3 行10 个 Skill 总行数300 行30 行公共逻辑修改改 10 个文件改 1 个基类新增一个 Skill 成本30 行模板 业务3 行业务单元测试覆盖难模板代码干扰易只测业务更重要的是可维护性得到了质的提升。后来我又加了 5 个 Skill每个只花了 5 分钟写业务逻辑再也不用复制粘贴了。6. 总结与思考这次重构让我深刻体会到重复代码是万恶之源。当你在写第 3 个相似的类/函数时就该停下来思考抽象方案了。抽象基类 装饰器是消除 Agent Skill 模板代码的绝佳组合。基类负责骨架装饰器负责横切关注点参数校验、权限检查等。不要过度抽象。我的原则是只有出现 3 次以上重复时才考虑抽象。过早抽象反而会增加理解成本。代码行数不是唯一目标。虽然从 300 行压到了 30 行但更重要的是代码的可读性和可维护性。30 行清晰的代码远胜 300 行重复的代码。如果你也在写 Agent 或类似的插件化系统不妨试试这个模式。你会发现写代码可以是一件很清爽的事。

相关新闻

QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)

QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)

一、基础定位、头文件、继承关系 1. 引入头文件 #include <qgssinglebandpseudocolorrenderer.h>2. 继承链 QgsRasterRenderer↳ QgsSingleBandRenderer↳ QgsSingleBandPseudoColorRendererQgsRasterRenderer&#xff1a;栅格渲染器顶层抽象基类&#xff0c;所有栅格渲染…

2026/10/24 23:27:49 阅读更多 →
Qwen3-8B大模型本地化部署与vLLM优化实践

Qwen3-8B大模型本地化部署与vLLM优化实践

1. 项目背景与核心价值 在当前的AI技术浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;的本地化部署正成为开发者关注的焦点。Qwen3-8B作为通义千问团队推出的80亿参数开源模型&#xff0c;在中文理解和生成任务上展现出接近商用闭源模型的性能。而vLLM作为UC Berkel…

2026/10/25 19:59:59 阅读更多 →
Typora如何设置字体颜色

Typora如何设置字体颜色

1. 需要打开文件的偏好设置——>markdown扩展语法中——>勾选内联公式。2. 在编辑器中&#xff0c;使用 $\textcolor{颜色}{.......}$ latex语法即可修改颜色​举例&#xff1a;我想要把hello world修改成红色。$\textcolor{red}{hello world}$输入后敲击回车&#xff…

2026/10/26 14:47:11 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/10/25 22:36:10 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/26 4:52:12 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/10/26 5:00:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/10/26 3:16:46 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 12:00:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →