Javascript style guide we use at Transit.
Our styles are based on the excellent javascript guide from Airbnb with a few exceptions.
- Limit your lines to 120 characters. eslint: max-len.
This ensures readability and maintainability.
// Bad.
const promise = Promise.resolve(true).then(Promise.resolve).then(Promise.resolve).then(Promise.resolve).then(Promise.resolve);
// Good.
const promise = Promise.resolve()
.then(Promise.resolve)
.then(Promise.resolve)
.then(Promise.resolve)
.then(Promise.resolve);
-
Allow usage before declaration. eslint: no-use-before-define
doSomething(); function doSomething() {}
As soon as a concept has a name, this name should always be used to refer to that concept, and that name shouldn't be used to refer to anything else.
Example:
- A
globalRouteId
is a unique identifier to a route. One should never call itrouteId
since it is another concept (used in the GTFS, the tGTFS and the bgtfs with different meaning). - A
feed
is an instance of thetransit_production.feeds
table. AnalertFeed
is an instance of theservice_update.alert_feeds
table.
Example: If some external tools/library/api uses the same name for another concept, then at least the foreign name should be prefixed for disambiguation, or even both.
- When we match the stops from the GTFS to the stop from some real-time API, we call the first one
gtfsStop
and the second oneapiStop
even if the first one is usually just called stop.
-
An array should have a name that gives clues about its content.
// Bad. const things = ['dog', 'cat', 'mouse']; // Good. const animals = ['dog', 'cat', 'mouse'];
-
An object of
thing
indexed by somekey
should be calledthingByKey
.// Bad. const routes = { 2: { routeShortName: 'R1', routeLongName: 'Awesome Route 1' }, }; // Good. const routeByGlobalRouteId = { 2: { routeShortName: 'R1', routeLongName: 'Awesome Route 1' }, };
-
When you have different representations of the same thing, apply some disambiguation on the content.
// Bad. let date = '2017-01-01 00:00:00'; date = moment(date, 'YYYY-MM-DD HH:mm:ss'); // Good. const dateAsString = '2017-01-01 00:00:00'; const dateAsMoment = moment(dateAsString, 'YYYY-MM-DD HH:mm:ss');
// Bad. let stopSequence = '1'; stopSequence = parseInt(stopSequence); // Good. const stopSequenceAsString = '1'; const stopSequenceAsInt = parseInt(stopSequenceAsString);
With some reasonable limits, one shouldn't be afraid to have long variable name, and be more afraid of meaningless names. For example:
apiStopByStopIdByTripHeadsignByRouteId
should be still preferred asdict
orapiStops
.
Below are features that are recommended to start using. Although, keep in mind that they are closely related to node versions, so please double check if a feature is available before starting using it.
Dealing with asynchronous code can be tricky sometimes. To simplify and improve readability, one must try using Promises instead of the classic error-first callback. Here are a few links to understand them and start using them efficiently.
Async/await is part of the ES2017 release. Node 7.6 ships with V8 5.5, which includes async/await
natively. So it's time to start use it. Although, one must completely understand how Promises work because both features work together.