明:CQRS 在 Elixir 中的实验

简介

学习编程语言时,通过动手项目实践往往能取得最佳效果,因为真实场景的挑战能加速技能掌握。凭借C#背景和对Brighter框架的持续贡献,我决定通过构建名为Ming的项目来深化Elixir技能。该项目在探索Elixir函数式编程范式的同时,实现了*CQRS(*命令查询职责分离)等设计模式。

Ming项目

Ming的设计灵感来源于Brighter框架Commanded,其核心目标是将C#中的CQRS原则移植并适配到Elixir生态中。

名称由来

或许你会疑惑为什么选择"明"(Ming)这个名称。我希望这个库名简短易记,在发音上接近Brighter且便于英文交流。葡萄牙语命名未果后,正在学习中文的我发现"Ming"(明)的发音非常契合这个要求。

核心概念

处理器(Handlers)

Ming中的处理器是简单的模块,通过定义`execute/2`函数处理命令/事件和执行上下文。例如:

ruby 复制代码
defmodule SampleHandler do
  @moduledoc false

  def execute(%Ming.ExampleCommand1{}, %Ming.ExecutionContext{}), do: :ok
end

这种设计既保留了C#接口的简洁性,又利用Elixir的模式匹配特性提升了代码可读性。

命令/事件路由

通过use Ming.Router定义分发规则注册处理器:

ruby 复制代码
defmodule Ming.SampleRouter do
  @moduledoc false
  use Ming.Router

  dispatch [SampleCommand, SampleEvent], to: ReturningAKeyHandler
  dispatch SampleEvent, to: ReturningAKeyHandler
end

路由器会生成发送/发布管道。当某个命令注册了多个处理器时,Ming会返回*{:error, :more_than_one_handler_founded}*错误,以此强制显式设计。

中间件

通过middleware/1send_middleware/1publish_middleware/1向管道添加中间件:

ruby 复制代码
defmodule Ming.SampleRouter do
  @moduledoc false
  use Ming.Router

  middleware SomeMiddleware

  dispatch [SampleCommand, SampleEvent], to: ReturningAKeyHandler
  dispatch SampleEvent, to: ReturningAKeyHandler
end

这允许实现日志记录或事务管理等横切关注点,类似于.NET中间件管道,但保持了Elixir的函数式纯粹性。

宏(Macros)

Elixir的宏功能在编译时生成代码方面非常强大,但调试和排查问题较为困难(可能因我经验不足)。C#中类似特性是源代码生成器,但需要掌握Roslyn API。

命令处理器

在Brighter中,IAmACommandProcessor 集中管理命令发送/事件发布。Ming通过Ming.CommandProcessor实现类似功能:

ruby 复制代码
defmodule SampleCommandProcessor do
  use Ming.CommandProcessor, otp_app: :sample

  router SampleRouter
end

该模块注册路由器并作为交互入口点,充分利用Elixir OTP的健壮性优势。

改进路线图

  • 文档完善: 遵循Elixir官方指南结构提升可读性,并通过Hex.pm发布
  • 功能扩展: 消息网关消费、后期处理方法等特性开发
  • 测试覆盖: 完善测试用例验证错误处理和中间件行为

总结

Ming展示了Elixir的函数式编程特性和OTP生态系统如何构建可扩展、易维护的系统。通过融合C# Brighter框架的设计思想与Elixir语言优势,该项目成功搭建了不同编程范式间的桥梁。对于学习者而言,从微型项目起步,结合《Programming Elixir》等官方文档,是掌握该语言的有效路径。

参考资料

Ming项目GitHub地址

相关推荐
AI情绪识别开源9 天前
检信 AI 智能推广平台(代号:JX-Promote)
人工智能·算法·erlang
qyyyyy57012 天前
PDF 转 JSON 怎么做?从表格和元数据提取到 LLM 结构化处理
数据库·pdf·json·erlang·llama
典典分享指南17 天前
GEO 实战:从挖搜索词到监控 AI 收录,一套内容流水线怎么搭
开发语言·青少年编程·numpy·erlang
qyyyyy57019 天前
外文 PDF 怎么整理成 Markdown?从翻译、内容提取到 RAG 知识库导入
自然语言处理·pdf·erlang·机器翻译·零知识证明
Patrick_Wilson1 个月前
为什么让程序主动崩溃反而更可靠?聊聊 supervisor 与 let it crash
后端·erlang·elixir
星栈2 个月前
LiveView 页面越写越卡,我最后抓到的凶手不是数据库,是我自己乱塞 `assigns`
前端·前端框架·elixir
星栈2 个月前
LiveView 怎么测:从组件测试到端到端,我终于不再只敢手点页面了
前端·前端框架·elixir
星栈2 个月前
LiveView 的认证系统:从登录到权限,我一开始以为有 `current_user` 就算完事了
前端·前端框架·elixir
星栈2 个月前
LiveView 的 LiveComponent:比 React 组件更轻,但我一开始真的把它用错了
前端·前端框架·elixir
星栈2 个月前
LiveView 的实时通信,爽是爽,但 PubSub 和广播也最容易把自己绕晕
前端·前端框架·elixir