SuperAPI AI 工具集

elixir-antipatterns

编程与开发

查看项目

更新于 10-15 15:17

技能介绍

用途

本技能是一份 Elixir/Phoenix 反模式目录,用于识别和规避会损害应用健壮性与可维护性的写法。核心目录包含 8 个关键反模式,主题分布为:错误处理 3 个、架构 2 个、性能 2 个、测试 1 个。

建议在以下场景加载:编写 Elixir 模块与函数;使用 Phoenix Framework(控制器、LiveView);构建 Ecto schema 与数据库查询;实现 BEAM 并发(Task、GenServer);使用标记元组处理错误;使用 ExUnit 编写测试。

主要能力(8 个核心反模式)

错误处理

  1. 用标记元组返回结果:应返回 {:ok, value} | {:error, reason},而不是返回 nil 或抛出异常。用 @spec 在函数签名中记录错误情形,模式匹配会强制调用方显式处理。

  2. 不要为业务错误使用 raise:例如不要写 Repo.get(User, id) || raise "User not found",而应返回 {:error, :not_found}。

  3. 不要在 with 的失败操作中使用 =:with {:ok, user} <- fetch_user(id), validated = validate(user), ... 中 = 不会检查 {:error, _},应改为 {:ok, validated} <- validate(user)。

架构与边界

  1. 不要把业务逻辑放在 LiveView:校验与数据操作应委托给 context(如 Accounts.create_user/1),LiveView 只处理 UI 与事件分发。好处是 context 无需 Phoenix 即可测试,逻辑可复用。

  2. 不要在 with 中串联超过 4 步:过多的职责应聚合为内聚函数,例如分为 validate_and_fetch/1、process_business_rules/1、persist_and_notify/1 三段。

数据与性能

  1. 不要在循环中查询(N+1):应使用 User |> Repo.all() |> Repo.preload(:posts),将 100 个用户场景从 101 次查询降为 2 次。资料给出的影响对比为:100 用户下 N+1 约 10 秒,preload 约 5ms。若需要复杂过滤(如 WHERE posts.status = 'published'),应使用 join + preload,具体写法参见 EXTENDED.md。

  2. 不要在缺少索引的列上频繁查询:在迁移中为常查询列创建索引,例如 create unique_index(:users, [:email]),避免在百万行级数据上全表扫描。

测试

  1. 不要编写没有断言的测试:每个测试都应断言预期行为,例如 assert {:ok, user} = UserService.create_user(%{name: "Juan"}) 并进一步断言 user.name == "Juan"。

使用方式

资料提供的使用方式为:在相应开发场景中加载本技能作为参考,按其中 ❌ BAD / ✅ CORRECT 代码示例对照修改。风格约束可配合 mix format 与 Credo。更多模式与深入示例参考 EXTENDED.md(资料提到其中包含 40 多个反模式,具体内容暂未提供)。

快速对照表

场景 反模式 正确模式
错误处理 raise "Not found" {:error, :not_found}
数据缺失 返回 nil {:error, :not_found}
业务逻辑 放在 LiveView 放在 context 模块
关联数据 Enum.map + Repo.get Repo.preload
with 链 validated = fn() {:ok, validated} <- fn()
频繁查询 无索引 create index(:table, [:column])
测试 无断言 assert 预期行为
复杂逻辑 6 步以上 with 聚合为 3 个函数

适用场景

Elixir 模块与函数编写、Phoenix 控制器与 LiveView 开发、Ecto schema 与查询构建、BEAM 并发(Task、GenServer)、标记元组错误处理、ExUnit 测试编写。

限制

资料未说明该技能的安装方式、运行环境要求、授权与收费信息,暂未提供。EXTENDED.md 中 40 多个模式的具体清单与示例内容,资料仅提及存在而未展开。