Callbacks are evil! š
Discussing the pros and cons of using ActiveRecord Callbacks with real world experiences.
Iām working on a super secret app to revolutionize service field businesses š. Yesterday, the codebase had the opportunity to be viewed by eyes from the outside world for the first time and got feedback.
One of the things that stood out was the code related to converting Requests to Quotes. This workflow:
This particular code:
This involved the callback after_create!
I know, I know. Callbacks are evil!
Well, my lame excuse at the time of development is I could not find the correct language for the conversion process when developing the ubiquitous language.
Based on the stakeholders, whenever they need the quote to be produced, they just say to the employee: āPalihug ko pa.quote ani dong/dai. ā
This can be loosely translated as: āHey [name], can you please create a quote for this customerās request?ā
At that time of development, I could not find the right words for it. Based on what I was hearing from the stakeholders, they just said to create a quote.
So, I opted for the easiest solution available, callbacks!
Why are callbacks bad?
It is probably not that concerning in this particular case since the workflow is pretty simple.
However, Iāve been burned by this before! When I was working on an e-commerce application, we used a after_save
callback that sent app notifications to listing owners when their listings were updated. When we ran a script that was intended to update silently thousands of listings on a Sunday evening. Long story short, it was not a very silent Sunday š
.
So, how do we move away from callbacks?
Modeling/developing/writing a better ubiquitous language for the domain you are working on helps you write better code.
In my case, I could not find the right technical words while conversing with the stakeholders.
However, now that I started developing the user interface, it seems itās pretty straightforward:
So, what does the change look like in the code?
Step 1: Create a PORO to handle the business logic
Things to note on the code above:
I created a PORO (Plain Old Ruby Object) for the Request to Quote Conversion business logic.
Later, if we want to send email or mobile notifications to admins or employees, we should update this class.
If anything fails, this class should handle the failure gracefully, especially if it involves payments, etc.
Now that itās a class, creating unit tests for this specific business logic would be easier, ensuring that this process is more robust when change requests come in later.
Step 2: Update controllers
You can then use the PORO on the controller like this:
Optional Steps:
You can actually do it a step further and follow DHHās approach, creating a method for the request model:
Then, you can easily create a call this method on the controller like so:
Now, the code is more readable and safer in the future!
Question: Are callbacks evil?
There are two camps for this, people who are for and against callbacks.
So which camp do I align?
My take is:
As developers, we are constantly understanding the domains that we are working on and developing a unique ubiquitous language for them.
Initially, we may not have the right words for it, thus we need to use convenient āgenericā tools such as callbacks. But as soon as you learn more about the domain, and build a better ubiquitous language, the design of your code should follow also.
Hello there!
Do you have a startup idea or an exciting project youāre passionate about? Iād love to bring your vision toĀ life!
Iām a software developer with 13 years of experience in building apps for startups, I specialize in Rails + Hotwire/React.
Whether youāre looking to innovate, grow your business, or bring a creative idea to the forefront, Iām here to provide tailored solutions that meet your uniqueĀ needs.
Letās collaborate to make something amazing!
Sincerely,
Ademar Tutor
hey@ademartutor.com