Abseil Tip 186 함수는 무명 네임스페이스에 두는 것을 선호하세요

원문 게시: 2020년 11월 5일, 주간 팁 #186

작성자: James Dennett, Jason Rennie

최종 수정: 2020-11-05

빠른 링크: abseil.io/tips/186

“모든 것은 가능한 한 단순해야 하지만, 지나치게 단순해서는 안 된다.” - 아인슈타인의 생각을 해석한 로저 세션스

새로운 함수를 추가할 때 기본적으로 해당 함수가 호출되는 .cc 파일에 로컬인 비멤버 함수로 만드는 것이 좋습니다. 다른 선택이 필요할 수 있는 합리적인 이유가 있지만, 무명 네임스페이스(익명 네임스페이스라고도 함)에 작성하는 것을 고려하세요.

장점

무명 네임스페이스에 비멤버 함수를 작성하면 함수가 .cc 파일에 내부적으로 위치하도록 하고(헤더 파일에서 제거), 클래스 외부로 이동시키는 이점을 제공합니다.

헤더 파일에 선언된 함수에 비해 다음과 같은 장점이 있습니다:

  • 함수의 정의를 쉽게 찾을 수 있습니다(사용 위치와 동일한 파일에 정의되어 있으며 첫 번째 사용 위치 위에 존재).
  • 문서화, 선언, 정의를 한 곳에 둘 수 있습니다(헤더 파일에 선언된 함수는 두 위치로 분리됨).
  • 다른 소스 파일로부터 격리되어 리팩터링이 용이합니다.
  • 의미 있는 const를 걱정할 필요가 없습니다(별도의 선언이 없으므로).
  • 편의용 별칭 및 로컬 타입과 같은 라이브러리의 다른 구현 보조 요소들과 함께 동일한 위치에 둘 수 있습니다. 참고: 주간 팁 #119: using 선언 및 네임스페이스 별칭.
  • 관련된 타입도 무명 네임스페이스로 이동 가능(단일 소스 파일에서만 참조된다면)이라는 부수적 이점이 있습니다.

비공개 메서드에 비해 다음과 같은 장점이 있습니다:

  • 입력과 출력이 명확합니다. 입력과 출력은 주로 함수의 매개변수와 반환값을 통해 명시됩니다. 반면 메서드는 모든 멤버 변수를 읽거나 비-const 메서드인 경우 비-const 멤버를 수정할 수 있습니다. 비멤버 함수는 인터페이스에 따라 읽거나 수정할 수 있습니다(전역 변수를 제외하고).
  • 클래스 API가 더 간단하고 짧아집니다. 불필요한 비공개 메서드는 상속 관련 비공개 선언이나 클래스 이후의 선언을 찾기 어렵게 만들 수 있습니다.

이러한 대부분의 장점은 헤더 파일이 없는 경우에도 유효합니다(예: *_test.cc 또는 *_main.cc 파일).

무명 네임스페이스를 사용하지 않는 경우

때로는 비멤버 로컬 함수가 적절하지 않을 수 있습니다. 예를 들어:

  • 함수가 여러 소스 파일에서 유용한 경우. 이를 헤더 파일에 선언하면 재사용이 가능합니다.
  • 함수가 객체나 클래스와 복잡한 상호작용이 있는 경우. 예를 들어, 여러 필드를 읽고 반환값만으로 처리할 수 없는 방식으로 상태를 수정해야 하는 함수는 메서드로 작성하는 것이 더 적합할 수 있습니다. 특히, 뮤텍스와 관련된 로직은 주로 멤버 함수에서 처리하는 것이 적합합니다.
  • 함수가 클래스의 API의 일부로 포함되어야 할 경우.

대안: static 비멤버 함수

비멤버 함수를 static으로 표시하면 다른 번역 단위의 코드에서 격리된다는 점에서 무명 네임스페이스에 넣는 것과 본질적으로 동일한 효과를 얻을 수 있습니다. 무명 네임스페이스는 타입, 함수, 객체에 대해 일관된 방식으로 이를 수행하지만, 일부 사람들은 함수 선언에 static을 명시적으로 작성하여 함수가 번역 단위에 로컬임을 표시하는 것을 선호합니다(무명 네임스페이스가 있는지 확인할 필요 없이). 이 팁은 무명 네임스페이스 사용을 권장하지만, static을 사용하는 것도 합리적인 선택이 될 수 있습니다.

참고 자료

Google 스타일 가이드에서 이 방향성을 어느 정도 제시하고 있지만, 완전하게 다루지는 않습니다. 예를 들어:

  • 무명 네임스페이스 섹션에서는 정의를 무명 네임스페이스에 두거나 static으로 선언할 것을 권장하지만, 비공개 메서드에 대해서는 다루지 않습니다.
  • 입력과 출력 섹션에서는 반환값 사용을 권장하지만, 멤버 수정(this를 통해)에 대해서는 다루지 않습니다. this는 일종의 모든 입력/출력 매개변수입니다.
  • 로컬 변수 섹션에서는 변수 범위를 최소화하도록 권장하지만, 이를 클래스 및 객체로 확장하지는 않습니다.
  • 비멤버, 정적 멤버, 전역 함수 섹션에서는 단순히 함수들을 그룹화하기 위해 클래스를 사용하는 것을 권장하지 않습니다.

요약

파일 로컬 함수는 의존성을 단순화하고 코드의 지역성을 높여줍니다. 비멤버 함수는 캡슐화를 강화하고 클래스 정의를 단순화하며 의존성을 더 명확히 만듭니다. 함수를 작성할 때, .cc 파일의 무명 네임스페이스에 파일 로컬 비멤버 함수로 만드는 것을 고려하세요. ```