2021. 6. 1. 15:51ㆍ개발 잡부
나도 나름 코드를 예쁘게 짜는 편이다.
제일 싫어하는게 코드가 눈에 안 들어오는 거라, 스페이스바와 엔터를 아끼지 않는다.
그래서 클린 코더라는 소리를 듣기는 했지만, 클린코드가 뭔지는 사실 잘 몰랐다.
그래서 이번기회에 클린코드가 뭔지 한번 알아보자.
클린 코드를 위한 첫단계, 구상과 설계
깔끔한 코드를 위해서는 깔끔한 프로젝트가 있어야 한다.
구조화와 일반화가 익숙하지 않은 초보 프로그래머들을 보면
이런 식으로 코드를 짜는 경우가 있다. (나도 그랬다)
class Border {
function check() {
대충 x, y 경계를 나가면 true를 반환함
}
}
class Character {
function move(x, y) {
대충 x, y 좌표를 이동하는 코드
대충 x, y가 경계를 나가지 못하게 하는 조건문
근데 Border가 있는지 모르고 그냥 코드를 또 작성함
}
}
복잡한 예시를 들 수 없어서 Unity에서 사용되는 예시를 하나 들고 왔다.
프로젝트 전체를 보면 해당 기능을 하는 함수가 이미 만들어져 있는 경우가 있다.
하지만 그런 기능을 하는 클래스가 있는지 모르고 알고리즘 문제 풀듯,
본인이 작성중인 클래스 안에 모든 로직을 집어넣는 경우가 있다.
이런 문제는 보통 이러한 경우에 생겨난다.
1. 프로젝트 전체 구성이 엉성한 경우.
2. 프로젝트 구성은 좋으나 구조에 대한 이해도가 낮은 경우
3. 둘 다 좋으나 공유가 안 된 경우
그렇기 때문에 UML과 프로젝트 전체 구조에 대해 고민하고, 미리 작성해야 한다.
두번째, 변수와 함수의 이름
책을 보며 코딩의 첫 발을 뗀 프로그래머들이 가장 많이 하는 행동이 있다.
바로 변수명 대충 짓기.
대학교에서도 많이 봤고, 나도 사실 그랬다.
내가 봤던 제일 충격적인 코드는 이렇다. (대충 재연)
let aab = "";
aab += list.join(",");
let abb = 5;
aab += (abb * 100).toString();
그만 알아보자
예제에서는 변수명을 a, b이런 식으로 작성하는 경우가 있다.
그리고 코드도 전체적으로 적으니 어떤 역할을 하는 변수인지 알 수 있다.
하지만 수천, 수만줄의 코드를 보고 있는데 변수명이 aab면 깃 로그를 뒤지게 되어있다.잡히면 죽는다
본론으로 돌아가서, 다음과 같은 규칙대로 변수, 함수명을 지정하면 좋다.
정해진건 아니지만 국룰에 가깝다.
// 1. 언어에 맞는 명명 규칙(naming convention)을 따른다. 자세한건 구글 선생님께 여쭤보자.
// 파이썬은 스네이크 케이스를 사용한다. 스네이크는 띄어쓰기를 _로 바꾸면 된다.
user_first_name = "a"
// 자바스크립트는 카멜 케이스를 사용한다. 카멜은 띄어쓰기 다음 글자를 대문자로 바꾼다.
let userFirstName = "a";
// 대부분의 언어에서 클래스는 파스칼 케이스로 사용한다. 파스칼은 카멜에서 첫 글자도 대문자로 해주면 된다.
class UserFirstName { }
// 2. 변수은 명사로, 함수는 동사로 하면 좋다.
const name = "인호";
function getName() { return "인호"; }
// 특히 함수는 주요 동작을 앞에 두면 좋다. 자주 쓰이는 여러가지 경우를 보자.
function getName() // get: 무언가를 반환하여 받는 경우
function setName(name) // set: 값을 지정(대입)하는 경우
function handleClick(event) // handle: 어떤 이벤트가 발생했을 때 처리하는 경우
function addName(name) // add: 리스트나 키-밸류에 값을 추가하는 경우
// 3. 스페이스와 엔터를 아끼지 말자. (근데 이건 조직의 문화마다 다름)
const pi = 3.14f;
const len = 4;
// 이 두 코드의 가독성을 비교해보자.
const circleArea=(len/2)*(len/2)*pi;
const circleArea = (len / 2) * (len / 2) * pi;
// 개인적으로는 변수 선언 전후, 반환 전, 로직 단위 전후에 줄바꿈을 넣는다.
const circleArea=(len/2)*(len/2)*pi;
circleArea=round(circleArea);
circleArea=circleArea/10;
return circleArea;
// 줄바꿈 + 공백
const circleArea = (len / 2) * (len / 2) * pi;
circleArea = round(circleArea);
circleArea = circleArea / 10;
return circleArea;
세번째, 반복문 최적화
친구에게 오목을 만들라고했더니, 오목이 완성되었는가를 체크하는 코드가 어마어마했다.
한 방향 검사하는 코드를 복붙하여 8방향으로 값 하나씩만 바꿔서 짠 것이다.
일반화가 어려운건 맞지만 하나하나 연습해나가야 한다.
다음의 코드를 최적화 해보자.
// 틱택토 게임
const gameMap = [[1, 2, 1], [0, 1, 2], [2, 1, 0]]
// 가로 체크
if (gameMap[0][0] == gameMap[0][1] && gameMap[0][1] == gameMap[0][2] && gameMap[0][0] != 0) { ... }
if (gameMap[1][0] == gameMap[1][1] && gameMap[1][1] == gameMap[1][2] && gameMap[1][0] != 0) { ... }
if (gameMap[2][0] == gameMap[2][1] && gameMap[2][1] == gameMap[2][2] && gameMap[2][0] != 0) { ... }
// 세로
if (gameMap[0][0] == gameMap[1][0] && gameMap[1][0] == gameMap[2][0] && gameMap[0][0] != 0) { ... }
if (gameMap[0][1] == gameMap[1][1] && gameMap[1][1] == gameMap[2][1] && gameMap[0][1] != 0) { ... }
if (gameMap[0][2] == gameMap[1][2] && gameMap[1][2] == gameMap[2][2] && gameMap[0][2] != 0) { ... }
// 대각선
if (gameMap[0][0] == gameMap[1][1] && gameMap[1][1] == gameMap[2][2] && gameMap[0][0] != 0) { ... }
if (gameMap[2][0] == gameMap[1][1] && gameMap[1][1] == gameMap[0][2] && gameMap[2][0] != 0) { ... }
틱택토에서 총 8가지 라인을 확인하여 승리를 만족했는지 보는 코드이다.
대충 정신이 아득해지는데, 이런 식으로 일반화해볼 수 있다.
// 틱택토 게임
const gameMap = [[1, 2, 1], [0, 1, 2], [2, 1, 0]]
const startPoints = [[0, 0], [0, 1], [0, 2], [0, 0], [1, 0], [2, 0] [0, 0], [2, 0]];
const vectors = [[1, 0], [1, 0], [1, 0], [0, 1], [0, 1], [0, 1], [1, 1], [-1, 1]];
for (let i = 0; i < startPoints.length; i++) {
const s = startPoints[i];
const v = vectors[i];
if (gameMap[s[0]][s[1]] == gameMap[s[0] + v[0]][s[1] + v[1]]
&& gameMap[s[0] + v[0]][s[1] + v[1]] == gameMap[s[0] + v[0] * 2][s[1] + v[1] * 2]
&& gameMap[s[0]][s[1]] != 0) {
...
}
}
어? 코드가 별로 안 줄었는데? 어렵기만 하고 괜히 하는거 아냐?
아니다. if안의 ...에도 일반화된 값을 넣을 수 있다는 것을 생각하면 코드가 어마어마하게 줄어든다.
무엇보다 새로운 내용이 추가되더라도, 복사한 코드를 하나하나 손으로 고치지 않아도 되고,
손으로 고치는 과정에서 오탈자가 생길 가능성이 크다는점,
코드의 덩치가 커져서 가독성이 떨어진다는 점을 고려하면 훨씬 좋다.
그거와는 별개로 코드가 좀 맘에 안 드는데 암튼
내가 회사에 들어갔을 때 처음 배웠던 것은 코딩 컨벤션이었다.
위에서 말한 네임 컨벤션부터, 스페이스바는 어디에 띄우는지,
엔터는 어디에 띄우는지와 같은 내용들부터 배웠다.
그때는 왜 그렇게 호들갑이지 했는데,
코드를 읽다보면 왜 그런지 이해가 간다.
클린 코드는 미래의 나를 위해서도지만, 같이 협업하는 팀원들을 위해서도이다.
그리고 프로젝트가 팔리게 된다면 프로젝트를 활용하는 외부 사람들을 위해서도다.
나와 남을 위한 배려. 그것이 클린코드가 아닐까
코 - 슥
출처 (아래의 원글이 더 유익합니다)
'개발 잡부' 카테고리의 다른 글
야누스 (janus) 비디오룸 플러그인 문서 해석 (0) | 2022.02.24 |
---|---|
콘솔에서 깃 초기화부터 깃허브에 업로드까지 (0) | 2021.06.23 |
[과외] 클래스? 그거 왜 쓰는건데? (0) | 2021.05.26 |
[취준일기] 2021-05-24: 기업 탐색 (0) | 2021.05.26 |
[금붕어] 맨날 까먹는 Git 명령어 모음 (0) | 2020.12.10 |