最近用Cursor(Claude 3.7 Sonnet那个模型)写一个FastAPI项目,确实快,但一个月下来review代码时发现,它特别喜欢把逻辑塞进一个超长的service函数,然后疯狂用依赖注入,还老爱生成pydantic的嵌套model。我原本习惯写扁平一点的模块结构,现在感觉自己的代码风格被它悄悄改写了,有点别扭。
用Cursor写后端一个月,感觉代码风格被它带偏了,大家有这问题吗?
全部回复
共 43 条我倒觉得这不完全是坏事,Claude 3.7确实有它自己的“审美”,但关键是它把模式撞到你面前,逼着你思考为什么这么写。你提到超长service函数,我猜它可能是为了把业务编排和基础设施解耦,但如果你项目没那么复杂,这确实显得过度设计。我最近也遇到类似情况,后来干脆在系统提示里写清楚“保持扁平模块,单个函数不超过40行,少用嵌套model”,效果好很多。不过有一点我得提醒你,依赖注入这东西在FastAPI里其实是加分项,测试时mock特别方便,别一棍子打死。真正要警惕的是,你长期用AI写代码,会慢慢失去对“为什么这么设计”的敏感度,因为每次都是直接拿结果。我现在的做法是让它先给方案,我自己挑一个改,而不是全盘接受。你要是觉得别扭,可以试试每周抽一天纯手写,找找手感,不然真会被带偏到回不去。
同感,我最近也发现它特别喜欢依赖注入,明明几行能搞定的事非要绕一大圈。
我后来是写完立刻重构,不然堆一个月再看真是头大。
确实有同感,Claude写代码特别喜欢套一层层抽象,我上次让它改个查询逻辑,结果给我整出三个嵌套的service外加一堆type alias,看着都累。后来我学乖了,prompt里明确写“保持扁平结构,别搞依赖注入”,输出就正常多了。你也可以试试在项目里建个AGENTS.md或者规则文件,把风格约束写进去,它每次都会遵守。另外感觉这种“风格漂移”其实挺正常的,毕竟工具用久了总会互相影响,关键还是自己review的时候心里有数。
确实有同感,Claude 3.7写业务代码特别喜欢“高内聚”那一套,一个service恨不得把整个业务流程都包圆了。不过后来我想通了,这玩意儿本质是“平均风格”,它只是把社区里最常见的写法堆给你,未必适合你的项目。我现在会刻意在prompt里强调“保持扁平结构,不要过度抽象”,效果好了不少。另外你review的时候如果觉得别扭,干脆直接手动重构几个关键模块,让它下次照着你的风格来,AI适应人总比人适应AI容易。
这问题我太有同感了,用Cursor写了两周Java服务,回头一看代码全是它那套“模板感”极强的东西,什么Builder满天飞、每个方法都拆成Optional链式调用。最气的是它特别喜欢把简单逻辑包装成策略模式,搞得类数量翻了一倍,看着是“整洁”了,但实际维护起来反而要跳来跳去。我后来学乖了,每次让它生成前先在注释里明确写清楚“不要依赖注入,不要嵌套model,用平铺直叙的写法”,虽然还是会偶尔犯病,但至少能拉回一点自己的风格。其实我觉得这就像用惯了智能输入法,打字节奏会被潜移默化地改变,关键是你得定期回头审视自己的代码,把那些“AI味”重的地方手动重构掉。另外我还会刻意去读一些自己以前写的项目,找找那种手感的锚点,不然真容易越写越不像自己的。你有没有试过在项目里加个自定义的规则文件(比如针对linter或者代码模板)来约束它?我试了下,效果比单纯提示语好不少。
我倒觉得这不完全是坏事,长service加依赖注入在FastAPI里其实挺契合框架本身的风格,尤其项目大了以后测试会好写很多。但你说被“带偏”我特别理解,我有个朋友用Copilot写React,现在写什么都先来一层自定义hook,连静态页面都给你拆成七八个组件,看的人脑壳疼。我自己的经验是,AI生成的代码有个特点,它会把所有“最佳实践”都堆上去,不管你这个场景需不需要,结果就是过度设计。所以我现在用Cursor的时候,会刻意在prompt里加上“保持简单扁平”之类的约束,或者让它先写一版,我再手动拆掉一部分抽象。另外,嵌套的pydantic model其实还好,真正烦人的是它特别喜欢把类型注解写满,有时候连个局部变量都要搞个复杂类型,读起来反而费劲。你有没有试过让它用你以前的旧代码当风格参考?我觉得这个比口头指令管用得多。
我倒是有类似的体会,不过方向不太一样。我那个项目用Cursor写了一周,发现它特别爱搞抽象层,Controller、Service、Repository一个不落,我本来就是个喜欢直接写业务逻辑的人,看着那些多出来的文件属实心累。后来我特意在rules里加了条“保持扁平化,不要过度分层”,情况才好转一些,但有时候改完代码它还是会“手痒”给你重构回原来的样子,挺无奈的。我觉得这背后其实是个习惯问题,AI的“默认值”跟咱自己的编程直觉有冲突,用久了确实会被潜移默化。你那个超长service函数我倒是没遇到,可能是它觉得把所有依赖都注进去就算“设计良好”了?但说实话,嵌套pydantic model这个我太有共鸣了,有时候一个请求体套三层,看半天才捋清楚字段到底从哪来的。我现在会定期拿自己写的老代码喂给它当风格参考,让它学着点,虽然效果不完美,但比原来默认的那套至少顺眼多了。
确实有同感,Claude特别喜欢把东西往service层堆,依赖注入用得飞起,我回看自己手写的老项目都觉得陌生了。不过我倒觉得嵌套model有时候挺方便,至少响应结构清晰,就是改动时牵一发动全身有点头疼。你后来有试着在prompt里明确要求它保持扁平风格吗?我试过几次,感觉它能听懂但偶尔还是会犯老毛病。
确实有同感,Claude写业务代码时特别爱往一个文件里堆依赖注入,看它生成的service层我总觉得像在看Spring的Java代码。不过后来我试了试在项目根目录放个CLAUDE.md,把模块划分规则和代码风格写清楚,它生成的代码就规矩多了。你也可以试试给它喂几个你以前写的模块文件当few-shot样本,风格会贴合很多。
说实话我也有点这种感觉,不过我是反过来的。我本来写Go的,习惯了那种简单粗暴的扁平结构,用Cursor写Python项目时它老爱给我套Repository模式加抽象基类,review的时候看得我头大。后来我发现了,其实这玩意儿跟prompt关系很大,你得在项目说明文件里明确写清楚你的代码规范,比如函数别超过多少行、禁止过度嵌套之类的,不然它确实会按训练数据里的主流风格来。至于超长service函数,我猜可能是上下文窗口限制导致的,它没法像人一样站在全局视角拆模块,只能在一个函数里把事情堆完。我觉得你可以试试把大文件拆成小文件再让它续写,或者干脆每生成一段就手动refactor一下,别等着最后统一改,那样子工作量太吓人了。还有就是pydantic嵌套model这个,其实看场景吧,如果数据确实有层级关系那没啥问题,但如果只是为了类型好看硬造结构就有点过了。
我倒觉得这事儿挺正常的,用AI写代码本质上就是在跟另一个人的风格磨合,它那套长service加嵌套model的模式其实挺符合Claude的偏好的。不过你提到的依赖注入,我反而觉得用多了之后自己写测试的时候省了不少事,可能你还没适应过来?要不试试在prompt里直接写明你要扁平结构,它其实挺听话的。
同感,我用了两周就发现它在service层特别喜欢堆依赖注入,一个函数恨不得塞五六个参数,看着都累。后来我学乖了,每次让它改代码前先贴一段自己写的风格示例,或者明确要求它保持扁平结构,效果会好很多。不过说真的,它生成的pydantic嵌套模型在复杂业务下确实有优势,可能就是咱们还没适应这种范式转换吧。
说实话我也有同感,不过我是写Go的,它硬生生给我整出了一堆接口嵌套和工厂模式,明明一个struct加几个方法就能搞定的事。后来我仔细想了想,这其实反映的是模型训练数据里的“最佳实践”偏好,它默认你在构建一个会长期演进的大型系统,而不是一个需要保持简单直接的中型服务。我自己摸索出的办法是每写完一个功能就主动做一次“风格回滚”,把那些过度抽象的地方手动拆平,或者干脆在系统提示里明确写“偏好扁平结构,避免过度封装”。另外我怀疑它生成的长函数跟上下文窗口的注意力机制有关,容易在局部优化而忽略全局模块划分,所以现在我会先自己搭好骨架再让它填肉。你有没有试过让它先输出设计方案再写代码?我试了两次,感觉它能收敛不少,但代价是思考时间明显变长。
确实,它生成的代码结构化太强了,我后来都得手动拆函数才能找回自己的节奏。
同感,我现在就把它当高级补全用,整体架构还得自己拿主意。
我倒觉得这未必是坏事,Claude 3.7那个模型确实偏好高内聚的service层,但它生成的依赖注入结构其实挺规范的,只是跟你原本的扁平风格冲突了。我之前用Copilot写Go项目也有类似感觉,后来干脆把它的建议当参考模板,再手动拆成自己习惯的包结构,反而吸收了不少好的设计思路。不过你说得对,如果完全跟着它走,确实容易失去个人风格,毕竟代码最终是给人读的,不是给AI看的。你现在是打算继续磨合还是强制让它按你的风格来?
同感,我现在写代码前都得先想好结构再让它填,不然它老给你整出个千层饼架构。
说白了就是得自己把边界划清楚,不然AI真能顺着你的需求一路叠buff。
确实会这样,我后来都先自己搭好结构再让它填,不然越写越像它那一套。
我也有类似的感觉,不过我倒不觉得是模型“带偏”了,更像是它在迎合一种它认为“标准”的后端写法。你提到的超长service函数和疯狂依赖注入,其实在不少Python项目里本身就是常见套路,Cursor只是把它放大到极致了。我后来发现,与其说被它改风格,不如说我开始偷懒,懒得去拆那些它一把梭生成的逻辑。但问题是,这种写法在项目小的时候看着挺整洁,一旦业务分支多起来,那个service函数能长到让你怀疑人生。我现在会在prompt里直接加一句“保持函数粒度小,按职责拆分”,或者让它先给模块结构再写代码,效果会好不少。另外pydantic嵌套model那个是真的,它好像默认所有输入输出都得套三层,有时候一个接口返回就俩字段,它也能给你整出个Base、Create、Update、Response来。所以我的策略是,让它干脏活累活可以,但结构决策还是得自己拿,不然写着写着就变成它的形状了。
深有同感,我最近也发现它特爱套依赖注入,写着写着就跟着跑了。
我也有类似感觉,不过我倒觉得这跟模型关系不大,主要是它默认就往“能跑就行”的方向写。我后来在.cursorrules里加了几条约束,比如函数不超过40行、禁止无意义的嵌套model,情况好很多。但说实话,有时候它那种写法确实更省事,改着改着就懒得掰回来了。