Why you should use Trailblazer
To have absolute control over your orchestration layer
Prelude
So you chose your ideal framework to work with, you’ve set up your project perfectly, and everything seems to be in its right place, you are now framed by a set of abstraction rules, you know where to find your models, your views, your controllers, your routes... you feel invincible and you’re all set up to start coding and go wild.
How it’s going so far
So you start writing your fancy unbreakable code, and everything seems to be perfect, slowly but surely the project is getting bigger, and as this transition is happening, this eerie feeling creeps up inside you, but you have no time for self-awareness right? because you need to finish important tasks, while the upcoming deadline haunts your soul, so you have no time to think about maintaining your code or at least double-check what you’re doing, because, at the end of the day, you have your conventions to follow, and you can’t be wrong, you did this many times before, so what could go wrong right? “No worries, it’s going to be okay.” is what you’re telling yourself in an attempt to drown those heavy burdens of thoughts.
A day of reckoning
At some point, that build-up of chaos reaches its climax and catches up to you, and now you realize you’re lost in a big mess, scratching your head in frustration after trying to remember what and where that certain code you wrote a while ago, and sometimes you don’t even know why you did something, and is it even necessary, you start to question the very foundations as you get sucked inside a whirlpool of confusion.
The whole structure becomes fragile, exposed, vulnerable, and sensitive to every small change, fearing its demise every time you need to refactor something or build a new feature upon the already doomed codebase.
So… what is “Trailblazer”?
Web frameworks are responsible for laying the foundation for us, taking a huge load off our minds by providing layers of abstraction to everything we need such as routing, rendering, running jobs, mailing, and more… But when it comes to business logic, it is completely up to us, absolute freedom to do as we see fit, meaning that there are no boundaries and no restraints.
Trailblazer is a business logic framework, and its purpose lies in improving and maintaining our architecture, saving us from fat models and controllers. Acting as a guide, an overseer over our orchestration layer which is the core logic of our app.
Trailblazer introduces us to a new layer of abstraction that helps us organize and extract the structure into smaller chunks of code by creating service objects called operations, the operation is in charge of controlling and handling the logic flow through steps.
module Post::Operations
class Create < Trailblazer::Operation
step :initialize
step :validate
fail :validation_errors
step :persist
def initialize(options, **)
options[:model] = Post.new
end
...
end
end
Above is a demonstration of an operation that takes care of creating a new post, let’s look at the following Railway to understand how the operation behaves:
The operation is Railway-oriented, meaning that its instruction blocks are distributed evenly based on their respective responsibilities, making it clearer to understand the tracks, and super easy to handle their errors.
So keep in mind to design your flow in a manner that respects the Railway mannerism for more compatibility and efficiency.
By separating this logic from our controller, it should look like this: (Let’s say we’re building an API with Rails)
class PostsController < ApplicationController
# POST /api/posts
def create
result = Post::Operations::Create.(params: params)
if result.success?
return render json: { success: true }, status: :created
end
render json: { success: false }, status: :unprocessable_entity
end
end
As a consequence of this separation, our controller only has to worry about the responsibility of rendering a response while our operation does the actual work of the action.
Resulting in a light controller with a clearer comprehension potential. Not to mention that extracting the Post creation logic to a unique operation complies with the Single Responsibility Principle while also encouraging reusability and composition, which gives us more flexibility and liberty to create other operations that extend the latter with ease.
Conclusion
As we’ve seen, Trailblazer inspires order and discipline, and blesses us with:
- A layer of abstraction dedicated to business logic
- Backbone concepts to support the architecture
- Encouraging split of responsibility, reducing entangled code dependencies
- Emphasis on code quality, maintenance, and reusability
What’s more amazing is that Trailblazer goes beyond operations, and offers more solutions to handle other aspects of core logic such as Finders to take care of filtering systems, Forms for validations, Representables to act as decorators for models…
But we’ll leave all these subjects for another time, let’s take it one step at a time, I hope you benefited from this article, have a nice day!
Related Stories
PART 1:🔹Why you should use Trailblazer
PART 2: A Guide to Trailblazer’s Operation
PART 3: A Guide to Trailblazer’s Finder
PART 4: Everything you need to know about Trailblazer Representable
References
- Trailblazer.to: The official website
- trailblazer/trailblazer gem