I met with a contractor last week who recommended a bunch of changes to our codebase. As a first time developer, moonlighting as a tech lead, I at first was really excited by the value of these suggestions. Set up linters; add formatting to your commits so they become searchable - and of course, as always, write more tests. These were all things I've wanted to do for a while, but the speed of development and short term priorities always interfered with the cleanup.
For example, we didn't add tests to UI components, because we did so much dogfooding and knew where the errors were. This manual testing slowed us down at times, but it never became a strict blocker to automate this. Also, linters really only caused issues on PRs. The process got in the way of speed and speed was what we needed.
It made me wonder, however, when is optimization necessary? - There is a quote in programming that says -
premature optimization is the root of all evil
According to this stack overflow post, the full quote is:
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.
This I think gets to the root of the issue - most of the time it’s unnecessary to optimize things, but the small percentage of the time that it really does matter makes a huge difference. I've thought about how this applies to our code.
We've had a number of issues with Login flow - we never wrote tests, but since we were dogfooding, we only went through a small subset of logged-in states (accounts created already, sign in again). There were a few times when this flow degraded and testing would have really helped.
A month or two ago, the indices in our database changed, but we didn't notice and our core algorithm failed to pick it up - we fixed the issue within a few hours, but it caused some weird UX bugs.
There were a number of times where it didn't matter as well:
One of the recommendations the contractor made as critical was setting up a linter for JSON. We have had PRs that had conflicts that were annoying, but they are generally easy to resolve.
Every time we onboard a new developer, we have to go through the process of setting up her computer, and this can be cumbersome for the whole team. A good README would go a long way, but it's a one-time thing that's hard to test.
The biggest takeaway is that software engineering, much like life, is about building a system. What allows it to go wicked fast is automating things that humans previously did. What's important is figuring out how to build the most efficient system for your team. Where are your strengths and weaknesses? What can you live without? And continually move forward. - just because you don't know the perfect way to do something doesn't mean you should drop everything and figure it out. You can do things imperfectly for a while and optimize later.