We've all seen the joke, time and time again --
"There are only two hard things in Computer Science: off by one errors, cache invalidation, and naming things."
It's true. Naming things can be really hard. There seems to be all of these hidden rules around how we can name our properties and classes.
You: I'm just going to introduce this helper class, FileHelper.cs
The World: No! You can't use Helper in your class! That's just begging to violate the single responsibility principle.
But naming things correctly can save yourself and others a lot of time. I'll share with you an example from earlier this week. Consider this command:
Assuming you had no knowledge of what this command did, I bet you have some guesses. Maybe you would have only one guess, and I'd honestly be Okay with that. You're probably thinking:
Well.. it starts the web driver manager..?
And you'd be right. Almost.
Unfortunately, webdriver-manager start also performs an update. Although the only way you'd be able to figure this out is if you read the documentation (which honestly seems a little buried to me) or if you ran into the same issue I ran into this week.
While not incredibly relevant to the story, if you want to learn more about what webdriver-manager is, you can read the projects npm page or the GitHub repository. The TL;DR is that it is a means to manage E2E tests for Angular projects.
It goes a little something like this...
For most of the things we develop at my company, we put them into Docker containers. This includes our end-to-end (E2E) tests. The Dockerfile for our tests is pretty straightforward, and honestly as to not add too many unnecessary details, the only thing that really matters is that we have the following command in the Dockerfile:
RUN webdriver-manager update
When the image is built, webdriver-manager update will be run, which will install the latest version of the webdriver manager. Docker images are immutable. That is, when they are created, they do not change. This means that the Docker image will be created with the latest version of the web-driver manager.
Now, to start the web-driver manager, we need to run the infamous webdriver-manager start command from within the Docker container.
Though depending on when you created your Docker image and when you started running your container, you're going to get one of two scenarios:
- The container will start up just fine and run your tests as you expect.
- The container will error when trying to run the webdriver-manager.
This is due to the fact that, unfortunately, webdriver-manager start not only starts, but attempts to start the latest version. Regardless of what version is installed. So it is possible that a new version has been released, and the Docker image is no longer relevant.
Luckily the solution isn't too bad. We just need to update the Dockerfile to update to a specific version. This forces our Docker image to always have version 3.0.0 installed.
RUN webdriver-manager update --versions.standalone 3.0.0
We then need to change the webdriver-manager start command to also include the same parameter:
webdriver-manager start --versions.standalone 3.0.0
Which in turn, forces the webdriver manager to start a specific version.
A simple solution, but a problem that took a decent time to figure out what was going wrong. Never would I have imagined that start did more than just that. Had the command been called startupdate or just left as start with an optional update parameter, the problem would've been much more apparent.
The biggest takeaway from all of this is that your naming should say exactly what it is doing and..
Have no side effects
Side effects are lies. Your function promises to do one thing, but it also does other hidden things. Sometimes it will have unexpected behavior. They are devious and damaging mistruths that often result in strange temporal couplings and order dependencies. – Miguel Loureiro
Your code should do what it says it does, and nothing more.