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

2025. 9. 3. 13:50·Software Engineering/Clean Code

 

클린코드 #5 형식 맞추기

 

프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다.
이를 위해 간단한 규칙을 정하고 그 규칙을 착실히 따라야 한다. 팀에 속했다면 팀의 규칙을 따라야 한다.


(요즘은 코드 스타일을 xml 등의 문서로 작성해 IDE에 등록해주면 코드 스타일을 자동으로 적용해준다)


형식을 맞추는 목적

코드 형식은 너무 중요하다. 코드 형식은 의사소통의 일환이다. 너무 중요하니, 코드 형식을 맹목적으로 따르면 안 된다.


오늘 구현한 기능은 언젠간 바뀔꺼고, 오늘 구현한 코드는 앞으로 바뀔 코드 품질에 큰 영향을 미친다.
맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장성에 계속 영향을 미친다.


그러면 대체 원활한 소통을 장려하는 코드 형식은 무어일까?


적절한 행 길이를 유지하라.

소스 코드의 길이는 파일 크기와 밀접하므로 파일 크기 관점에서 살펴보자.


코드 최대 길이가 1000줄까지 되는 프로젝트도 있고, 200줄까지인 프로젝트도 있다. 중요한 건 200줄로도 커다란 시스템을 구축할 수 있다는 것이다. 반드시 지켜야 하는 규칙은 아니지만, 지키면 좋은 규칙이다. 큰 파일보다 작은 파일이 이해하기 쉽기 때문이다.


신문 기사처럼 작성해라

신문 기사에는 최상단에 기사를 몇 마디로 요약하는 표제가 나온다. 독자는 표제를 보고서 기사를 읽을지 말지 결정한다. 두괄식 같은 형식으로 나타나있다.


소스 파일도 신문 기사처럼 작성한다. 이름은 간단하면서도 설명이 가능하게 짓는다. 이름만 보고도 내가 찾는 모듈인지 바로 알 수 있도록 신경써서 지어야 한다. 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명하고, 아래로 내려갈 수록 의도를 세세하게 묘사한다.


개념은 빈 행으로 분리하라

각 행은 수식이나 절을 나타내고, 일련의 행 묶음은 완결된 생각 하나를 표현한다. 따라서 생각 사이에는 빈 행을 넣어 분리해야 마땅하다.


자바라면 패키지명과 import 사이에 빈 행을 넣어주고, 필드와 생성자 사이, 생성자와 메서드 사이에 빈 행을 넣어준다.


세로 밀집도

줄바꿈은 개념을 분리해주지만, 세로 밀집도는 연광성을 의미한다. 서로 밀집한 코드 행은 세로로 가까이 놓아야 한다.
필 ~~~ 드메~~서드 요렇게 쓰면 필드가 몇 개이고 메서드가 몇 개인지 한 눈에 안들어온다. (필드) 개행 (메서드) 요렇게 해두면 필드, 메서드가 어떻게 구성되어 있는지 한 눈에 들어온다.


수직 거리

메서드 안에서 메서드를 호출하는 경우를 생각해보자. 이 함수에서 저 함수 오가며 소스 파일을 위 아래로 뒤지지만, 코드가 미로 같아서 혼란스러운 적이 있을 것이다. (상속 관계에서도 마찬가지다. 소스 코드를 계속 거슬러 올라가고…)
코드 조각이 어디에 있는지 찾고 기억하는데에 시간과 노력을 소모한다.


서로 밀접한 개념은 세로로 가까이 둬야 한다. (하나의 파일에 속하는 경우)
그리고 타당한 이유가 없는 한 밀접한 개념이라면 같은 파일에 위치해야 한다. (protected 변수를 피해야 하는 이유)


세로 거리는 코드 연관성을 표현한다. 연관성이 깊은 개념이 떨어져있으면, 코드를 읽는 사람이 여기저기 뒤지게 된다.


Best Practice

  • 변수 선언: 변수는 사용하는 위치에 최대한 가까이 선언한다.
  • 인스턴스 변수: 클래스 맨 처음에 선언한다.
    • C++은 인스턴스 변수를 마지막에 선언하지만 이는 중요한게 아니다. 중요한 건 모여있다는 점이다.
  • 종속 함수 : 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치해야 한다.
    • (나는 지금까지 public 전부 나열 private 전부 나열 이렇게 했는데, 책의 내용처럼 기능별로 모아두는게 더 좋은 것 같다)
    • 호출하는 함수는 호출되는 함수보다 먼저 배치한다.
      • 고차원 저차원으로 흐르도록
    • 이러면 코드의 흐름이 자연스럽게 읽힌다.
  • 개념적 유사성: 개념적 친화도가 높은 코드일수록 가까이 배치한다.
    • 개념적 친화도 요인
      • 한 함수가 다른 함수 호출 (직접적 종속성)
      • 변수와, 그 변수를 사용하는 함수
      • 비슷한 동작을 수행하는 함수
        • 명명법도 비슷하고, 기본 기능이 유사, …

가로 형식 맞추기

프로젝트 7개를 대상으로 한 행의 가로 길이를 조사해봤더니

  • 10자 미만 : 30%
  • 20 ~ 60자: 40%
  • 80자 이후는 급감

프로그래머는 짧은 행을 선호하고, 짧은 행이 바람직하다.
과거에 비해서 모니터 크기가 커졌다고 해도(200자가 한 화면에 들어오기도 한다), 120자는 넘지 말자.


가로 공백과 밀집도

가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다.

  • 할당 연산자를 강조하기 위해 앞 뒤에 공백을 준다.
    • int lineSize = line.length()
    • 두 가지 요소가 확실히 나뉨이 분명해진다.
  • 함수 이름과 이어지는 괄호 사이에는 공백을 넣지 않는다.
    • private void measureLine(String line() {
    • 함수와 인수는 서로 밀접하기 때문이다.
  • 함수를 호출하는 코드에서 괄호 안 인수는 공백으로 분리한다.
    • lineWidthHistogram.addLine(lineSize, lineCount)
    • 쉼표를 강조해 인수가 별개라는 사실을 보여준다.
  • 연산자 우선순위를 강조하기 위해서도 공백을 사용한다.
    • return (-b + Math.sqrt(determinant)) / (2*a);
    • 승수 사이에는 공백이 없다. 곱셈의 우선순위가 가장 높기 때문이다.
    • 항 사이에는 공백이 들어간다. 덧셈과 뺄셈은 우선 순위가 곱셈보다 낮기 때문이다.

Code Formatter 대부분은 연산자 우선순위를 고려하지 못해 수식에 같은 간격을 적용해버린다. 공백을 넣어도 공백을 없애는 경우가 많다.


가로 정렬

public class FitNesseExpediter implements ResponseSender {
	private Socket                Socket;
	private InputStream           input;
	private OutputStream          output;
	private Request               request;
	// ...

	public FitNesseExpeditor(Socket			s,
							 FitNessContext context) throws Exception {
		this.context = 			  context;
		socket = 				  s;
		input = 					  s.getInputStream();
		//...
	}
}

어셈블리어 시절에는 이런 식의 정렬을 많이 사용했다. 하지만, 이런 식의 가로 정렬은 유용하지 못하다.
코드가 엉뚱한 부분을 강조하여 진짜 의도가 가려지기 때문이다.

  • 변수 유형은 무시하고 변수 이름부터 읽게 된다.
  • 생성자를 보자. 할당 연산자는 보이지 않고, 오른쪽 피연산자에 눈이간다.

정렬하지 않았을 때 중대한 결함을 찾기 쉽다. 정렬할 정도로 목록이 길다면, 목록 길이가 문제지 정렬이 문제가 아니다.
(필드가 너무 많다 정렬해야 할 것 같다 X / 클래스를 분리해야 한다 O)


들여쓰기

소스 파일은 윤곽도처럼 계층을 가지고 있다. 파일 전체, 개별 클래스, 메서드 내부, 블록 내부, …


범위로 이뤄진 계층을 표현하기 위해서 우리는 코드 들여쓰기를 한다. 들여쓰는 정도는 계층에서 코드가 자리잡은 수준에 비례한다.

  • 클래스 정의 같은 파일 수준 들여쓰지 않음
  • 클래스 내 메서드 선언 클래스보다 한 수준 들여씀
  • 메서드 코드 메서드 선언보다 한 수준 들여씀
  • …

프로그래머는 들여쓰기 체계에 크게 의존한다. 들여쓰기의 시각화 덕분에 코드를 빨리 훑을 수 있다.


들여쓰기 무시하기
가끔식 간단한 if문, while문에서 들여쓰기를 무시하고 싶을 수 있다. 또는, 한 행에 몰아 적고 싶을 수 있다.

if (조건) { return; }

저자는 이런 코드를 피한다고 한다. 제대로 들여쓰기를 한다고 한다.


가짜 범위

가끔 빈 while문, for문을 접할 때도 있다. 이런 경우는 피하는게 베스트나, 못 피한다면 빈 블록을 올바로 들여쓰고 괄호로 감싸자.

while (dis.read(buf, 0, readBufferSize) != -1);

이런 코드 대신 아래와 같은 코드를 작성하자.


while (dis.read(buf, 0, readBufferSize) != -1)
; // 새 행에 세미콜론 적기

팀 규칙

프로그래머라면 선호하는 규칙이 있다. 하지만 팀에 속한다면, 팀의 규칙을 선호해야 한다.
팀은 한 가지 규칙을 합의하고 그 규칙을 따르자. 따로 국밥을 만들지 말자.


좋은 SW는 읽기 쉬운 문서로 이뤄진다. 스타일은 일관적이고 매끄러워야 한다.

'Software Engineering > Clean Code' 카테고리의 다른 글

[클린 코드] #7 오류 처리  (0) 2025.09.03
[클린 코드] #6 객체와 자료구조  (0) 2025.09.03
[클린 코드] #4 주석  (0) 2024.11.09
[클린 코드] #3 함수  (0) 2024.11.07
[클린 코드] #2 의미 있는 이름  (0) 2024.11.07
'Software Engineering/Clean Code' 카테고리의 다른 글
  • [클린 코드] #7 오류 처리
  • [클린 코드] #6 객체와 자료구조
  • [클린 코드] #4 주석
  • [클린 코드] #3 함수
lumana
lumana
배움을 나누는 공간 https://github.com/bebeis
  • lumana
    Brute force Study
    lumana
  • 전체
    오늘
    어제
    • 분류 전체보기 (463)
      • 개발 일지 (0)
        • Performance (0)
        • TroubleShooting (0)
        • Refactoring (0)
        • Code Style, Convetion (0)
        • Architecture (0)
      • Software Engineering (36)
        • Test (8)
        • 이론 (18)
        • Clean Code (10)
      • Java (72)
        • Basic (5)
        • Core (21)
        • Collection (7)
        • 멀티스레드&동시성 (13)
        • IO, Network (8)
        • Reflection, Annotation (3)
        • Modern Java(8~) (13)
        • JVM (2)
      • Spring (53)
        • Framework (12)
        • MVC (23)
        • Transaction (3)
        • AOP (11)
        • Boot (0)
        • AI (0)
      • DB Access (16)
        • Jdbc (1)
        • JdbcTemplate (0)
        • JPA (14)
        • Spring Data JPA (0)
        • QueryDSL (0)
      • Computer Science (130)
        • Data Structure (27)
        • OS (14)
        • Database (10)
        • Network (21)
        • 컴퓨터구조 (6)
        • 시스템 프로그래밍 (23)
        • Algorithm (29)
      • HTTP (8)
      • Infra (1)
        • Docker (1)
      • 프로그래밍언어론 (15)
      • Programming Language(Sub) (77)
        • Kotlin (1)
        • Python (25)
        • C++ (51)
        • JavaScript (0)
      • FE (11)
        • HTML (1)
        • CSS (9)
        • React (0)
        • Application (1)
      • Unix_Linux (0)
        • Common (0)
      • PS (13)
        • BOJ (7)
        • Tip (3)
        • 프로그래머스 (0)
        • CodeForce (0)
      • Book Review (4)
      • Math (3)
        • Linear Algebra (3)
      • AI (7)
        • DL (0)
        • ML (0)
        • DA (0)
        • Concepts (7)
      • 프리코스 (4)
      • Project Review (6)
      • LegacyPosts (11)
      • 모니터 (0)
      • Diary (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
lumana
[클린 코드] #5 형식 맞추기
상단으로

티스토리툴바