Feedback on Modular Monoliths and Public Interface Communication

This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.

Message originally sent by slack user U72IU7M0YSV

Hey, I just found this community. I’ve worked on a number of different modular monoliths and am currently experimenting with a way in which things (e.g. controllers) can talk to the public interface of a module. Maybe I can put together a repo or gist of my thinking, would be great to get some feedback.

Message originally sent by slack user U72IU7M0YSV

At the moment it looks like this:

module Issues
  class Error < StandardError; end

  # @example
  #   Issues.raise_issue(title: 'Out of Diskspace') do |on|
  #     on.success { |issue| render json: issue }
  #     on.failure { |errors| render json: errors }
  #   end
  #
  def self.raise_issue(attributes, &block)
    OnRaiseIssue.call(RaiseIssue.new(attributes), &block)
  end

For the commands (aka form objects) it uses Dry-Struct + ActiveModel::Validations and for the command handler (aka service object) it uses Dry::Transaction.

I am curious to see a more complete example!

Message originally sent by slack user U72DWE3TY2J

That’s cool. At work, we have a similar pattern

 Sequence(
   :validate_entry,
   :build_response
  ).call(...)

Message originally sent by slack user U72DWE3TY2J

I love/hate it.
Plus: This pattern makes it easier to chain things while writing complex pipelines.
Cons: Tracing tends to break, and this pattern complicates error handling.

Also, it requires folks to understand Monads. And most rails folks don’t know Monads well enough.
Chaining ActiveJobs might be a less elegant solution, but its observability is much better

Message originally sent by slack user U72DWE3TY2J

In an ideal world, I would just move all of these processes to https://temporal.io/ Durable Executions/Tasks systems (in our experience) have proved to be easier to scale than traditional queue-based systems.

Message originally sent by slack user U721QG0W3H1

I’ve been working with a similar approach and extracted the design we were using in a small library:
https://github.com/Hanikamu/hanikamu-active_command
So basically it’s what you described for service design with DryStruct and active model errors
I like to use monadic responses from dry::rb
For complex pipelines I really like the Event Driven Architecture provided by
https://railseventstore.org/
So using pub/sub withing your rails app with AR. Then you have a really nice overview of the state of your events structured in streams. I had three years of experience working with this setup in an IoT platform dealing with MQTT messages and was performing really good

Message originally sent by slack user U72IU7M0YSV

I’m working on a blog post to outline my experiments, will post here when complete.