Weekly Pair Programming 1: Early return and async/await
- 2019-11-15
- Rocket.Chat Web
Today, I had a pair programming session with my mentor Douglas, which is an awesome experience for me. I learned a lot of advanced programming knowledge from this pair session. And below are some of the notes that deserved to be mentioned:
Early Return
Early return is a coding style that is to help us avoid The IF Spaghetti. Take the following code as an example:
1 | post() { |
Though, there is no problem with the above code, we can use early return to avoid the unnecessary indentation:
1 | post() { |
With the above refactor, we can reduce the indentations and improve the readability of the code. A few years ago, the JavaScript community was suffering from the indentation issues caused by callback functions - also known as callback hell and we finally solved this problem via the async/await. I think this is also the reason why we prefer the early return instead of wrapping the main logic into the if statement.
Tracker.autorun
Meteor allows developers to use Tracker.autorun
to offer a runFunc
, so whenever the reactive data sources are changed (such as Session, database queries), the runFunc
will be called automatically to update the UI. This is a great feature but when we try to pass an async
function as the runFunc
, this mechanism will be broken. Let's combine the real code to make a more intuitive understanding 👇
1 | // The code that is not working ☹️ |
So what's the difference between them? Douglas made a simulated call stack that can approximately represent what's going on with the above code 😶
1 | Meteor.startup |
The previous one usessettings.get(...)
in an asynchronous function and when it is resolved, it surely will be executed but it will lose the right context. This is possibly the reason why the Meteor Tracker can't track the dependency as expected and run the corresponding function when the sources are changed.
For the next one, we moved the settings.get(...)
outside the asynchronous function. We wrote a little more code though, we handled the problem and the UI finally auto-updated as expected 😄
Async/await
The async/await is syntactic sugar of the Promise, which means the following two forms of code are equivalent:
1 | // The Promise way |
So for it, no matter whether we need to return a result back to its caller, it's unnecessary for us to add the keyword await before the last the statement inside the async function. The async keyword is only for the previous asynchronous statements.
Lessons
There are also some lessons I learned from this session. Hope I can avoid using them in the future 🙅
Never write unreadable/confusing code
If you can not understand what the code is doing at first glance, then it's surely the unreadable and confusing code 💩. You absolutely need to refactor to make it more readable 👊
Here is a part of code what I wrote before:
1 | if ([8, 46].includes(e.keyCode) && e.target.value === '') { |
At first glance, you don't exactly know what these two keycodes 8 and 46 mean (unless you recited all the keycodes before 😶). So we need to add two other constants to make it more clear to others:
1 | const KEYCODE_BACKSPACE = 8; |
Looks much better 🎉
Type before
Another best practice that I can learn from Douglas is that we can use the type of constants as the prefix to indicate others these constants' types or what the scope these constants belong to.
For example: 1
2
3
4
5
6
7// Bad 🙅
const BACKSPACE_KEYCODE = 8;
const DELETE_KEYCODE = 46;
// Good 👍
const KEYCODE_BACKSPACE = 8;
const KEYCODE_DELETE = 46;
This rule can be also applied to *.i18n.json
files. For instance:
1 | { |
Singleton pattern
In some situations, we apply singleton pattern to save the system resources (usually for some managers). It can also be used to avoid global variables of pollution.
Conclusion
I am so appreciated that I had a wonderful pair programming session with Douglas today and it is really helpful for me to have a better understanding of both our codebase and advanced programming knowledge. Extremely looking forward to the next one!