用途:在创建或审查 Elixir 项目、CLI 等场景下,按惯用方式编写并发 Elixir 代码。资料强调进程是轻量的,用监督者建模失败,而不是到处 try;Phoenix/Ecto 归 phoenix 技能。
工具链:Mix(mix new,多应用时用 umbrella)、Hex 管理依赖并在 mix.exs/mix.lock 中谨慎锁定版本;运行 mix test、mix format、mix credo(若项目使用)、mix dialyzer(若有 Dialyzer)。新代码用 Elixir 1.20+/OTP 27+,并遵守仓库 .tool-versions;编译器与类型系统警告需在改动范围内处理。
组织:lib/ 下 my_app.ex 作为精简公开 API,my_app/application.ex 放监督树,test/test_helper.exs;umbrella 用 apps/。按领域分模块,MyApp 重导出稳定 API;纯代码与 OTP 进程分离,内部实现用 defp,不暴露 internals。
语言:在函数边界用模式匹配与 guards;用 |> 做转换;structs 与 map 使用已知原子键,外部输入用 String.to_existing_atom/1;公开 API 写 @spec,领域类型用 @type/@typedoc;用 with 处理 {:ok, _}/{:error, _} 且不吞掉错误分支;用递归+累加器,Enum/Stream 处理集合。
OTP:Application 只启动监督树;Supervisor 默认 :one_for_one,子进程 restart: :permanent(除非确为 transient);GenServer 状态最小化,handle_call 请求响应、handle_cast 即发即弃、handle_info 外部消息;call 显式超时,不无理由用 :infinity;Task/Task.Supervisor 做一次性工作;Registry/DynamicSupervisor 管理按 id 的实例;消息用带标签元组;状态放在属主进程,避免过早用 ETS,领域逻辑不用 Agent。
错误与并发:监督树内 let it crash;可预期的输入/IO 错误返回 {:error, reason};raise/throw 仅用于编程不变量;try/rescue 放在 JSON、HTTP、磁盘等边界;重要操作用 :telemetry 与结构化日志。进程隔离、一封进程一块状态;mailbox 需背压;不用 :persistent_term 存可变数据;注意超时与关闭。
测试:ExUnit,async: true(无全局状态时),start_supervised!/1,优先 fakes/ports 而非重度 mock,改动范围 mix test 需通过。
反模式:万能 GenServer、对外部输入用 String.to_atom/1、大热路径用 Enum、生产环境 Process.sleep、空监督者或关键服务 restart: :temporary、假设本技能含 Phoenix(MyAppWeb、LiveView、Ecto.Repo)。
集成与完成标准:Web/LiveView/Ecto 用 phoenix,HTTP 契约用 api-design,容器部署用 docker;代码格式化、处理编译器警告、API 返回 {:ok, _}/{:error, _} 或有理由的 raise、进程在监督下、显式超时、公开函数有 typespec、关键路径 ExUnit 测试通过。