item 51 : 메서드 시그니처를 신중히 설계하라
Last updated
Last updated
항상 표준 명명 규칙을 따라야 한다.
클래스와 인터페이스 (Class & Interface):
대문자로 시작하며 각 단어의 첫 글자를 대문자로 표기한다 (PascalCase).
클래스 이름은 보통 명사 또는 명사구로 표현한다.
예: Person
, DataManager
, HttpRequestHandler
.
메서드 (Method):
소문자로 시작하며 각 단어의 첫 글자는 대문자로 표기한다 (camelCase).
메서드 이름은 동사 또는 동사구로 작성하여, 메서드가 수행하는 동작을 명확히 설명해야 한다.
예: calculateTotal()
, fetchUserData()
, isUserLoggedIn()
.
변수 (Variable):
소문자로 시작하며 각 단어의 첫 글자는 대문자로 표기한다 (camelCase).
변수 이름은 가능한 구체적이고 명확하게, 변수의 목적을 설명하도록 작성한다.
예: userName
, accountBalance
, maxRetryCount
.
상수 (Constant):
모든 글자를 대문자로 표기하며 단어 간에 밑줄 (_
)을 사용한다 (SNAKE_CASE).
예: MAX_BUFFER_SIZE
, DEFAULT_TIMEOUT
.
패키지 (Package):
모두 소문자로 표기하며 회사 도메인을 뒤집은 형태로 시작한다.
예: com.example.app
, org.openai.utils
.
동사 또는 동사구로 명확히 표현:
예: save()
, load()
, calculateInterest()
.
이처럼 메서드 이름은 그 메서드가 무슨 작업을 하는지 명확하게 나타내야 함
부울 값을 반환하는 메서드는 is
로 시작:
예: isValid()
, isEmpty()
, isUserActive()
.
부울 값을 반환하는 메서드의 경우 is
를 접두사로 붙이는 것이 일반적
설명적인 이름으로 의미 명확히 하기:
예: getCustomerData()
, sendEmailNotification()
.
긴 이름을 피해야 하지만, 너무 짧고 애매한 이름도 피해야 합니다. 적절하게 설명적이면서 이해할 수 있는 이름을 사용하는 것이 중요
자바 라이브러리의 명명 규칙과 일관성 유지:
예: 자바의 컬렉션 메서드들은 add()
, remove()
, clear()
, contains()
와 같은 이름을 사용한다.
이처럼 널리 사용되는 메서드 이름을 참조함으로써 일관성을 유지하고 다른 개발자들이 쉽게 이해할 수 있게 된다.
좋은 예시:
나쁜 예시:
명확하고 일관성 있게 메서드 이름을 짓는 것이 중요하다. 이해할 수 있고, 같은 패키지에 속한 다른 이름들과 일관되게 짓는 게 최우선 목표다.
메서드 이름은 무엇을 하는지 쉽게 이해할 수 있도록 지어야 하며, 동사 형태로 시작하여 동작을 설명해야 합니다.
긴 이름은 피하자.
자바 표준 명명 규칙을 따르고, 필요시 자바 API 가이드를 참조하여 개발자 커뮤니티에서 널리 받아들여지는 방식으로 이름을 짓는 것이 좋다.
편의 메서드를 너무 많이 만들지 말자.
각 메서드는 자신의 역할에만 충실해야 한다: 많은 기능을 하나의 메서드에 넣으면 복잡해지고 이해하기 어려워지므로, 명확한 단일 책임 원칙을 지켜야 한다.
메서드가 너무 많은 클래스와 인터페이스는 피해야 한다: 유지보수와 사용이 어렵기 때문에 필요한 최소한의 기능을 메서드로 정의해야 한다.
직교란 수학에서 온 용어로, 서로 직각(90。)을 이루며 교차 한다는 뜻이다. 수학의 관점에서 직교하는 요소들은 서로 독립적이다.
직교성(Orthogonality): 기능 간 독립성을 높여 메서드 수를 줄이는 효과를 기대할 수 있다. 기능을 잘게 나누어 필요한 기본 기능들만 제공하면, 그 기능들을 조합하여 더 복잡한 동작을 구현할 수 있다. 예시로 List
의 subList()
와 indexOf()
메서드를 들 수 있다.
“직교성이 높다”라고 하면 “공통점이 없는 기능들이 잘 분리되어 있다” 혹은 “기능을 원자적으로 쪼개 제공한다” 정도로 해석할 수 있다. 예를 들어 본문의 List 설명에서 ‘부분리스트 얻기’와 ‘주어진 원소의 인덱스 구하기’는 서로 관련이 없다. 따라서 두 기능을 개별 메서드로 제공해야 직교성이 높다고 할 수 있다.
매개변수는 4개 이하로 유지하는 것이 좋다. 매개변수가 많아지면 기억하기 어렵고 사용자가 혼동할 수 있다.
같은 타입의 매개변수가 여러 개 연달아 나오는 경우는 특히 피해야 한다. 매개변수의 순서를 잘못 입력할 가능성이 있기 때문이다.
메서드 나누기: 메서드를 여러 개로 쪼개 각각이 원래 매개변수 목록의 부분집합을 처리하도록 한다. 이렇게 하면 메서드 수는 늘어날 수 있지만 기능 간의 독립성을 높여 유지보수를 쉽게 한다. java.util. List 인터페이스가 좋은 예다.
도우미 클래스 활용: 매개변수 여러 개를 묶어주는 도우미 클래스를 만들기. 일반적으로 이런 도우미 클래스는 정적 멤버 클래스
로 둔다. 특히 잇따른 매개변수 몇 개를 독립된 하나의 개념으로 볼 수 있을 때 추천하는 기법이다. 예를 들어 카드의 숫자와 무늬를 묶어 하나의 매개변수로 만들면 API와 클래스 구현이 깔끔해진다.
빌더 패턴 응용: 메서드 호출에서도 빌더 패턴을 응용하여 많은 매개변수를 처리한다. 먼저 모든 매개변수를 하나로 추상화한 객체를 정의하고, 클라이언트에서 이 객체의 세터(setter) 메서드를 호출해 필요한 값을 설정하게 하는 것이다.
이때 각 세터 메서드는 매개변수 하나 혹은 서로 연관된 몇 개만 설정하게 한다.
클라이언트는 먼저 필요한 매개변수를 다 설정한 다음, execute 메서드를 호출해 앞서 설정한 매 개변수들의 유효성을 검사한다. 마지막으로, 설정이 완료된 객체를 넘겨 원하 는 계산을 수행한다.
클래스 대신 인터페이스 사용: 매개변수 타입으로 인터페이스를 사용하는 것이 클래스보다 유연하다. 예를 들어 Map
인터페이스를 사용하면 여러 구현체(HashMap
, TreeMap
등)를 사용할 수 있다.
boolean 대신 열거 타입 사용: 가능하면 boolean 대신 2개 이상의 값을 가지는 열거형(enum)을 사용합니다. 열거형은 코드의 의미를 명확히 전달할 수 있고, 선택지를 쉽게 확장할 수 있다.
편의성을 위한 고수준 기능 제공은 신중히: 자주 사용되는 조합이나 성능 최적화를 위한 고수준 기능을 별도로 제공할 수 있지만, 필요 이상의 고수준 기능 추가는 API를 복잡하게 만들 수 있다.
직교성(Orthogonality)을 고려한 설계는 테스트와 유지보수를 용이하게 한다. 기능 간에 서로 독립적이도록 잘 나누는 것이 핵심이다.