How to kill the scalability of your app in 5 simple steps
Over the past year, we transformed our mobile app from a simple client-side package into a dynamic code block that takes orders from the headquarters. This transition involved substantial reworking and tying up loose ends. In this blog, I’ll outline 5 critical steps on what NOT to do if you want your app to be scalable.
#1 — Using literals everywhere
Literals are extremely luring while coding as you have to do the bare minimum: type it. It is the number one mistake made by new programmers. The more you write literals, the more you have to re-write them in future. It will make your app prone to inconsistencies and take additional memory in all cases.
// Bad
if (items < 100) {
print('Items are less than 100');
} else {
print('Items are more than 100');
}
Instead, use constants wherever possible. Both you and your app will have a better time in future.
// Good
const int length = 100;
if (items < length) {
print('Items are less than $length');
} else {
print('Items are more than $length');
}
#2 — Not wrapping dependencies
As you transition in your career you realise that nothing is permanent. Not even the most basic image loading library in your app. If one day you have to make all images in your app round-cornered, or change the error-state icon throughout, you will have a hard time.
// Our project will use this wrapped dependency that we
// have absolute control over. Even if we have to change
// the image loading mechanism, there will be only one
// change in the whole project.
class ImageLoader extends StatelessWidget {
const ImageLoader({required this.url});
final String url;
@override
Widget build(BuildContext context) => CachedNetworkImage(imageUrl: url);
}
Dependency wrapping is a simple yet interesting approach and I will be writing a separate article on it. For now, consider that there should be only one door to a room.
#3 — Using arrays as the root in API response
In most organisations the backend and frontend developers work as a team towards a task and don’t mind minor reforms. Consider this example REST API response.
// GET https://api.myapp.com/postcards
[
{
"id": 1,
"sender": "John Wick"
},
{
"id": 2,
"sender": "Tony Stark"
}
]
If the response is an array, it is impossible to add any other kind of data to it. If we just wrap this in an object with a key, any future additions will take minimal effort on both ends.
// GET https://api.myapp.com/postcards
{
"postcards": [
{
"id": 1,
"sender": "John Wick"
},
{
"id": 2,
"sender": "Tony Stark"
}
],
"sharingEnabled": false
}
Wrapping the array in an object does no harm to anyone but helps in the future. Do keep in mind to not club logically unrelated data.
#4 — Having no remote control over your app
We are imperfect and so is our work. Things tend to break often even in Fortune 500 organisations. For this reason it is important to have some degree of remote control over your app.
If something fails, or a change in plan occurs, you should be able to communicate to the end user through the current version of the app itself. I’m breaking this into two parts:
- Kill-switches: When shipping a new feature, always implement some kind of kill-switch mechanism. When turned off, users won’t be able to access (or even know about) the feature. You may use a service like Firebase Remote Config for this. It is as simple as storing a boolean remotely and using it to show or hide a button on the screen.
✨ Update: I just published a full guide on Kill Switch
- Dialogs and notifications: There are times when things break beyond repair and you need to tell the users to update the app ASAP. If you can show a dialog or send a push notification whenever needed you won’t have to rely on gradual updation of the app and can prevent losing users and negative reviews.
#5 — Reinventing the wheel: over-using dependencies
This should be considered a paradox: A common malpractice to use external packages and dependencies for minor inconveniences. Do not import anything unless it is not worth your time. Don’t add a package to draw a dotted line on the screen. Even if you have to copy-paste some files from the Github repo, do it, instead of importing the whole library.
Everybody’s small mistake amounts to a huge production bug one day. It gets more complicated when you upgrade your dependencies. Do a time-cost analysis and then decide.
Conclusion
This one is out of pure learning and that is why I was extra delighted while writing this blog. Good practices can sometimes feel overwhelming to go with but take a deep breath and realise that it is a matter of a few extra seconds or minutes that will make the difference, the rest is mere anxiety.
Let me know how you liked this one and let’s meet in another blog. Happy coding!
🚀 Let’s connect!
Connect with me on LinkedIn for professional insights and networking.
Explore my contributions on GitHub and Stack Overflow to collaborate on something amazing! ✨