728x90
목차
1. 의도를 분명히 밝혀라
- 변수의 존재 이유, 기능, 사용법 등이 변수/함수/클래스명에 드러나야한다. 따로 주석이 필요하지 않을 정도로.
- 의미를 함축하거나 코드를 읽는 사람이 사전지식을 가지고 있다고 가정하지 말자.
- 예시 1
//Bad
int d; (X)
//Good
int elapsedTimeInDays;(o)
int daysSinceCreation;(o)
- 예시 2
//Bad
public List<int[]> getThem(){
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList){
if(x[0]==4){
list1.add(x);
}
}
return list1;
}
//Good - 좀 더 명확히 해당 리스트가 어떤 리스트인지 알 수 있다.
public List<int[]> getFlaggedCells(){
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard){
if(cell[STATUS_VALUE]==FLAGGED){
flaggedCells.add(x);
}
}
return flaggedCells;
}
2. 그릇된 정보를 피하라
- 중의적으로 해석될 수 있는 이름 지양하기
- 개발자에게는 특수한 의미를 가지는 단어(List 등)는 실제 컨테이너가 List가 아닌 이상 accountLIst와 같이 변수명에 붙이지 말다. 차라리 accountGroup, bunchOfAccounts, accounts 등으로 명명하자
- 비슷해 보이는 명명에 주의하자.
3. 의미 있게 구분하라 (불용어-noise word-를 쓰지 말자)
- 불용어 = 의미를 정확하게 구분하기 어려운 용어를 쓰지 말것
- [a1, a2, ...] 과 같이 숫자로 구분하는 경우 (x)
- 클래스 이름에 Info, Data와 같은 불용어를 붙이지 말자. 정확한 개념 구분이 되지 않음
- 예시 (왼쪽이나 오른쪽이나 뭘 써야할지 구분이 안된다)
- Name vs NameString
- getActiveAccount() vs getActiveAccounts() vs getActiveAccountInfo() (이들이 혼재할 경우 서로의 역할을 정확히 구분하기 어렵다.)
- money vs moneyAccount
- message vs theMessage
- 예시 (왼쪽이나 오른쪽이나 뭘 써야할지 구분이 안된다)
- 읽는 사람이 차이를 알도록 이름을 짓자.1
4. 발음하기 쉬운 이름을 사용하라
//Bad
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
/*...*/
}
//Good
class Customer {
private Date generationTimeStamp;
private Date modificationTimeStamp;
private final String recordId = "102";
/*...*/
}
5. 검색하기 쉬운 이름을 사용하라
- 상수는 static final과 같이 정의해 쓰자.
- 변수 이름의 길이는 변수의 범위에 비례해서 길어진다. 예를 들면 지역변수는 e 라는 이름을 써도 되지만, 전역 변수 같은 경우 e를 쓴다면 거의 모든 문장에 포함되기때문에 찾기 어려워 진다. 그래서 int FINAL_NUMBER 이런식으로 이름을 길게 작성해줘야한다.
6. 인코딩을 피하라 (변수에 부가 정보를 덧붙여 표기하는 것을 뜻함.)
- 헝가리안 표기법
- 변수명에 해당 변수의 타입(String, Int 등)을 적지 말자
- 멤버 변수 접두어
- 멤버 변수 접두어를 붙이지 말자
//Bad
public class Part{
private String m_disc; // 설명 문자열-멤버 변수 접두어 "m_"이 포함됨
void setName(String name){
m_disc = name;
}
}
//Good
public class Part{ //클래스와 함수는 접두어가 필요없을 정도로 작아야 마땅하다.
String description;
void setDescription(String description){
this.description = description;
}
}
- 인터페이스와 구현
- 인터페이스 클래스와 구현 클래스를 나눠야 한다면 구현 클래스의 이름에 정보를 인코딩하자.
Interface class | Concrete(Implementation) class | Do/Don't |
IShapeFactory | ShapeFactory | X - 해당 클래스가 인터페이스라는 정보 주기싫어서 |
ShapeFactory | ShapeFactoryImp | O |
ShapeFactory | CShapeFactory | O |
7. 자신의 기억력을 자랑하지 마라
- 코드를 읽는 사람이 머리속으로 한번 더 생각해 변환해야 할만한 변수명을 쓰지 말라. 예를 들면 URL에서 호스트와 프로토콜을 제외한 소문자 주소를 r이라는 변수로 명명하는 일 등
//URL이 아래와 같다면
https://www.example.com/path/to/page?query=123
//여기서 호스트(host)와 프로토콜(protocol)을 제외한 부분은 /path/to/page?query=123
String r = "/path/to/page?query=123";
//그런데 r이라는 변수명은 너무 짧아서 의미를 알기 어렵다.
- 똑똑한 프로그래머와 전문가 프로그래머를 나누는 기준 한가지는 "Clarity(명료함)"이다. 전문가는 남들이 이해하는 코드를 내놓는다.
8. 클래스 이름
- 명사 혹은 명사구를 사용하라.(Customer, WikiPage,Account,AddressParser)
- Manager, Processor, Data, Info 와 같은 단어는 피하자 - 너무 일반적이라 역할이 모호함
- 동사는 사용하지 않는다.
9. 메서드 이름
- 동사 혹은 동사구를 사용하라.(postPayment, deletePayment, deletePage, save 등)
- 접근자, 변경자, 조건자는 get, set, is로 시작하다. (추가: should, has 도 가능)
- 생성자를 오버로드할 경우 정적 팩토리 메서드를 사용하고 해당 생성자를 private로 선언한다.
- "정적(Static)" - static 키워드를 사용해서 객체를 생성
- "팩토리(Factory)" - 객체를 생성하는 역할
//Bad
Complex fulcrumPoint = new Comples(23.0);(x)
//Good
Complex fulcrumPoint = Complex.FromRealNumber(23.0)
//여기서 FromRealNumber 이게 정적팩토리메서드
public class Complex {
private double real;
private double imaginary;
// 🔹 생성자는 private으로 감춤
private Complex(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}
// 🔹 정적 팩토리 메서드 (실수만 받을 경우)
public static Complex FromRealNumber(double real) {
return new Complex(real, 0.0); // 허수 부분은 0으로 설정
}
// 🔹 정적 팩토리 메서드 (실수와 허수를 받을 경우)
public static Complex FromPolarCoordinates(double magnitude, double angle) {
return new Complex(magnitude * Math.cos(angle), magnitude * Math.sin(angle));
}
@Override
public String toString() {
return real + " + " + imaginary + "i";
}
}
10. 기발한 이름은 피하라
- 특정 문화에서만 사용되는 재미있는 이름보다 의도를 분명히 표현하는 이름을 사용하라
- HolyHandGrenade(x) 👉 DeleteItems(o)
- whak(x) 👉 kill(o)
11. 한 개념에 한 단어를 사용하라
- 추상적인 개념 하나에 단어 하나를 사용하자.
- fetch, retrieve, get 섞어 쓰지 말고 하나만, 예를 들면 get 하나만 사용
- controller, manager, driver 도 마찬가지
12. 말장난을 하지마라
- 한 단어를 두 가지 목적으로 사용하지 말자.
- 예를 들면 이전에 Add는 기존 값 두개를 더하거나 이어서 새로운 문장을 만들었는데 새로운 메서드에는 집합에 값 하나를 추가한다면, 맥락이 다르기때문에 동일한 이름으로 작성하기보다는 append 혹은 insert로 바꾸는게 옳다.
//Bad
public static String add(String message, String messageToAppend)
public List<Element> add(Element element) (x)
//Good
public static String add(String message, String messageToAppend)
public List<Element> append(Element element) (o)
13. 해법 영역(Solution Domain) 용어를 사용하자
- 코드를 읽을 사람은 프로그래머이다. 모든 용어를 도메인 영역(ex. 의료, 금융)에서 가지고 온다면 동료들은 매번 고객에게 의미를 물어봐야한다. 그러므로 기술 개념에는 기술 이름이 가장 적합하다.
14. 의미 있는 맥락을 추가하라
- 클래스, 함수, namespace 등으로 감싸서 맥락(Context)을 표현하라 - 변수가 좀 더 큰 구조에 속해있다는 사실이 명확해짐
- 그래도 불분명하다면 접두어를 사용하다.
//Bad
private void printGuessStatistics(char candiate, int count) {
String number;
String verb;
String pluralModifier;
if (count == 0){
number = "no";
verb = "are";
pluralModifier = "s"
} else if (count == 1){
number = "1";
verb = "is";
pluralModifier = ""
} else {
number = Integer.toString(count);
verb = "are";
pluralModifier = "s"
}
String guessMessage = String.format("There %s %s %s%s", verb, number, candidate, pluralModifier);
print(pluralModifier);
}
//Good
private class GuessStatistics() {
String number;
String verb;
String pluralModifier;
public String make(char candidate, int count){
createPluralDependentMassageParis(count);
return String.format("There %s %s %s%s", verb, number, candidate, pluralModifier);
}
private void createPluralDependentMassageParis(int count){
if (count == 0){
thereAreNoLetters();
} else if (count == 1){
thereIsOneNoLetters();
} else {
thereAreManyLetters();
}
}
private void thereAreNoLetters(){
number = "no";
verb = "are";
pluralModifier = "s"
}
private void (){
number = "1";
verb = "is";
pluralModifier = ""
}
private void (){
number = Integer.toString(count);
verb = "are";
pluralModifier = "s"
}
}
15. 불필요한 맥락을 없애라
- Gad Station Delux 이라는 어플리케이션을 작성한다고 해서 클래스 이름의 앞에 GSD를 붙이지는 말자. G를 입력하고 자동완성을 누를 경우 모든 클래스가 나타나는 등 효율적이지 못하다.
- 이는 모듈 재사용 관점에서도 좋지 못하다. 재사용하려면 이름을 바꿔야한다. 예를 들면, GSDAcocuntAddress 대신 Address라고만 해도 충분하다.
두려워하지 말고 서로의 명명을 지적하고 고치자. 그렇게 하면 이름을 외우는 것에 시간을 뺴앗기지 않고 "자연스럽게 읽히는 코드"를 짜는 데에 더 집중할 수 있다.
728x90