Premature optimization, what even is this? We are always reading about premature optimization (I am using the term "PO" for this in the later run in this blog post, though) and that we should use it, when starting with a project, when we do not actually need a feature, we want to implement. However, there are some things you may consider when doing projects under a specific condition. Not everything is as easy as just pushing the code to GitHub, letting the CI doing the work of checking the code, and deploying it to all users immediately. Some things need to be well thought of.
What is premature optimization?
When I heard the term of PO the first time, I immediately thought of (almost) the right thing:
Optimizing stuff, before they are even ready to see the world through mature eyes.
But it's a bit different. Donald Knuth correctly wrote the following sentences:
Programmers waste enormous amounts of time thinking about or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. 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%.
— Knuth in "StructuredProgrammingWithGoToStatements"
He simply says, that most of the time (97%) we should not think about optimizing our code in the first run. But we shouldn't "pass up our opportunities in that critical 3%". I will show you an example, which most people think would belong to 97% of Knuth's statement.
Give me your example!
Disclaimer: I am strictly talking about native applications (doesn't matter what OS we are talking about). In web applications, it's a lot easier, because, after a deployment, everything is straight available for every user without updating anything.
Ok, ok. I will tell you our example, which we recently experienced while developing a mobile application with an API implementation through the web. It was a very strict CRUD application, however, the structure is a bit complex, when it comes to In-App Purchases. Recently, we wanted to roll out some In-App Purchases for some versions only. We are hosting the whole in-app purchasing part in our own backend (no external recurring subscription SaaS that is handling that stuff), and we needed a solution for this.
Immediately, we thought about implementing some type of attribute on our subscription model, which can be queried using the version number of the application, that is currently installed on the user's device.
We had our failure, which could have been solved with PO (is it called like this when it is the right thing to do in this situation?). The problem we had:
- We had already rolled out some versions of our application, and some users are lazy when it comes to updating applications on its device.
- We are not able to differentiate, which version number the client has installed.
The API wouldn't even know, if an app, a web app, or just a
curl has called it.
Now we had the problem, that we couldn't target any previous versions of our application. You remember what could have solved this issue? Right. Premature Optimization!
The solution was – from now on – sending the Build Number (and also Platform – you know, PO has gotten us into this) to the API when doing a call. Gladly we didn't have millions of users in our application, and we could just implement a fallback for the version number, but a fallback is not the best solution for this. The fallback was version number 1, so we could only target all versions not sending the build number and platform, and not every specific one.
From now on, we will always implement this method for sending the build number and platform with the API request, when starting a new project.
But the requirement wasn't there from the beginning
I am with you in this regard, but in our eyes (since discovering this "issue"), we think this is the right way to solve ways when you want to target a specific version, and this is a crucial feature for us in every application we are writing. Imagine what you can do with this trick:
- Exposing specific attributes in your API for build numbers above others
- Tracking build number coverage on your server-side instead of relying on external API services.
- Building a "notifications" endpoint, which exposes notifications based on your build number (and optionally attributes in your user model – if any)
- And a lot more!
Ok, what now?
In the shown example, we are forced to build stuff the way I perhaps do not want to do. That is, why this blog post should simply state, that you should think twice about writing or optimizing your code, before implementing it (or not).
If you want to schedule a code review or maybe you are forcing another problem in your code you would like to discuss, please feel free to reach out.