📖
개발자의 실무를 위한 기본기 - 클린코드
December 19, 2021
어떻게 하면 주니어 개발자로서 성장할 수 있을까? 더 낫은 개발자가 될 수 있을 까 고민하던 중에 인프런에 그랩님이 강의하신 ‘모든 개발자의 실무를 위한 올인원 기본기 클래스’ 강의가 있어 강의를 듣고 Step by Step 공부하고 정리하는 글을 쓰려고 합니다.
1.네이밍
컨벤션
snake_case
: Python, Ruby 등에서 권장cameCase
: Java, Javascript 등에서 권장PascalCase
: 대부분의 프로그래밍 언어에서 클래스를 네이밍할 때 사용kebab-case
: HTML Element를 표현할 때 사용
네이밍
-
변수 : 명사 혹은 형용사로 작성
const userData = ... // 명사 const isValid = ... // 형용사
-
함수와 메서드 : 동사 혹은 형용사로 작성
function sendData() { ... } function inputIsValid() { ... }
-
클래스 : 일반적으로 명사로 작성
let Client = new Object();
Tip
구체적이고 명시적으로 적을 것, 짧고 애매한 표현보다 길고 직관적인 표현이 낫다.
// as-is
const dt = '20211219KST';
// to-be
const datetimeWithTimezone = '20211219KST';
2. 주석, 포맷팅
2. 1 주석
네이밍으로 표현할 수 없는 영역을 주석으로 표현
-
법적인 정보를 담을 때
// Copyright (c) 2021...
-
의도를 명확하게 설명할 떄
// throughput을 늘리기 위해 스레드를 10개까지 늘린다. for (let idx = 0; idx < 11; idx++) { thread = threading.Thread(target=...) thread.start() }
-
중요성을 강조할 떄
// 최종 결재를 하기 전에 진행해야 하는 validation gkatn
-
결과를 경고할 떄
// WARNING: API 서버가 항상 양호한지 알 수 없음 function connectApiServer() { ... }
2. 2 관용적으로 사용되는 키워드
TODO
: 당장은 아니지만 다음에 해야할 때FIXME
: 치명적인 에러를 발생하는 코드는 아지미나 수정해야 할 때XXX
: 더 생각해볼 필요가 있을 떄
2. 3 포맷팅
Vertical Formatting
-
한 파일에 코드를 다 넣지 말고, 개념에 맞게 파일을 나눠서 사용
// as-is // store.js에 전부 있음 const FruitsStore = new Object(); const DesertStore = new Object(); // to-be // FruitStore.js const FruitsStore = new Object(); // DesertStore.js const DesertStore = new Object();
-
다른 개념의 코드는 Spacing으로 분리
-
비슷한 개념의 코드는 붙여서 사용
function testUserByProduct() { const user = new User() const product = new Product() product.setSoldOut(true) user.get(product) }
Horizontal Formatting
-
한 줄에 코드를 다 넣기보단 변수 등을 활용해서 가독성 높이기
// as-is personList.extend([Person('adam'), Person('even'), Person('noa')]) // to-be const items = [Person('adam'), Person('even'), Person('noa')]; personList.extend(items);
3. 함수
3. 1 함수의 역할은 하나만 - SRP (Single Responsibility Principle)
-
as-is
const Database = new Object(); function createUser(email, password) { if (!email.includes('@') || email.length < 6) { throw new Error('유저 정보를 제대로 입력하세요') } const user = {"email" : email, "password" : password}; const database = Database("mysql") database.add(user) const emailClient = EmailClient() emailClient.setConfig(...) emailClient.send(email, "회원가입을 축하합니다") return true } createUser('@faeafaa', 'af')
-
to-be
function createUser(email, password) { validateCreateUser(email, password); const user = buildUser(email, password) saveUser(user) sendEmail(email) return } function validateCreateUser(email, password) { if (!email.includes('@') || email.length < 6) { throw new Error('유저 정보를 제대로 입력하세요') } } function buildUser(email, password) { return { "email": email, "password": password } } function saveUser(user) { const database = Database("mysql") database.add(user) } function sendEmail(email) { const emailClient = EmailClient() emailClient.setConfig(...) emailClient.send(email, "회원가입을 축하합니다") }
3. 2 반복하지 말자 - DRY (Don’t Repeat Yourself)
-
as-is
function createUser(email, password) { if (!email.includes('@') || email.length < 6) { throw new Error('유저 정보를 제대로 입력하세요') } } function updateUser(email, password) { if (!email.includes('@') || email.length < 6) { throw new Error('유저 정보를 제대로 입력하세요') } }
-
to-be
function validateCreateUser(email, password) { if (!email.includes('@') || email.length < 6) { throw new Error('유저 정보를 제대로 입력하세요') } } function createUser(email, password) { validateCreateUser(email, password) } function updateUser(email, password) { validateCreateUser(email, password) }
3. 3 파리미터 수는 적게 유지하자
-
as-is
const User = function (name, age, sex) { console.log(`안녕하세요 저의 이름은${name}이고, 나이는 ${age}, ${sex} 입니다.`) } const Adam = User('adam', '30', 'male')
-
to-be
const Person = function (name, age, sex) { this.name = name; this.age = age; this.sex = sex; } const User = function (person) { console.log(`안녕하세요 저의 이름은${person.name}이고, 나이는 ${person.age}, ${person.sex} 입니다.`) } const Eve = new Person('eve', 25, 'female') const newUser = User(Eve);
3. 4 사이드 이펙트를 잘 핸들링하자
사이드 이펙트(Side Effect)는 함수가 실행됐을 때 함수 이외의 어떤 것들에 변화를 주는 것을 뜻한다. 사이드 이펙트를 잘 다루지 못하면, 예측하지 못하는 문제들이 발생할 수 있다.
// 사이드 이펙트 X
function getUserInstance(email, password) {
user = User(email, password)
return user
}
// 사이드 이펙트 O
function updateUserInstance(user) {
user.email = 'new email';
}
// 사이드 이펙트 O
function createUser(email, password) {
user = User(email, password)
startDBSession(); // 외부 DB Session에 변화를 줄 수 있다.
}
사이드 이펙트를 잘 핸들링 하는 방법
- 코드를 통해 충분히 예측할 수 있도록 네이밍을 잘하는 것이 중요
- update, set 같은 직관적인 prefix를 붙여서 사이드 이펙트가 있을 수 있음을 암시
- 함수의 사이드 이펙트가 있는 부분과 없는 부분으로 잘 나눠서 관리
- 명령(side effect O)과 조회(side effect X) 를 분리하는
CQRS
방식이 있다
- 일반적으로 update를 남발하기 보단 순수 함수 형태로 사용하는 것이 더 직관적이고 에러를 방지할 수 있다.
-
as-is
const carts = [] function addCart(product) { carts.push(product) } const product = Product(...) addCart(product)
-
to-be
const cart = ['apple', 'orange'] function getAddedCart(product) { return [...cart, product] } const carts = getAddedCart('mango') console.log(carts)
순수함수란?
- 어떤 함수에 동일한 인자를 주었을 때 항상 동일한 값을 리턴하는 함수
- 외부의 상태를 변경하지 않는 함수
- 참조 블로그