1. 주석
경솔하고 근거 없는 주석은 코드를 이해하기 어렵게 만든다. 오래되고 조잡한 주석은 거짓된 잘못된 정보를 퍼뜨려 해악을 미칩니다. 프로그래밍 언어를 치밀하게 사용해 의도를 표현할 능력이 있다면, 주석은 거의 필요하지 않을 것 입니다.
주석은 오히려 거짓말을 한다. 시간이 지날수록 주석을 작성할 당시의 의도는 잊혀지고, 그릇될 가능성이 높다. 코드에 주석을 추가하는 이유는 코드 품질이 나쁘기 때문입니다. 모듈을 짜고 보니 짜임새가 엉망이고, 알아먹기 어렵기 때문에 주석을 쓰려고 합니다.
// 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
if (employee.isEligibleForFullBenefits())
1) 좋은 주석
때로는 회사가 정립한 구현 표준에 맞춰 법적인 이유로 특정 주석을 넣으라고 명시합니다. 저작권 정보나 소유권 정보는 필요하고도 타당하다. (IDE는 주석 헤더를 자동으로 축소)
- 법적인 주석
- 정보를 제공하는 주석
- 의도를 설명하는 주석
- 의미를 명료하게 밝히는 주석
- 결과를 경고하는 주석 : 다른 프로그래머에게 결과를 경고할 목적으로 주석을 사용합니다.
- TODO 주석 : '앞으로 할 일'을 주석으로 남겨두면 좋다.
- 중요성을 강조하는 주석
// Copyright (C) 2003, 2004, 2005 by Object Mentor, Inc. All rights reserved.
// GNU General Public License 버전 2 이상을 따르는 조건으로 배포합니다.
// kk:mm:ss EEE, MMM dd, yyyy 형식이다.
Pattern timeMatcher = Pattern.compile(
"\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*"
);
2) 나쁜 주석
- 주절거리는 주석 : 다른 사람이 이해하지 못한다면 쓰지 않는 것이 좋다.
- 같은 이야기를 중복하는 주석
- 의무적으로 다는 주석
- 오해할 여지가 있는 주석
- 이력을 기록하는 주석
- 있으나 마나 한 주석
- 함수나 변수로 표현할 수 있다면 주석을 달지 마라
- 위치를 표시하는 주석
- 닫는 괄호에 다는 주석
- 공로를 돌리거나 저자를 표시하는 주석
- 주석으로 처리한 코드 : 작성하지마라. 소스 코드 관리 시스템을 활용하라.
2. 형식 맞추기
프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 합니다. 코드 형식을 맞추기 위한 간단한 규칙을 정하고, 그 규칙을 착실히 따라야 합니다. 그렇다면 원활한 소통을 장려하는 코드 형식을 무엇일까?
1) 적절한 행 길이를 유지하라.
소스 코드는 얼마나 길어야 적당할까? 프로젝트 7개를 조사한 결과, 평균 파일 크기는 약 65줄이고, 전체 파일 중 대략 1/3이 40줄에서 100줄 조금 넘는 정도이고, 거의 500줄을 넘지 않고 대부분 200줄 정보인 파일로도 시스템을 구축할 수 있습니다.
2) 신문 기사처럼 작성하라.
소스 파일도 기사와 비슷하게 작성합니다. 이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단할 정도로 신경 써서 짓습니다. 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명하고, 아래로 내려갈수록 의도를 세세하게 묘사합니다. 마지막에는 가장 저차원 함수와 세부 내역이 나옵니다.
3) 개념은 빈 행으로 분리하라.
소스 코드를 보면 패키지 선언부, import문, 각 함수 사이에 빈 행이 들어갑니다. 간단한 규칙이지만 새로운 개념을 시작한다는 시각적 단서가 됩니다.
4) 수직 거리
- 함수 연관 관계에 따라 밀접한 개념은 세로로 가까이 둬야 합니다. 타당한 근거가 없다면 서로 밀접한 개념은 한 파일에 속하는 것이 맞습니다.
- 변수도 사용하는 위치에 최대한 가까이 선언합니다. 우리가 만든 함수는 매우 짧으므로 지역 변수는 각 함수 맨 처음에 선언합니다.
5) 개념적 유사성
어떤 코드는 서로 끌어당기는데, 친화도가 높을수록 코드를 가까이 배치합니다. 비슷한 동작을 수행하는 함수라면 세로로 가까이 위치시킵니다.
6) 세로순서
호출되는 함수를 호출하는 함수보다 나중에 배치합니다. 그러면 소스 코드 모듈이 고차원에서 저차원으로 자연스럽게 내려가게 됩니다. 가장 중요한 개념을 가장 먼저 표현하고, 세세한 사항은 가장 마지막에 표현합니다.
7) 가로 형식 맞추기
가로로는 얼마나 길어야 할까? 전체 40% 정도는 20 ~ 60자 정도 입니다. 그리고 10자 미만이 30% 정도 입니다. 프로그래머는 명백하게 짧은 행을 선호합니다.
8) 밥 아저씨의 형식 규칙
코드 자체가 최고의 구현 표준 문서가 되는 예이다.
public class CodeAnalyzer implements JavaFileAnalysis {
private int lineCount;
private int maxLineWidth;
private int widestLineNumber;
private LineWidthHistogram lineWidthHistogram;
private int totalChars;
public CodeAnalyzer() {
lineWidthHistogram = new LineWidthHistogram();
}
public static List<File> findJavaFiles(File parentDirectory) {
List<File> files = new ArrayList<File>();
findJavaFiles(parentDirectory, files);
return files;
}
private static void findJavaFiles(File parentDirectory, List<File> files) {
for (File file : parentDirectory.listFiles()) {
if (file.getName().endsWith(".java"))
files.add(file);
else if (file.isDirectory())
findJavaFiles(file, files);
}
}
}
3. 객체와 자료 구조
1) 자료 추상화
- 아래와 같이 구체적인 클래스와 추상적인 클래스가 있는데, 어떤 클래스가 좋은 클래스 일까요?
- 자료를 세세하게 공개하기 보다는 추상적인 개념으로 표현하는 편이 좋습니다. 개발자는 객체가 포함하는 자료를 표현할 가장 좋은 방법을 심각하게 고민해야 합니다. 아무 생각 없이 조회/설정 함수를 추가하는 방법이 가장 나쁘다.
// 구체적인 Point 클래스
public class Point {
public double x;
public double y;
}
// 추상적인 Point 클래스
public interface Point {
double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
// 구체적인 Vehicle 클래스
public interface Vehicle {
double getFuelTankCapacityInGallons();
double getGallonsOfGasoline();
}
// 추상적인 Vehicle 클래스
public interface Vehicle {
double getPercentFuelRemaining();
}
2) 자료 / 객체 비대칭
- 절차적인 코드는 기존 자료 구조를 변경하지 않으면서, 새 함수를 추가하기 쉽습니다. 하지만 새로운 자료 구조를 추가하기 어렵습니다.
- 반면, 객체 지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽습니다. 하지만 새로운 함수를 추가하기 어렵습니다. 그러려면 모든 클래스를 고쳐야 합니다.
3) 디미터 법칙
- 디미터 법칙은 잘 알려진 휴리스틱으로, 모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다는 법칙입니다. 앞 절에서 봤듯이 객체는 자료를 숨기고 함수를 공개합니다.
- 좀 더 정확히 표현하면, "클래스 C의 메서드 f는 다음과 같은 객체의 메서드만 호출해야 합니다."고 주장합니다.
- 자료 구조는 무조건 함수 없이 공객 변수만 포함하고, 객체는 비공개 변수와 공개 함수를 포함한다면 문제는 훨씬 간단할 것 입니다.
4) 자료 전달 객체
- 자료 구조체의 전형적인 형태는 공개 변수만 있고, 함수가 없는 클래스 입니다. 자료 구조체를 때로는 DTO라고 하는데, 애플리케이션 코드에서 사용할 객체로 변환하는 일련의 단계에서 가장 처음으로 사용하는 구조체 입니다.
public class Address {
private String street;
private String streetExtra;
private String city;
private String state;
private String zip;
public Address(
String street, String streeExtra,
String city, String state, String zip
) {
this.street = street;
this.streetExtra = streetExtra;
this.city = city;
this.state = state;
this.zip = zip;
}
public String getStreet() {
return street;
}
public String getStreetExtra() {
return streetExtra;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
public String getZip() {
return zip;
}
}
5) 결론
- 객체는 동작을 공개하고, 자료를 숨긴다. 그래서 기존 동작을 변경하지 않으면서 새 객체 타입을 추가하기는 쉬운 반면, 기존 객체에 새 동작을 추가하기는 어렵습니다.
- 자료구조는 별다른 동작 없이 자료를 노출합니다. 그래서 기존 자료 구조에 새 동작을 추가하기는 쉬우나, 기존 함수에 새 자료 구조를 추가하기는 어렵습니다.
'Software Tech > Spring (feat.JAVA)' 카테고리의 다른 글
[클린코드] 4. 경계 & 단위테스트 (2) | 2025.05.19 |
---|---|
[클린코드] 3. 예외처리 (0) | 2025.05.19 |
[클린코드] 1. 깨끗한 코드와 함수 (1) | 2025.05.15 |
[AOP] Aspect & Logging (feat. SpringBoot) (0) | 2025.05.12 |
[Java] Spring 시작하기 (0) | 2025.01.07 |