Absolutes as an AntiPattern
It’s been awhile since my last post — almost 2 months to be specific. A trip to Portugal, getting sick and a minor run-in with a table saw made it challenging to post anything for the last couple weeks. But I’d be lying if I said I was itching to write.
During that time, I didn’t have anything screaming to be talked about. I have a long list of “decent post” topics, but none of them got me particularly excited. Until today…
I stumbled on a blog post related to Rails’s upcoming Active Job feature. While demonstrating the syntax for specifying the adapter, there was comment in the code snippet that said “inline and other worse options”. This caught me by surprise and bummed me out at the same time. Not only because I’m the author of one of them, but because there are a handful of background processing libraries in Ruby that are really good.
So, naturally, I pinged the author and mentioned the comment might be sending the wrong message. He responded with “I consider sidekiq to be the best background processing tool available for Ruby.” And then later, “sidekiq is significantly better that delayed_job and resque. You’re welcome to disagree”.
Note: The responses above illustrate a general sentiment. By no means is this post focused on the individual that said them.
The thing is, I don’t completely disagree. As you probably already know, I’m a huge fan of of Sidekiq. I’ve contributed to the project and believe Sidekiq’s author, Mike Perham is not only a great leader in the Ruby community, but a great example of how to manage and lead open source projects well.
However, those responses reminded me how damaging absolutes can be. You’ve probably heard it before:
“we can ABSOLUTELY NOT do x, y and z”
Why not? Will the world end? How do I know?
or, what about:
“this feature needs to go out tomorrow, no excuses”
What if there is an excuse? What if it’s not ready? Will I be fired? Will our company go under?
There are trade-offs to every decision made. While some options may not be ideal, they may still work, perhaps just not as well.
Absolutes beg the toddler question, ”why?”. Why won’t that language X work? Why can’t we use Y?. If you don’t know the answer to those questions, you’re doing yourself a disservice by not asking. Maybe the person has thoroughly researched the topic to come up with those conclusions. But, maybe, they haven’t.
I’ve noticed those who do exhaustive research on a topic tend to present the information in a different manner. They’re confident the facts they found will prove their case and seem to present their findings less defensively. No, ”it has to be done like this”. More like, “I found a few ways to fix the problem and here’s why I think option 1 might be the best solution. What do you think?”.
Whether you follow agile or any other methodology, predictions and absolutes have no place in conversations. There are plenty of examples of failed software projects. I’m pretty sure all of them featured people promising the work would be done in time and under budget. Buuuuuuut, it wasn’t.
Background Job Options
Delayed Job was the first Ruby background processing library I used. I remember feeling badass that I was doing all this complicated stuff in the background. But at some point, there we so many jobs and so much activity that pushing and pulling jobs out of the primary data store wasn’t efficient. Reads from the web UI would slow down (and ultimately stop) and users would bail. Unfortunately, I couldn’t pop up a message and say, ”hey, hope you don’t mind, but I’m doing some pretty crucial shit in the background here, so you’re experience is gonna be sucky for a bit! sorry :(”.
So, at the time, Resque was the next logical transition. I migrated the previously written jobs from Delayed Job to Resque and experienced a new level of bad ass. Fast forward 4 years — I still work on projects using Resque. Needless to say, it’s a pretty awesome piece of open source software.
A few years ago, Sidekiq came along. While I didn’t know much about multi-threading code in Ruby, I tried it on a side project and was floored at the results. Those 6 Heroku workers that I’d been paying for could be compacted in to 1?!?! And on top of that, I only needed 1 worker that had 25 workers working against the queue?!?!
But then one day, I dropped it in to a project that was using MongoDB and MongoMapper as ORM and things didn’t go so well. In the end, MongoMapper wasn’t thread-safe, which is a requirement of Sidekiq worker code. So in that case, was Sidekiq the best tool for the job? While I would’ve loved to use Sidekiq on that project, it certainly (like the absolute there…) wasn’t the right tool for that job.
And what about when I first started with Delayed Job…we were a small startup with limited cash. While it seems silly to balk over an extra $35 Heorku dyno, it was $35 that could’ve gone towards something else. Not to mention the extra Redis instance, along with the expertise to make sure the thing didn’t fall over and die. Was Sidekiq (or Resque for that matter) the best tool for that job? Nope!
Fast forward a few years, I had the need for an in-process background processing library, so I wrote one. That need was driven off the motivation above — needing to minimize cost and complexity. Would Sidekiq have worked for that project? Of course! In fact, it was using Sidekiq for a year or so before I transitioned the jobs to use Sucker Punch.
Use Cases
At this point, you should be noticing a trend, right? The examples above were unique use cases with a unique set of requirements and limitations. Sure, if every project I worked on had unlimited resources (both time and money), Sidekiq would be probably be my go-to the majority of time (even when writing that sentence I hesitated and almost wrote “all the time”).
But I hesitate now. Because I remember learning about the new cool things and thinking, ”This is the best! There’s no way I’ll never not use it”. And when I would talk to other developers, I would rave about how X is the best for Y. And now I realize I was a dummy for doing that. There’s no way I could’ve made that judgement for someone else and their work. What I really should’ve said was, ”I tried [insert fancy new gem/technique] for the first time the other day. It worked really well for doing X in my project that does Y”. That definitely doesn’t sound as exciting, but it was the truth.
I feel fortunate to get to write Ruby everyday. It’s incredibly expressive, which is why the debate over the countless ways to do something is great. Does the code express the right intent? For your method, it might. But for mine, it might express the complete opposite. The good news is, that’s OK. Both versions will work and the fact that we can have conversations like that is a praise for the language itself. I prefer to have the opportunity to have that conversation about style, rather than a language more black and white. Maybe it’s the creative in me, but it seems like no 2 Ruby solutions will be identical and that’s one of the things I love most about writing Ruby.
We often joke about the stack overflow post that starts with “I’m thinking about learning Rails…is it better than PHP?”. Or even more relevant today, ”Which javascript framework should I use?”.
And then there’s the guy who comes along and is all like, ”Let’s back up, what are you doing and why do you absolutely need a FRAMEWORK????”. While I used to ignore those types of comments, they’re the kind that I think about now and find myself typing. And that has me wondering…why the change?
Experience, Experience, Experience
I got to thinking about how I felt when I was first learning to program. When I started to feel comfortable with Rails, my confidence was through the roof. But at the same time, my naivety was at an all time high. I had had minimal experiences with software systems that were either critical or heavily-loaded. But having found Resque, I felt like I could solve the world’s problems. This is somewhat of an exaggeration, but not too far off. I realized that, as it relates to my technical career, my naivety is doing this related to time:
The less naivety, the more options and, naturally, certainty takes a nose dive:
The more I learn about programming in general, the more questions I have. Fortunately, experiences have brought me to a point where I can fairly weigh the use of Sucker Punch or Delayed Job for a particular use case. I’m not sure projecting absolutes from up high does anyone any good. Beginners will take it as the word and spread the message to others they come across.
Use cases are real. And the less we force our own biases on people, the faster they’ll realize experience is key and the random guy behind the cat avatar on Stack Overflow might actually be asking the right questions — even if they are convoluted.
Next time you hear an absolute, ask ”Why?”.