如何用 ECC 开发 F 项目并做函数式代码审查?
2026/9/10 18:41:43 网站建设 项目流程

如何用 ECC 开发 F# 项目并做函数式代码审查?

【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC

在 Claude Code 里开发 F# 项目时,通常要同时解决两件事:代码要符合函数式惯例(不可变、模式匹配、Option/Result而不是 null 和异常),以及改完代码后有一道可重复的审查关卡。ECC 提供的是一套组合方案:rules/fsharp规则包负责在编码阶段约束.fs/.fsx文件,fsharp-testing技能给出测试栈和运行方式,fsharp-reviewer子代理负责在改动完成后按固定优先级做函数式代码审查,并给出 Approve / Warning / Block 结论。

准备条件

  • 已安装并登录claudeCLI,ECC 插件已装入。可用下面的命令确认插件状态:
/plugin list ecc@ecc
  • 注意:Claude Code 插件机制无法随插件分发rules,所以 F# 规则包必须手动复制到规则目录,这一步无法省略(参见 README 中 "Claude Code plugins cannot distributerules" 的说明)。
  • 审查与测试命令依赖本机可用的dotnetCLI;格式检查依赖fantomas(文档说明“if available”,即没有时可跳过该检查)。

第一步:安装 F# 规则包

规则按“common 通用层 + 语言层”组织,F# 语言层扩展 common 层,并通过../common/相对路径引用通用规则。因此必须复制整个目录,不能用/*把文件拍平,否则相对引用会断掉、同名文件会互相覆盖(见 rules/README.md)。

用户级安装(对所有 Claude Code 会话生效):

mkdir -p ~/.claude/rules/ecc cp -R rules/common ~/.claude/rules/ecc/ cp -R rules/fsharp ~/.claude/rules/ecc/

项目级安装(只对当前仓库生效,规则放在项目根目录的.claude/rules/ecc下):

mkdir -p .claude/rules/ecc cp -R rules/common .claude/rules/ecc/ cp -R rules/fsharp .claude/rules/ecc/

注意这里复制的是rules/fsharp整个目录而不是其中的单个文件,原因同上。README 建议规则从common+ 一个你实际使用的语言包起步,因为规则是始终加载的上下文,装多了会占用 token。fsharp不在./install.sh文档示例列出的语言清单里,手动复制就是文档给出的安装方式。

第二步:按 F# 规则写代码

rules/fsharp下每个文件的 frontmatter 都声明了适用路径**/*.fs**/*.fsxtesting.md等还包含**/*.fsproj),即只要你编辑的是 F# 文件,这些规则就会作为始终加载的上下文生效。核心约束如下:

类型与不变性(coding-style.md):

  • 默认不可变,mutable只在性能有正当理由时使用;
  • 领域建模用可辨识联合(discriminated union)而不是类层次,数据用 record;
  • 用单例 union 包装原始类型做类型安全边界,例如type EmailAddress = EmailAddress of string
  • Option代替 null,用Result处理可能失败的操作,优先|>管道而不是 if/else 链。

错误处理(patterns.md):预期失败走Result<'T, 'TError>的铁路式编程,而不是抛异常;顺序可失败操作可以用result { }计算表达式:

let placeOrder request = result { let! validated = validateOrder request let! inventory = checkInventory validated.Items let! order = createOrder validated inventory return order }

系统边界验证(security.md):在应用边界用智能构造器拒绝非法输入,用private单例 union 保证只能从构造器进入类型:

type ValidatedEmail = private ValidatedEmail of string module ValidatedEmail = let create (input: string) = if System.Text.RegularExpressions.Regex.IsMatch(input, @"^[^@]+@[^@]+\.[^@]+$") then Ok(ValidatedEmail input) else Error "Invalid email address" let value (ValidatedEmail v) = v

同文件还要求:数据库访问必须用参数化查询(Dapper/EF Core 示例用@customerId参数占位),API key、连接串等秘密不得硬编码,本地开发用 user secrets,生产用 secret manager。

open 声明顺序(coding-style.md):open语句分四组、组间空行分隔、组内按字典序排序:System.*Microsoft.*→ 第三方命名空间 → 项目自身命名空间。

第三步:组织并运行测试

测试栈由 fsharp-testing 技能 与 rules/fsharp/testing.md 共同定义:

工具用途
xUnit测试框架
FsUnit.xUnitF# 风格断言(should equal
Unquote基于 F# quotation 的断言,失败信息展示完整表达式
FsCheck.xUnit属性测试
NSubstitutemock .NET 依赖
WebApplicationFactoryASP.NET Core 集成测试

目录约定是测试镜像src/结构放在tests/下,并区分 Unit / Integration / Properties / Helpers。一个用 Unquote 断言Result的最小单测(文档示例):

open Xunit open Swensen.Unquote [<Fact>] let ``PlaceOrder returns success when request is valid`` () = let request = { CustomerId = "cust-123"; Items = [ validItem ] } let result = OrderService.placeOrder request test <@ Result.isOk result @>

运行与验证命令(tests/MyApp.Tests/是文档示例中的测试项目路径,替换为你的测试项目):

dotnet build # 编译检查 dotnet test # 运行全部测试 dotnet test --filter "FullyQualifiedName~OrderService" # 按测试名过滤 dotnet test --collect:"XPlat Code Coverage" # 收集覆盖率 dotnet watch test --project tests/MyApp.Tests/ # 开发期 watch 模式

dotnet test --collect:"XPlat Code Coverage"会额外收集覆盖率报告,运行时间会比普通dotnet test长;文档建议的行覆盖目标是 80%+,重点放在领域逻辑、验证、认证和失败路径上。

可选:用 PostToolUse 钩子自动把关

rules/fsharp/hooks.md 建议在~/.claude/settings.json中配置 PostToolUse 钩子(会修改你的用户级 Claude Code 配置):

  • fantomas:编辑 F# 文件后自动格式化;
  • dotnet build:每次编辑后验证解决方案仍可编译;
  • dotnet test --no-build:行为变更后重跑最近相关的测试项目。

Stop 钩子则用于:大范围 F# 改动结束会话前跑一次最终dotnet build,以及在修改过appsettings*.json时给出警告,避免把秘密提交进仓库。不配置钩子也不影响后面的人工审查流程,钩子只是把编译与格式检查前移到每次编辑之后。

第四步:调用 fsharp-reviewer 做函数式代码审查

README 的 agent 对照表明确:F# 代码审查没有对应的 slash 命令,需要直接调用fsharp-reviewer子代理。其完整定义在 agents/fsharp-reviewer.md,frontmatter 声明工具为Read, Grep, Glob, Bash,模型为sonnet,描述要求“Use for all F# code changes. MUST BE USED for F# projects”。

被调用后,代理会按固定顺序动作:

git diff -- '*.fs' '*.fsx' # 查看本次 F# 文件改动 dotnet build # 编译检查 fantomas --check . # 格式检查(可用时执行)

然后只审查本次修改过的.fs/.fsx文件,按以下优先级分级:

  • CRITICAL(安全):SQL 注入(查询字符串拼接)、命令注入(Process.Start未验证输入)、路径穿越、不安全反序列化(BinaryFormatter)、硬编码秘密、CSRF/XSS;
  • CRITICAL(错误处理):吞掉异常(with _ -> ())、IDisposable未用use/use!释放、阻塞式 async(.Result.Wait()GetAwaiter().GetResult(),应改用let!/do!)、库代码中的裸failwith
  • HIGH(函数式惯例):领域逻辑中的mutable/ref、不完整的模式匹配(含隐藏新 union case 的_兜底)、可用List.map/Seq.filter/Array.fold表达的命令式循环、用 null 代替Option<'T>、能用模块 + 函数 + record 解决的类设计;
  • HIGH(类型安全):原始字符串/整数承载领域概念(应改单例 DU)、边界缺少验证(应用智能构造器)、无类型测试的:?>下转型、obj装箱;
  • HIGH(代码质量):超过 40 行的函数、超过 3 层的嵌套、缺少[<RequireQualifiedAccess>]、未使用的open
  • MEDIUM(性能):热路径上重复求值的懒Seq(应Seq.toList/Seq.toArray物化)、循环内字符串拼接(应StringBuilderString.concat)、值类型经obj传递造成的装箱、EF Core 循环中的 N+1 查询;
  • MEDIUM(惯例):命名(函数/值 camelCase,类型/模块/DU case PascalCase)、过长的管道链拆成命名中间绑定、task { task { } }嵌套压平为let!

如何解读审查输出

代理按固定格式输出每条发现:

[SEVERITY] Issue title File: path/to/File.fs:42 Issue: Description Fix: What to change

判定标准是明确的三分支:

  • Approve:没有 CRITICAL 或 HIGH 问题;
  • Warning:只有 MEDIUM 问题,可谨慎合并;
  • Block:发现 CRITICAL 或 HIGH 问题,需要修完再提。

对 ASP.NET Core、EF Core、Fable 项目还有框架专项检查(Giraffe/Saturn handler 与中间件顺序、EF Core 迁移安全与AsNoTracking、Fable 的 Elmish 架构),只在你使用这些框架时相关。

限制与下一步

  • 规则是始终加载的上下文,rules/fsharprules/common合计只有 10 个文件,但 README 建议只装common+ 一个实际语言包,不要在无需要求下叠加更多 pack。
  • 当语言规则与 common 规则冲突时,语言规则优先(specific overrides general),这是 rules/README.md 声明的覆盖规则。
  • 审查聚焦于本次 diff 中的.fs/.fsx改动;如果fantomas未安装,格式检查会被跳过,审查只剩编译检查与人工规则核对。
  • 更深入的 .NET 模式与测试参考,代理文档指向dotnet-patternsfsharp-testing两个技能,仓库内可直接阅读 skills/fsharp-testing/SKILL.md。

完成一轮的判定标准就是上面三条可核对的结果:dotnet build通过、dotnet test(可按需带覆盖率收集)通过、fsharp-reviewer给出的结论落在 Approve 或只有 MEDIUM 的 Warning 档。出现 Block 时,按[SEVERITY]清单从 CRITICAL/HIGH 项逐条修复后重新触发审查即可。

【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询