Created
May 7, 2019 13:58
-
-
Save shingonu/84bc5e829059238b99f12b641e9568aa to your computer and use it in GitHub Desktop.
12 tips for writing clean and scalable JavaScript.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### 1. Isolate your code | |
topic๊ณผ ๋ถ๋ฆฌํด์ ๋ช ๋ฐฑํ ๋ก์ง์ ๋ฉ์ด๋ฆฌ๊ฐ ํ์ํ๋ค. ๋ง์ฝ ํจ์๋ฅผ ์์ฑํ๋ฉด ๋ฐ๋์ **ํ๋์ ๋ชฉ์ **์ ๊ฐ์ง๋ ๊ฒ์ผ๋ก ์์ฑํด์ผ ํ๋ค. ํ๋์ ํจ์์์ ์ฌ๋ฌ ๋ชฉ์ ์ ๊ธฐ๋ฅ์ด ๋ค์ด๊ฐ๋ฉด ์๋๋ค. | |
๋ํ ์๋ฌ๋ฅผ ์ค์ด๊ธฐ ์ํด์๋ ํจ์ ๋ด๋ถ์์๋ง ์ํ ๋ณ๊ฒฝ์ ์ผ์ผ์ผ์ผ ํ๋ค. ๋ง์ฝ ํจ์ ์ธ๋ถ์์ ์ํ๋ฅผ ๋ณ๊ฒฝ์ํค๊ณ ์ ํ ๋ ํจ์์์ ๋ฐ์ดํฐ๋ฅผ ๋ฆฌํด๋ฐ์์ ์ฌ์ฉํ๋ค. | |
### 2. Modularization | |
๋ง์ฝ ์ฌ๋ฌ ๊ฐ์ ํจ์๊ฐ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋น์ทํ ๊ฒ์ ์ฒ๋ฆฌํ ๋ ํ๋์ ๋ชจ๋๋ก ์ฒ๋ฆฌํ ์ ์๋ค. | |
```javascript | |
function add(a, b) { | |
return a + b | |
} | |
function subtract(a, b) { | |
return a - b | |
} | |
module.exports = { | |
add, | |
subtract | |
} | |
``` | |
```javascript | |
const { add, subtract } = require('./calculations') | |
console.log(subtract(5, add(3, 2)) | |
``` | |
### 3. Prefer multiple parameters over single object parameters | |
ํจ์๋ฅผ ์ ์ธํ ๋ ํ๋์ ํ๋ผ๋ฏธํฐ(object parameter)๋ณด๋จ ์ฌ๋ฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ค(specific parameters)์ ์ฌ์ฉํ๋ ๊ฒ์ด ํญ์ ์ข๋ค. | |
```javascript | |
// GOOD | |
function displayUser(firstName, lastName, age) { | |
console.log(`This is ${firstName} ${lastName}. She is ${age} years old.`) | |
} | |
// BAD | |
function displayUser(user) { | |
console.log(`This is ${user.firstName} ${user.lastName}. She is ${user.age} years old.`) | |
} | |
``` | |
๊ทธ๊ฒ์ด ์ข์ ์ด์ ๋ ํจ์ ์ ์ธ๋ถ๋ง ๋ณด๊ณ ๋ ์ด๋ค ํ๋ผ๋ฏธํฐ๊ฐ ํ์ํ ์ง ์ ํํ ์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ง์ฝ์ ๊ฐ์ฒด๋ง ๋ณด๋ด๊ฒ ๋๋ฉด ํจ์์ ํ๋ผ๋ฏธํฐ๊ฐ ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง ํจ์์ ๋ณธ๋ฌธ์ ์ฝ์ด์ผ ํ๋ค. | |
ํ์ง๋ง ์ด๋ ๊ฒ ์ฌ๋ฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ์์ฉ์ด ์๋ ์ง์ ์ด ์๋ค. ๊ทธ ์ง์ ์ ํจ์์ ํ๋ผ๋ฏธํฐ๊ฐ 4๊ฐ์์ 5๊ฐ ์ด์์ผ๋ก ๋์ด๋ ๋์ด๋ค. ์ด๋ ๊ฒ ํจ์์ parameter๊ฐ ๋ง์ด ํ์ํ ๊ฒฝ์ฐ๋ object parameter๋ฅผ ์ฐ๋ ๊ฒ์ผ๋ก ๋ฐ๊ฟ์ผ ํ๋ค. | |
ํ๋ผ๋ฏธํฐ๋ค์ ํจ์์์ ์ ํด์ง ์์๋๋ก ์ ๋ฌ๋์ด์ผ ํ๋ค. ๋ง์ฝ optional parameter๋ฅผ ๊ฐ์ง๋ ๊ฒฝ์ฐ์๋ undefined / null ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฃ์ ๊ฒฝ์ฐ๋ ์๋ค. ๋ง์ฝ object ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ ๊ทธ๋ฅ whole object๋ฅผ ์ ๋ฌํ๊ธฐ๋ง ํ๋ฉด ๋๋ค. | |
### 4. Destructuring | |
Destructuring์ ES6์ ๋์ ๋ ์ข์ ๋๊ตฌ๋ค. ์ด๊ฒ์ object๋ก๋ถํฐ ํน์ ํ ํ๋๋ฅผ ๊ฐ์ง๊ณ ์์ ๋ณ์์ ํ ๋นํ๋ค. | |
``` | |
// EXAMPLE FOR MODULES | |
const { add, subtract } = require('./calculations') | |
``` | |
์ด๋ฐ ๊ฒ๊ณผ ์ ์ฌํ๊ฒ ํจ์์ ํ๋ผ๋ฏธํฐ๋ก object๊ฐ ์ฌ์ฉ๋ ๋ Destructuring์ ์ฌ์ฉํ ์ ์๋ค. | |
```javascript | |
function logCountry({name, code, language, currency, population, continent}) { | |
let msg = `The official language of ${name} ` | |
if(code) msg += `(${code}) ` | |
msg += `is ${language}. ${population} inhabitants pay in ${currency}.` | |
if(contintent) msg += ` The country is located in ${continent}` | |
} | |
logCountry({ | |
name: 'Germany', | |
code: 'DE', | |
language 'german', | |
currency: 'Euro', | |
population: '82 Million', | |
}) | |
logCountry({ | |
name: 'China', | |
language 'mandarin', | |
currency: 'Renminbi', | |
population: '1.4 Billion', | |
continent: 'Asia', | |
}) | |
``` | |
object parameter๋ฅผ ํจ์์ ๋ฃ์ง๋ง ์ด๋ฌํ ๋ฐฉ์์ ์ทจํจ์ ๋ฐ๋ผ ํจ์์ ์ด๋ค ํ๋ผ๋ฏธํฐ๊ฐ ํ์ํ์ง ์ง๊ด์ ์ผ๋ก ์ ์ ์๋ค. | |
### 5. Use default values | |
Default values for destructuring or even basic function parameters are very useful. Firstly, they give you an example of what value you can pass to the function. Secondly, you can indicate which values are required and which are not. Using the previous example, the full setup for the function could look like this: | |
default value๋ฅผ ๋๋ ๊ฒ์ destructuring ๋๋ ์ผ๋ฐ ํจ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ ๋ ์ ์ฉํ๋ค. ์ฐ์ ํจ์์ ์ด๋ค ๊ฐ๋ค์ ๋ฃ์ ์ ์๋์ง ์์๋ก์ ๋ณด์ฌ์ค ์ ์๋ค. ๋ํ ํจ์์ ํ๋ผ๋ฏธํฐ๋ก์ optionalํ ๊ฑด์ง requiredํ ๊ฑด์ง ์ฝ๊ฒ ๋ณด์ฌ์ค ์ ์๋ค. | |
```javascript | |
function logCountry({ | |
name = 'United States', | |
code, | |
language = 'English', | |
currency = 'USD', | |
population = '327 Million', | |
continent, | |
}) { | |
let msg = `The official language of ${name} ` | |
if(code) msg += `(${code}) ` | |
msg += `is ${language}. ${population} inhabitants pay in ${currency}.` | |
if(contintent) msg += ` The country is located in ${continent}` | |
} | |
logCountry({ | |
name: 'Germany', | |
code: 'DE', | |
language 'german', | |
currency: 'Euro', | |
population: '82 Million', | |
}) | |
logCountry({ | |
name: 'China', | |
language 'mandarin', | |
currency: 'Renminbi', | |
population: '1.4 Billion', | |
continent: 'Asia', | |
}) | |
``` | |
๋ช ๋ฐฑํ๊ฒ ๋๋ก default value๋ฅผ ์ฌ์ฉํ์ง ์๊ณ error๋ฅผ throwํ ์๋ ์๋ค. | |
### 6. Data scarcity | |
์ด์ ํ์ ํตํด ํ ๊ฐ์ง ๊ฒฐ๋ก ์ ๋ด๋ ธ๋ค. ํ์ํ์ง ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ์ง ๋ง์. ํน์ ์ง์ ์์ ์ด๋ค ๊ฐ์ด ์ฌ์ฉ๋๋์ง ์ ํํ ์๋ ๊ฒ์ ๋งค์ฐ ์ค์ํ๋ค. | |
### 7. Line and indentation limit | |
์ข ์ข ์ฝ๋๋ฅผ ๋ณด๋ฉด 3,000์ค์ด ๋์ด๊ฐ๋ ํ์ผ์ ๋ณผ ์ ์๋ค. ์ด๋ฐ ํ์ผ์ ๋ณผ ๋ logic์ ์ฐพ๊ธฐ ๋งค์ฐ ํ๋ค๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ file size๋ฅผ ์๋์ ์ผ๋ก ์ ํํ๊ธฐ๋ ํ๋ค. ๋ง์ฝ ์ฝ๋๊ฐ 100์ค์ด ๋์ด๊ฐ๋ค๋ฉด ์ ๋ชจ๋๊ณผ ํ์ผ์ ์ฃผ์ ํ์ง ๋ง๊ณ ๋ง๋ค์. ๋ง์น ์ํ์ค ์ฐ๋งฅ์ฒ๋ผ ํ๋์ ํ์ผ์ด ๊ฑฐ๋ํ ์ฐ๋งฅ์ ์ด๋ฃจ๋๋ก ๋ง๋๋ ๊ฒ์ ๋ถํ์ํ ์ ์๋ค. | |
### 8. Use prettier | |
eslint๋ฅผ ๊ทธ ๋๋ง๋ค ํด์ฃผ์ง ๋ง๊ณ prettier๋ฅผ ์ฌ์ฉํด์ ์ฝ๋๋ฅผ ํ์ํ ํ์. prettier๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ์์ฑํ ๋ formatting์ ์๋์ ์ผ๋ก ํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ด์ ๋ํด ํฐ ๊ฑฑ์ ์ ํ ํ์๊ฐ ์๋ค. | |
### 9. Use meaningful variable names | |
์ด์์ ์ผ๋ก ๋ณ์ / ํจ์์ ์ด๋ฆ์ ์ปจํ ํธ์ ๋ด์ฉ์ ๋ด๊ณ ์์ด์ผ ํ๋ค. | |
#### Functions | |
ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก ์ด๋ ํ ์ก์ ์ ์ํํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํจ์์ ์ด๋ฆ์ ๋์ฌ๋ก ์ง๋ ๊ฒ์ด ์ข๋ค. | |
e.g., `convertCurrency` or `displayUserName`. | |
#### Arrays | |
These will usually hold a list of items; therefore, append an `s` to your variable name. For example: | |
``` | |
const students = ['Eddie', 'Julia', 'Nathan', 'Theresa'] | |
``` | |
#### Booleans | |
Simply start with `is` or `has` to be close to natural language. You would ask something like, โIs that person a teacher?โ โ โYesโ or โNo.โ Similarly: | |
``` | |
const isTeacher = true // OR false | |
``` | |
#### Array functions | |
`forEach`, `map`, `reduce`, `filter`, etc. are great native JavaScript functions to handle arrays and perform some actions. I see a lot of people simply passing `el` or `element` as a parameter to the callback functions. While this is easy and quick, you should also name these according to their value. For example: | |
``` | |
const cities = ['Berlin', 'San Francisco', 'Tel Aviv', 'Seoul'] | |
cities.forEach(function(city) { | |
... | |
}) | |
``` | |
#### IDs | |
Oftentimes, you have to keep track of the ids of specific datasets and objects. When ids are nested, simply leave it as id. Here, I like to map MongoDB `_id`to simply `id` before returning the object to the frontend. When extracting ids from an object, prepend the type of the object. For example: | |
``` | |
const studentId = student.id | |
// OR | |
const { id: studentId } = student // destructuring with renaming | |
``` | |
An exception to that rule is MongoDB references in models. Here, simply name the field after the referenced model. This will keep things clear when populating references documents | |
### 10. Use async / await where possible | |
callback์ ๊ฐ๋ ์ฑ์ ์์ข๊ฒ ๋ง๋ ๋ค. promise๋ผ๋ ์ข์ ํด์ด ์์ง๋ง ์ด ๋ํ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ ๋งํ๋ฉด async / await๋ฅผ ์ฌ์ฉํ๋ค. | |
### 11. Module import order | |
tips1๊ณผ 2์์ ๋ณด์๋ฏ์ด, ์ ์ ํ ์ฅ์์ logic์ ๋๋ ๊ฒ์ maintainability๋ฅผ ์งํค๋ ํต์ฌ์ด๋ค. ์ด๋ฌํ ๊ฒ์ฒ๋ผ, ๋ค๋ฅธ ๋ชจ๋์ ์ด๋ป๊ฒ import ์ํค๋๋ ์ฝ๋๋ฅผ ๋ดค์ ๋์ ํผ๋์ ์ค์ผ ์ ์๋ค. | |
```javascript | |
// 3rd party packages | |
import React from 'react' | |
import styled from 'styled-components' | |
// Stores | |
import Store from '~/Store | |
// reusable components | |
import Button from '~/components/Button' | |
// utility functions | |
import { add, subtract } from '~/utils/calculate' | |
// submodules | |
import Intro from './Intro' | |
import Selector from './Selector' | |
``` | |
### 12. Get rid of console | |
console์ ๋๋ฒ๊น ํ๋๋ฐ ์ ์ฉํ ๋๊ตฌ์ด์ง๋ง, ์ด๊ฒ์ด ๋๋ฌด ๋ง์ผ๋ฉด ์ฝ๋์ ํผ์ก์ ์ผ์ผํจ๋ค. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment