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
globalRouteIdis a unique identifier to a route. One should never call itrouteIdsince it is another concept (used in the GTFS, the tGTFS and the bgtfs with different meaning). - A
feedis an instance of thetransit_production.feedstable. AnalertFeedis an instance of theservice_update.alert_feedstable.
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
gtfsStopand the second oneapiStopeven 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
thingindexed by somekeyshould 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:
apiStopByStopIdByTripHeadsignByRouteIdshould be still preferred asdictorapiStops.
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.