위 사진은 배선정리가 끝난 뒤, 모습이다.
여러분의 코드는 배선 정리가 필요하다. 배선 정리가 안 되어있어도 잘 작동하지만 코드의 내용을 파악하기 위해 선들을 하나하나 볼 때면 왜 배선 정리를 하지 않았는지 후회할 것이다.
“코드 형식은 매우 중요하다”
오늘 구현한 기능이 다음 버전에서 바뀔 확률은 아주 높다.
그러나 오늘 구현한 코드의 가독성은 앞으로 바뀔 코드의 품질에 지대한 영향을 미친다.
1. 적절한 행 길이를 유지하라
다음의 그림은 파일의 길이 분포, 로그 배율을 표로 나타낸 그림이다.
JUnit, fitnese와 같은 파일을 보면 대부분의 파일 크기가 200줄 미만이다.
200줄 미만의 길이의 코드 파일로도 커다란 시스템을 구축 할 수 있다.
📢 파일의 길이는 200~300줄을 넘지 않도록 한다.
2. 신문 기사처럼 작성하라
이름은 간단하면서도 설명이 가능하게, 소스파일의 첫 부분은 고차원 개념과 알고리즘을 설명하고, 아래로 내려갈수록 세세하게 묘사한다.
3. 개념은 빈 행으로 분리하라
쉽게 설명하면 줄바꿈을 이용해서 비슷한 개념끼리 묶으라는 말이다.
package Naver_Api_Test.service;
import Naver_Api_Test.Dto.UserDto;
import Naver_Api_Test.domain.entity.User;
import Naver_Api_Test.domain.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
public User saveUser(UserDto userDto) {
User user = User.builder()
.name(userDto.getName())
.Email(userDto.getEmail())
.build();
return userRepository.save(user);
}
public void findUserById(Long id) {
}
}
위의 함수와 밑의 함수는 똑같은 함수인데 밑의 함수는 빈 행을 빼버린 코드다.
package Naver_Api_Test.service;
import Naver_Api_Test.Dto.UserDto;
import Naver_Api_Test.domain.entity.User;
import Naver_Api_Test.domain.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
public User saveUser(UserDto userDto) {
User user = User.builder().name(userDto.getName()).Email(userDto.getEmail()).build();
return userRepository.save(user);}
public void findUserById(Long id) {}
}
간단한 줄바꿈으로도 코드의 가독성을 높일 수 있다.
4. 비슷한 기능을 수행하는 코드는 가까이 붙여라
비슷한 기능을 수행하는 코드를 밀접하게 붙이면 코드의 연관성을 이해하는데 큰 도움이 된다.
변수 선언
변수는 사용하는 위치에 최대한 가까이 선언한다.
- 함수에서 사용하는 지역변수는 각 함수의 맨 앞에 선언한다.
- 인스턴스 함수는 클래스 맨 앞에 선언한다.
- (종속함수의 경우) 호출하는 함수를 호출되는 함수보다 앞에 배치한다.
5. 적절한 열 길이를 유지하라.
위 그림은 프로젝트 7개에서 조사한 행 길이 분포다.
표를 보면 0~80자 이후로 그래프가 급격하게 내려가는 모습을 볼 수 있다.
프로그래머는 명백하게 짧은 행을 선호하며, 대형 프로젝트에서도 짧은 행을 선호하는 것을 알 수 있다.
Intellij에서도 세로로 120자를 넘어가면 warning이 뜬다.
6. 가로 공백을 통해 밀접한 개념과 느슨한 개념을 표현하라.
lineWidthHistogram.addLine(lineSize, lineCount);
double determinant = determinant(a, b, c);
return (-b + Math.sqrt(determinant)) / (2*a);
1,2번째 줄에서는 인 사이에 공백이 있음을 볼 수 있다.
쉼표를 강조해 인수가 별개인 사실을 보여주기 위해서 공백을 보여준 것이다.
3번째 줄에서는 곱셈 사이에는 공백이 없고 사칙연산에는 공백이 있음을 볼 수 있다.
이는 우선 순위를 나타내기 위해 공백을 넣은 것이다.
📢 그러나 요즘에는 개발도구가 코드 형식을 자동으로 맞춰준다.
7. 들여쓰기를 준수하라.
들여 쓰는 수준이 소스파일 내에서 해당 코드의 계층의 깊이를 보여준다.
들여 쓰기를 하지 않으면 코드의 가독성이 매우 떨어지므로 꼭 해야 한다.
*요즘 개발 도구들은 들여 쓰기를 해주는 단축키가 있다.
//worst case 들여쓰기를 하지 않은 코드
public class FitNesseServer implements SocketServer { private FitNesseContext
context; public FitNesseServer(FitNesseContext context) { this.context
context; } public void serve(Socket s) { serve(s, 10000); } public void
serve(Socket s, long requestTimeout) { try { FitNesseExpediter sender = new
FitNesseExpediter(s, context);
sender.setRequestParsingTimeLimit(requestTimeout); sender.start(); }
catch(Exception e) { e.printStackTrace(); } } }
//good case 들여쓰기를 한 코드
public class FitNesseServer implements SocketServer {
private FitNesseContext context ;
public FitNesseServer(FitNesseContext context) {
this.context = context;
}
public void serve(Socket s) {
serve(s, 10000);
}
public void serve(Socket s, long requestTimeout) {
try {
FitNesseExpediter sender = new FitNesseExpediter(s, context);
sender.setRequestParsingTimeLimit(requestTimeout);
sender. start();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
8. 가짜 범위
때로 빈 while문이나 for문을 접하는데, 이런 경우 키워드 괄호 끝에 세미콜론(;)을 개행해서 넣어주도록 하자.
while (dis.read(buf, 0, readBufferSize) != -1)
;