Introduction
Learning a programming language is most effective when paired with hands-on projects, as real-world challenges accelerate mastery. With a background in C# and active contributions to the Brighter framework, I decided to build a project called Ming to deepen my Elixir skills. This project explores Elixir’s functional programming paradigm while implementing patterns like CQRS (Command Query Responsibility Segregation).
Ming project
Ming draws inspiration from the Brighter framework and Commanded. Its core focus is to replicate and adapt CQRS principles from C# to Elixir’s.
Name
Maybe you are asking yourself why Ming and if there is any meaning, I was looking a library name that was short easy to pronounce in English and it should be close the Brighter, I couldn't find any good name in Portuguese, the Chinese world Ming (明) is very close to Brighter and it's short and easy to pronounce.
Core Concepts
Handlers
Handlers in Ming are simple modules defining an execute/2
function, which processes commands/events and an execution context. For example:
defmodule SampleHandler do
@moduledoc false
def execute(%Ming.ExampleCommand1{}, %Ming.ExecutionContext{}), do: :ok
end
This mirrors the straightforward design of C# interfaces but leverages Elixir’s pattern matching for clarity.
Routing Commands/Events
To register handlers, use use Ming.Router
to define dispatch rules:
defmodule Ming.SampleRouter do
@moduledoc false
use Ming.Router
dispatch [SampleCommand, SampleEvent], to: ReturningAKeyHandler
dispatch SampleEvent, to: ReturningAKeyHandler
end
The router generates send/publish pipelines. If multiple handlers are registered for a command, Ming returns {:error, :more_than_one_handler_founded}
to enforce explicit design.
Middleware
Add middleware to pipelines using middleware/1
, send_middleware/1
, or publish_middleware/1
:
defmodule Ming.SampleRouter do
@moduledoc false
use Ming.Router
middleware SomeMiddleware
dispatch [SampleCommand, SampleEvent], to: ReturningAKeyHandler
dispatch SampleEvent, to: ReturningAKeyHandler
end
This allows cross-cutting concerns like logging or transactions, akin to .NET’s middleware pipeline but with Elixir’s functional purity.
Macros
Elixir has macro which is interesting feature, allow to generate code during compile, but it's difficult to debug and understood what is wrong (maybe it's because I don't have much experience), the closed feature that in C# is the source code generator, but the source code generator require knowledge in Roslyn API.
Command Processor
In Brighter, IAmACommandProcessor
centralizes command send/event publish. Ming adapts this with Ming.CommandProcessor
:
defmodule SampleCommandProcessor do
use Ming.CommandProcessor, otp_app: :sample
router SampleRouter
end
This module registers routers and serves as the entry point for interactions, leveraging Elixir’s OTP for robustness.
Roadmap for Improvements
- Documentation: Follow the Elixir guide’s structure to improve accessibility and publish via Hex.pm.
- Features: Add support to consumer and producer message from messaging gateway
- Testing: Add comprehensive tests to validate error handling and middleware behaviour.
Conclusion
Ming is a personal project for CQRS and help me to understood Elixir features and ecosystem. For learners, starting with small projects and leveraging resources like Programming Elixir or the Elixir official guides provides a balanced path to mastery.
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.