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 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 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:
Question: Are callbacks evil?
There are two camps for this: people who are for and against callbacks.
My take is:
As developers, we constantly understand the domains that we are working on and develop 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.
Originally posted on: https://blog.ademartutor.com/p/callbacks-are-evil
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
Top comments (0)