Quick Announcement: I'm working on a short book about building dev environments using Docker, called Sustainable Dev Environments with Docker and Bash. I'll mention it here again when it's 100% done, but if you want early access, please let me know at https://devbox.computer
(which also contains more details on the book).
No language, framework, tool, technique, person, or computer program operates on its own. They are all part of a system, and that system exerts influence over all that it encompasses. I want to talk about this concept in the context of various best practices and aphorisms.
It's hard to disagree with the phrase "use the best tool for the job". But, it's also hard to know exactly what it means. What is "best"? What is "the job"? When building software, these concepts aren't so clear.
This lack of clarity leads to the Best Tool for the Job Fallacy wherein a developer justifies a tool they'd just like to use because it's cool or fun or new. This almost always makes the system worse.
I wrote a book about Sidekiq, the background job library used in many Ruby on Rails apps. All things being equal, when you want to run stuff in the background, Sidekiq is the best tool for the job. But all things are never equal.
At Stitch Fix, we used Resque, since I was familiar with it from working at LivingSocial. Over time, we had several apps and services built in Rails, and they all used Resque for background job processing. We had shared tooling and code, a unified understanding across the team, and the start of basic observability for Resque.
One day, a developer wanted to use Sidekiq. He said it was the best tool for the job.
In this case, his definition of "best" was not what was best for the system. Adding a second job processing framework to the system of apps and developers would make things worse. He had no use-case that Resque could not handle. He just wanted to use Sidekiq.
Despite my protestations, it was adopted in his team's apps. Over time it made the system worse and worse. Everything the system had to do regarding background jobs had to be done twice: once for Resque and once for Sidekiq.
Granted, the system with only Sidekiq would've been better than the system with only Resque, but the proposing developer wasn't asking to migrate us to Sidekiq—he just wanted to not have to use Resque on his team's apps.
When I was at LivingSocial, the team was around 200 developers. The team's leadership took a laissez-faire approach and encouraged everyone to use the best tool for their job.
Each team was basically building web-based apps or services, with a few more specialized needs like sending emails. Here are the list of tools that at least one person decided were the best for their job: Ruby, Rails, Java, Clojure, Scala, Angular, Backbone, JQuery, JavaScript, CoffeeScript, ClojureScript, Bootstrap, Python, and a not-insignificant number of home-grown libraries and tools that did more or less what some existing open-source library already did.
The reality was that everyone just used whatever they wanted
or thought would be cool. I definitely fell victim to this
fallacy and created my own Ruby testing framework instead of
using assert
.
LivingSocial's system—the dev team—was not served by everyone using the best tool for the job. Each of the languages and frameworks I listed is capable of achieving the same results more or less. The system would've been easier to manage and would've produced better work if there were fewer tools.
Like many agile aphorisms, "use the best tool for the job" requires a lot of qualification and nuance to truly understand. It's too easy to interpret however you want, and most developers—especially those with a lack of experience or maturity—will use it to as a justification for their pet language or framework.
Technical leaders have to provide that missing context and nuance. I'd recommend simply avoiding the phrase entirely and give clearer, unambiguous guidance. If you are faced with this phrase, try to pick apart what is meant.
Start with "job": are you choosing a background processing system from scratch or are you choosing whether or not to add a second one to your existing system?
Next, try to quantify "best". Start from "best for the dev team" or "best for the technical portfolio". Grounding the phrase in reality can help figure out if there really is a gap in your existing tooling, or if someone just wants to play with a shiny object.
It's hard to keep up with everything, and sometimes I learn something that has been common knowledge for a while. Maybe this happens to you.
The <dialog>
element, plus a tiny bit of JavaScript and CSS, creates a nice, well-behaved and usable dialog with a darkened backdrop. I used to build those with JQuery plugins or other nonsense and now it's just built in to modern browsers.
I used it as part of Ghola, my color picker (which, if you are interested in Web Components, you can read about here) to allow previewing your color selections.
First, style the <dialog>
:
<!-- make the dialog 90% of the viewport
and generally centered on the page.
Please use CSS for your real projects :) -->
<dialog id="preview-dialog"
style="height: 90vh;
width: 90vw;
top: 1rem;
bottom: 1rem;
left: 1rem;
right: 1rem;
position: absolute;">
<!-- dialog contents -->
</dialog>
Open it with JavaScript when a button is clicked:
document.querySelector("button"). // or whatever opens it
addEventListener("click", (event) => {
event.preventDefault()
const dialog = document.getElementById("preview-dialog")
dialog.showModal()
})
This CSS will style the area behind the dialog:
::backdrop {
background-color: black;
opacity: 0.2;
}
The ::backdrop
pseudo-element targets the background of a dialog when it's shown. The dialog can be dismissed by hitting Escape, or you can call close()
on it.
Love it!
Unless otherwise noted, my emails were written entirely by me without any assistance from a generative AI.