New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DEV: Chat service objects #19814
DEV: Chat service objects #19814
Conversation
80d49a3
to
2daaa5f
Compare
So far I am liking this, since it's much more standardized and feels cleaner to do things only the one way. |
* Add ServiceBase and ServiceResult classes for standardization of service objects * Refactor ChatChannelsController#destroy into ChatChannelDestroyer * Make a ChatMessageCreatorV2 class to demonstrate refactor of existing service
2daaa5f
to
9a64eb6
Compare
OK thanks will need some time to read and think about all of this |
|
I like your rationale and where this is going If I may share some thoughts: I think this is going in the right direction and if we want to standardize how to work with business/service objects we should go even further. At some point, mixing validations, business logic and other stuff is going to make a service object bigger and harder to reason with (at least in my experience Another small gem I’ve been using is Interactor, this is some kind of very lightweight service object where you create small business logic units and where you can chain them together using what they call an organizer. While it works well, there is no layer for validations or policies, so this is something to add by yourself (which I did at some point). One thing I haven’t used (yet), is the whole actions from Hanami. If I’m not mistaken, they’re using gems from the DRY ecosystem under the hood, and it seems to provide a rather good experience too. Now, I’m not saying we should introduce a big set of gems or anything, but we should take a good look at what already exists, so we won’t reinvent the wheel. If we decide to still do things our way, I think there are plenty of good ideas in those tools, and we should probably be inspired by them This is, of course, just my opinion |
@martin-brennan I pushed the results of your ideas, @Flink ideas and my ideas (and interactor, and trailblazer :D). This is not finished, but I pushed it so we can talk of it. You will also note that I started working on spec and rewrote the destroyer service to use this "ChatService". One of the big focus I have is having very clear spec failures, eg:
One of the big missing piece IMO is to write some helper controller to handle failures. |
We’d probably have something by Monday/Tuesday |
Now defines before/after/around_call, before/after/around_contract
context "when channel is a category one" do | ||
context "when a valid user provides valid params" do | ||
let(:message) do | ||
MessageBus.track_publish(ChatPublisher::CHANNEL_EDITS_MESSAGE_BUS_CHANNEL) { result }.first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not to be addressed in that PR, but we've had some flaky test whenever two pieces of code would publish a message and would break the specs that are looking for the first
message in the bus. Do/should we have a way to filter for a certain type of message and then do .first
on it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes agreed, generally I think include?
on a map of events is just enough
This is a combined work of Martin Brennan, Loïc Guitaut, and Joffrey Jaffeux.
This commit implements a base service object when working in chat. The documentation is available at https://discourse.github.io/discourse/chat/backend/Chat/Service.html
Generating documentation has been made as part of this commit with a bigger goal in mind of generally making it easier to dive into the chat project.
Working with services generally involves 3 parts:
with_service
controller helper, handling success and failure of the service within a service and making easy to return proper response to it from the controllerNote in case of unexpected failure in your spec, the output will give all the relevant information: