Wrangling Service Objects with method_struct
Service Object is a pattern of extracting business logic into a separate “service”. It has gotten considerable traction in the Ruby ecosystem and is worth exploring. Steve Lorek described Service Objects in the following way:
A ‘service’ describes system interactions. Usually, these will involve more than one business model in our application.
As an example; we have a User model and this encapsulates a password. If a user has forgotten their password, the business rules dictate that we have to send them an e-mail with a link to reset it. This functionality is a service.
The CodeClimate blog post on refactoring fat models has a good rulebook on when to use this pattern:
- The action is complex (e.g. closing the books at the end of an accounting period)
- The action reaches across multiple models (e.g. an e-commerce purchase using Order, CreditCard and Customer objects)
- The action interacts with an external service (e.g. posting to social networks)
- The action is not a core concern of the underlying model (e.g. sweeping up outdated data after a certain time period).
- There are multiple ways of performing the action (e.g. authenticating with an access token or password). This is the Gang of Four Strategy pattern.
I see Service Objects as a mutation of the Command pattern. They allow separation of business logic from models and controllers, but have further benefits in testing and composition.
Hello method_struct
At Base Lab, we’re implementing Service Objects using the method_struct gem. Let’s go through an example which illustrates the benefits of this approach.
Continue reading >