[클린코드] 5장 형식 맞추기

wlsh44·2022년 10월 2일
0

클린코드

목록 보기
5/8

다른 사람들과 협업을 하게 되면 다양한 규칙을 적용해야 한다.
코드 외적으로는 VCS와 관련된 브랜치 전략, 이슈 관리, 커밋 컨벤션 등이 있다.
코드 내적 형식으로는 인덴트, 함수 길이, 주석, 이름 등 정말 다양한 컨벤션을 정할 수 있다.
또 이를 정했다면 IntelliJ의 플러그인인 checkStyle-IDEA와 같은 lint를 이용해 쉽게 적용할 수 있다.

좋은 코드 형식으로 모든 개발자가 코드를 작성하면 코드를 리뷰할 때 분명히 도움이 된다.
그렇기에 이 장에서는 어떤 형식으로 코드를 작성하는게 좋은지에 대해 설명한다.

적절한 행 길이를 유지하라

소스 코드의 길이에 관한 내용이다.

책에서는 Junit과 같은 큰 프로젝트도 대부분 소스 코드가 50줄에서 100줄 이내로 작성 되는 것을 보여준다.
즉, 작은 파일로도 커다란 프로젝트를 만들 수 있다.

작은 파일을 만들면 가독성에도 좋을 뿐더러 단일 책임 원칙도 지키기 쉬워진다.
소스 코드가 길다면(주석을 제외하고) 분명 객체가 여러 가지 일을 하고 있을 가능성이 높기 때문이다.

신문 기사처럼 작성하라

소스 파일도 신문 기사와 비슷하게 작성한다.
이름은 간단하면서도 설명이 가능하게 짓는다.
이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단 할 정도로 신경 써서 짓는다.
소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다.
아래로 내려갈수록 의도를 세세하게 묘사한다.

부연 설명이 필요 없을 것 같다.
너무 당연한 말이다. 심심할 때마다 한 번씩 상기하기 위해 적었다.


그런데 스터디에서 이 부분에 관해 재미있는 질문이 있었다.
코드를 고차원에서 저차원으로 적어야 하는 것은 분명히 맞지만 대부분의 개발자들이 그러지 않는 코드가 있다.

바로 상수이다.

상수같은 경우는 언제나 코드의 맨 상단에 위치하며 언제나 선언과 동시에 초기화 되기 때문에 저차원의 코드라고 볼 수 있다.

private final static int SOME_MAGIC_NUMBER = 20;

public int func() {...}

코드를 읽을 때 저 상수 값이 뭔지 알아야 하는 경우는 드물 것이다.

아마 관습처럼 해온 방식이고 모두가 크게 의식하지 않기 때문에 바꾸려고 노력하지는 않겠지만, 어쩌면 여러 관습 중에 악습(?)이 존재할 수도 있고 언제나 관습을 따라가기 보다는 '왜 이렇게 하지?' 라는 생각은 꼭 하고 넘어가는 버릇을 들여야 겠다고 생각했다.

개념은 빈 행으로 분리하라

빈 행은 가독성을 높여주기도 하면서 동시에 개념도 분리해준다.

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@RequiredArgsConstructor
public class SomeService {
    private final static int SOME_MAGIC_NUMBER = 20;

	private final OtherService otherService;
    private String someString;

    public int func1() {...}

    public int func2() {...}
}

Intellij에서 import 문도 자세히 보면 외부 디팬던시와 다른 패키지, 자바 라이브러리와 같은 형식으로 분리되어있다.
또한 상수와 변수, 함수끼리도 빈 행으로 분리되어있다.

이를 통해 각 코드들이 어떤 개념으로 묶여있는지 쉽게 알 수 있다.
또한 이 빈 행들을 다 지우지 않아도 충분히 가독성이 떨어질 거라고 예상할 수 있다.

수직 거리

변수는 사용하는 위치에 최대한 가까이 선언한다.

사용하는 위치와 떨어져 선언된 변수는 코드를 읽다가 다시 위로 올라가게 만든다.

다만 개인적으로는 선언보다는 초기화라는 단어가 더 맞다고 생각한다.
또한 이와 동시에 선언되는 코드가 제일 좋은 것 같다.

예전 c언어 스타일에서는 선언과 초기화를 분리하는 경우가 많았다.
특히 42서울의 코드 형식을 맞출 때는 무조건 분리해야 했었다.

나 같은 경우에는 c언어 스타일의 코드는 쓸데없이 코드가 길어지고 괜히 가독성이 떨어지는 것 같다는 생각했다.
이 생각은 최근에 자바를 사용하고 선언과 초기화를 동시에 하면서 더 확실하게 느껴졌다.

개인 취향인 부분이겠지만 나에게는 조금 호불호가 심한 부분인 것 같다.

종속 함수

한 함수 내에서 호출되는 다른 함수를 뜻한다.
이 함수들은 최대한 가까이 배치하여 코드를 페이지의 이동을 최소화 하면 코드를 읽는데 도움이 된다.

하나의 public 메서드 내에서 호출되는 private 메서드들이 여기에 해당 된다.

public void publicFunc1() {
	privateFunc1();
}

private void privateFunc1() {...}

public void publicFunc2() {
	privateFunc2();
    privateFunc3();
}

private void privateFunc2() {...}

private void privateFunc3() {...}

개념적 유사성

종속 관계가 아니더라도 개념적으로 유사한 함수들은 가까이 두는게 좋다.
책에서는 Junit의 예를 들었다.

public class Assert {
	static public void assertTrue(String message, boolean condition) {...}
    
    static public void assertTrue(boolean condition) {...}
    
   	static public void assertFalse(String message, boolean condition) {...}
    
   	static public void assertFalse(boolean condition) {...}

위 코드들은 오버로드 관계 또는 답을 boolean 형식으로 내는 유사한 개념을 가지고 있다.
그렇기 때문에 같이 두는 것이 자연스러워 보인다.

세로 순서

앞에서 언급했듯이 고차원에서 저차원으로 코드를 작성해야 한다.
세세한 사항을 가장 아래로 두자.

가로 형식 맞추기

책에서는 가로 길이 100~120자 정도는 괜찮다고 한다.

42서울에서 가로 길이 75줄 컨벤션으로 작성을 했었는데, 특히나 상수가 들어간 코드를 적을 때 지키기 힘들었다.

너무 길어도 안 좋지만 너무 짧아도 안 좋은 것 같다.

가로 공백과 밀집도

할당문이나 loop문의 괄호같은 경우에는 공백을, 함수의 괄호같은 경우에는 공백을 추가하지 않는다.

공백이 있으면 서로 다른, 없으면 같은 개념으로 인식된다.


다만 연산자 우선순위를 위해 우선순위가 높은 코드에는 공백을 넣지 않고, 그 외의 우선순위를 가진 연산자에는 공백을 넣는 부분은 마음에 들지 않았다.

스터디때 다른 분이 언급했다시피 소괄호를 이용한 우선순위 표현이 더 나은 방식인 것 같다.

만약 소괄호때문에 식이 복잡해졌다면 그건 소괄호의 잘못이 아니라 애초에 식을 깔끔하게 정리하지 못했을 수도 있을거라는 생각이 들었다.

가로 정렬

어셈블리 형식을 맞추는 형식이다.
이 또한 42서울에서 맞춰야 했던 형식이며, 개인적으로 제일 거부감이 들었다.

public		String			a;
public		int				b;
private		SomeLongClass	c;
protected	long			d;

이런 형식이다.
만약 중간에 SomeLongClass보다 긴 이름의 클래스 타입을 가진 변수를 선언해야 한다면 기존의 모든 정렬을 다시 맞춰주어야 한다.

책에서도 코드가 엉뚱한 부분을 강조하기 때문에 의도가 가려져 좋은 형식이 아니라고 한다.

다시는 이런 형식의 코드를 작성하지 않았으면 좋겠다. 😂

들여쓰기

책에서는 들여쓰기로 범위를 제대로 표현하라고 한다.
나 역시 이 부분에 공감한다.

하지만 한 줄짜리 코드 정도는 취향이라고 생각한다.

public String render() throws Exception {
	return "";
}

public String render() throws Exception { return ""; }

다만 개인적으로 한 줄짜리 loop 문 같은 경우에는 들여쓰기가 있었으면 한다.
정확히 말하자면 {} 이 있으면서 들여쓰기가 있는 코드가 제일 잘 보이고 {} 이 없으면서 들여쓰기가 있는 코드가 제일 읽기 힘들었다.

// 제일 잘 읽힘
for (int i = 0; i < N; i++) {
	//do something
}

// 그 다음으로 잘 읽힘
for (int i = 0; i < N; i++) //do something

// 제일 안 읽힘
for (int i = 0; i < N; i++)
	//do something

하지만 이 부분은 분명히 취향이라고 생각이 되고 다른 사람들은 어떻게 생각하는지 궁금하기도 하다.

느낀 점

42서울 코드 컨벤션이 새록새록 기억이 나는 장이었다.
분명 불만도 많았고 힘들었지만 덕분에 코드를 하나의 형식에 맞춰 작성하고 하나의 함수를 잘게 쪼개는 연습을 잘 하게 된 것 같다.
물론 다시 하라고 하면 안 할거다.😄

profile
정리정리

0개의 댓글