The Attractiveness of Efficiency
My experience has been that a lot of developers do not find writing "efficient" code or tests or whatever to be an attractive endeavor.
Let's bypass, for the moment, that "efficient" can mean many things.
How enticing efficient coding is, is directly proportional to how big and complex your project is. I won't argue that if you have a single unit test and running it once takes 600ms and another version takes 10ms that it likely isn't worth the effort to rewrite the 600ms code if it is already written.
I also understand that junior devs don't often see why it matters to write code following standards they don't understand. And as above, if the project is small enough, it isn't often worth it to rewrite something that works into something which is conformant.
However, projects grow. Especially closed source, for profit projects. In fact, they almost need to continuously grow larger and more complex to justify the price they demand. And so, you eventually end up with thousands of unit tests and hundreds of thousands of lines more of code.
All of a sudden those 600ms and inconsistent coding standards start to matter. A LOT.
I recently took on a task to improve the efficiency of some unit tests. I found a base level method shared by a large number of tests in a large-ish project which took between 600-1200ms to run. This code was shared across thousands of tests. Running the full suite of unit tests on a local dev environment typically took 15+ minutes and took between 40-70 minutes in the CI/CD pipeline. In both cases a large number of these tests were running in parallel.
I traced the cause down to a single helper method which was injecting via reflection and expression tree compilation, hundreds of classes into the base fixture.
I simply removed the line and about 60% of the tests calling that method still passed.
The old code was "effective" in the sense that is was simple. Write one line, and everything works. There was probably a time when there were only a few hundred tests and the subset of them which relied on this call were small enough that no one cared.
I added a new method to replace the old approach with a more targeted approach. It was still "simple". It inferred the types needed based on a generic type parameter. Not all of the types injected will be explicitly required. But, it brings the run time of all but the most demanding classes down to 1-10ms for that method. 60-600x faster. And across thousands of tests. Needless to say, all of a sudden, writing efficient code became sexy again.
And the same goes for code consistency. There is a huge difference in how long it takes to get productive in a piece of software that is consistent vs. one which isn't. Even if the standards don't align with your own best practices or expectations. A consistent project is easy to learn to read over time.
While I stated that size and complexity matter. The truth is, they only affect the perception. The sexiness. Code should ALWAYS be as efficient as you can muster and always as consistent as possible. Projects tend to grow. Or, if you're not for profit then you're probably open source. And people won't support or contribute to poor projects. So you only hamper your success.
Write consistent code and write efficient code. Even if it means you need to refactor often to get and stay there. It is WORTH it. In my case where I refactored the tests, the projects (which runs dozens to hundreds of pipelines a day) will save HOURS every single day in paid CPU time, in waiting for build to complete and in a number of other ways.
Comments
Post a Comment