C에서 변수 및 함수에 사용되는 명명 규칙 [닫기]


13

CI에서 큰 프로젝트를 코딩하는 동안 문제가 발생했습니다. 더 많은 코드를 계속 작성하면 코드를 구성하기가 어려울 때가 있습니다. 프로그램의 다른 부분에 대한 함수와 변수의 이름이 섞여있는 것처럼 보일 수 있습니다.

그래서 C 변수와 함수에 사용할 수있는 유용한 명명 규칙이 있는지 생각하고 있습니까?

대부분의 언어는 명명 규칙을 제안합니다. 그러나 C의 경우 지금까지 읽은 유일한 것은 코드 가독성을 설명하기 위해 이름을 설명해야한다는 것입니다.

편집하다:

제안 된 명명 규칙의 몇 가지 예 :

Java 어딘가에 대한 명명 규칙을 더 읽었지만 어디에 있는지 기억하지 못했습니다.


제안 된 명명 규칙을 사용하여 몇 가지 언어 예제를 인용하십시오. 그리고 우리는 이러한 명명 규칙을 찾을 수 있습니다.
Philip

@Philip 추가 예
아심 반살

1
전역을 사용하지 않으므로 변수에 문제가 없어야합니다. 그리고 함수 이름을 : 모듈의 이름 인 경우 order.c, 당신은 함수의 이름을 수 order_add(), order_del()등. 이름이 처음 8 자 내에서 고유해야한다는 오래된 시스템이있을 수 있습니다. 나중에 실수로 C ++로 전환하면 작성하는 사랑합니다 order::add()order::del()다음.
ott-- 2018 년

답변:


17

더 많은 코드를 계속 작성하면 코드를 구성하기가 어려울 때가 있습니다.

이것이 당신의 문제입니다. 조직을 올바르게 설정하고 스타일이 더 쉽게 흐를 것입니다.

코드 정리를 기다리지 말고 코드를 정리하십시오. 비록 언어가 당신을 위해 그것을하지 않지만, 코드는 여전히 낮은 결합과 높은 응집력을 가진 모듈로 구성되어야합니다.

그런 다음 이러한 모듈은 자연스럽게 네임 스페이스를 제공합니다. 충돌을 피하기 위해 모듈 이름 (길이가 긴 경우)을 약칭하고 함수 이름 앞에 해당 모듈을 붙입니다.

개별 식별자의 수준에서 이들은 주관적인 순서로 대략 증가합니다.

  1. 컨벤션을 고수
    • 예를 들어, function_like_this(struct TypeLikeThis variable)일반적입니다
  2. 헝가리어 표기법을 피하십시오 (죄송합니다 JNL)

    • 원래 의도대로 사용하지 않으려는 경우, 이는 끔찍한 시스템 버전이 아닌 Simonyi의 표기법 을 의미 합니다

      왜? 이에 대한 에세이를 쓸 수는 있지만 대신 Joel Spolsky가 작성한 이 기사 를 읽은 다음 관심이있는 경우 좀 더 찾아보십시오. 아래쪽에 Simonyi의 원본 용지에 대한 링크가 있습니다.

  3. 포인터 유형 정의가 실제로 불투명 한 쿠키 유형이 아닌 한 포인터 유형 정의를 피하십시오.

    struct Type *ok;
    typedef struct Type *TypePtr;
    TypePtr yuck;
    

    불투명 한 쿠키 유형 은 무엇을 의미 합니까? 클라이언트 모듈에 전달 해야하는 모듈 (또는 라이브러리 또는 기타) 내부에서 사용되는 것을 의미하지만 해당 클라이언트 코드는 직접 사용할 수 없습니다 . 라이브러리로 다시 전달합니다.

    예를 들어, 데이터베이스 라이브러리는 다음과 같은 인터페이스를 노출 할 수 있습니다.

    /* Lots of buffering, IPC and metadata magic held in here.
       No, you don't get to look inside. */
    struct DBContextT;
    /* In fact, you only ever get a pointer, so let's give it a nice name */
    typedef struct DBContexT *DBContext;
    
    DBContext db_allocate_context(/*maybe some optional flags?*/);
    void db_release_context(DBContext);
    int db_connect(DBContext, const char *connect);
    int db_disconnect(DBContext);
    int db_execute(DBContext, const char *sql);
    

    이제 내부를 볼 수 없기 때문에 컨텍스트가 클라이언트 코드에 불투명 합니다. 라이브러리로 다시 전달하면됩니다. 같은 FILE것도 불투명하고 정수 파일 설명자는 쿠키 이지만 불투명하지 않습니다.


디자인에 대한 메모

나는 설명없이 낮은 결합과 높은 응집력 이라는 문구를 사용했으며 그것에 대해 약간 나쁘게 느낍니다. 당신은 그것을 검색하고 좋은 결과를 찾을 수 있지만, 나는 그것을 간단히 설명하려고 노력할 것입니다.

위에서 스케치 한 DB 라이브러리 는 외부 인터페이스에 작은 인터페이스를 제공하기 때문에 낮은 커플 링을 보여줍니다 . 구현 세부 정보 (불투명 쿠키 트릭 포함)를 숨기면 클라이언트 코드가 해당 세부 정보에 의존하지 않게됩니다.

불투명 쿠키 대신 컨텍스트 구조를 선언하여 내용이 표시되고 데이터베이스에 대한 TCP 연결을위한 소켓 파일 설명자가 포함되어 있다고 가정합니다. DB가 동일한 머신에서 실행될 때 공유 메모리 세그먼트 사용을 지원하도록 구현을 변경하는 경우, 클라이언트는 단지 재 링크가 아니라 재 컴파일되어야합니다. 더 나쁜 것은 클라이언트가 파일 설명자를 사용 하기 시작했을 수 있습니다 ( 예 : setsockopt기본 버퍼 크기를 변경하기 위한 호출). 이제 코드도 변경해야합니다. 이러한 모든 세부 사항은 가능한 경우 모듈 내부에 숨겨져 있어야하며, 이는 모듈 간의 낮은 결합 을 제공 합니다.

또한 모듈의 모든 메소드가 동일한 작업 (DB 액세스)과 관련되어 있다는 점에서 높은 응집력 을 보여줍니다 . 것을 코드 만이 수단 필요가 디버깅을 단순화 구현 세부 사항에 대해 알 수있는 (즉, 우리의 쿠키의 내용) 실제로에 액세스 할 수 있습니다.

또한 단일 관심사가 있으면 이러한 기능을 그룹화 할 접두사를 쉽게 선택할 수 있습니다.

이제이 예제가 좋다고 말하는 것은 쉽지만 (특히 완전하지 않기 때문에) 즉시 도움이되지는 않습니다. 비결은 코드를 작성하고 확장 할 때 유사한 작업을 수행하거나 동일한 유형 (자체 모듈의 후보 일 수 있음)에서 작동하는 기능과 '별도의 별도 작업을 수행하는 기능'을 감시하는 것입니다. t 정말 관련이 있고, 분할 후보가 될 수 있습니다.


헝가리어를 피하는 이유를 이해할 수 있습니까? 그것에 대해 더 알고 싶어합니다. :)
JNL 2016 년

@JNL : 설명이 너무 짧아서 제대로 설명 할 수 없습니다. 새 질문으로 게시하는 것이 좋습니다.
Bart van Ingen Schenau 2016 년

with low coupling and high cohesion. 그게 무슨 뜻이야? 불투명 쿠키 유형에 대해 설명하십시오. 나는 그것이 무엇을 의미하는지 전혀 모른다.
Aseem Bansal 2018 년

나는 간단하게 해결하려고 노력했고 간결하게 실패했다. 잘만되면 그것은 당신을 시작해야한다.
쓸모없는

며칠 후에 답장을 드리겠습니다. 그 죄송합니다. 에 대한 귀하의 설명을 읽었습니다 low coupling and high cohesion. 따라서 기본적으로 내가 할 수있을 때 물건을 캡슐화한다는 것을 의미하며 실제로 필요한 기능에 액세스 해야하는 방식으로 수행해야합니다. 일부는 내 머리 위로 갔지만 여전히 나는 당신의 요점을 생각합니다.
Aseem Bansal

5

내 생각에 네 가지 문제를 명심하면 네이밍 문제의 90 %가 해결됩니다 .a ) 변수 및 함수 이름을 가능한 한 설명 적 이어야합니다 .b) 코드 전체에서 일관성이 있습니다 (즉, 함수의 이름이 addNumbers이면 두 번째 함수의 이름은 numbersMul이 아니라 multiplyNumbers로 지정해야합니다. c) 가능하면 이름을 짧게 입력해야합니다.

이 주제에 대한 다른 측면을 살펴보고 싶다면 명명 규칙 의 Wikipedia 페이지에 명심해야 할 것들이 많이 있습니다. 또한 C 및 C ++에 대한 분류가 있습니다.

C 및 C ++에서 키워드 및 표준 라이브러리 식별자는 대부분 소문자입니다. C 표준 라이브러리에서 축약 된 이름이 가장 일반적입니다 (예 : 문자가 영숫자인지 여부를 테스트하는 함수의 경우 등호). C ++ 표준 라이브러리는 종종 밑줄을 단어 구분 기호 (예 : out_of_range)로 사용합니다. 매크로를 나타내는 식별자는 일반적으로 대문자와 밑줄 만 사용하여 작성됩니다 (상수에 대소 문자를 모두 사용하는 많은 프로그래밍 언어의 규칙과 관련이 있습니다). 이중 밑줄을 포함하거나 밑줄과 대문자로 시작하는 이름은 구현 용으로 예약되어 있으며 (컴파일러, 표준 라이브러리) 사용해서는 안됩니다 (예 : reserved__ 또는 _Reserved). [5] [6] 이것은 피상적으로 스트로 핑과 유사하지만 의미가 다릅니다.


3
"가능한 경우 이름을 짧게 만드십시오"자동 완성 기능이있는 IDE를 사용하면 함수 이름은 한 번만 입력하기 만하면되는만큼 길고 설명적일 수 있습니다.
Joel

1
@Joel 끔찍한 조언. 모든 사람이 당신과 같은 IDE를 사용하는 것은 아닙니다.
제임스

6
@ 제임스 그들은 필요하지 않고 괜찮은 IDE를 사용할 수 있습니다. 그러면 생산성을 위해 선명도를 희생 할 필요가 없습니다.
Joel

IDE라는 용어는 이제 며칠이 조금 얇아졌습니다. 기술적으로 메모장 ++는 프로젝트를 컴파일하고 실행하도록 구성 할 수 있기 때문에 IDE이지만 주로 텍스트 편집기입니다. 그리고 자동 완성됩니다.
Philip

5

C의 유일한 어려운 제약은 네임 스페이스가 없다는 것입니다. 따라서 만들 수있는 방법을 찾아야 rename()당신의 기능 파일 시스템 로부터 라이브러리가 별개 rename()당신의 기능을 미디어 라이브러리를. 일반적인 해결책은 다음 filesystem_rename()과 같은 접두사 media_rename()입니다.

다른 일반적인 조언은 프로젝트 나 팀 내에서 일관성을 유지하는 것입니다. 가독성이 향상됩니다.


+1 : 라이브러리에서 내 보낸 심볼의 경우 특히 그렇습니다. "죄송하지만 파일 시스템 라이브러리는 그 미디어 라이브러리와 함께 사용되지 않습니다. 둘 다 내 보낸 함수 이름이 변경 되었기 때문입니다.
Residuum

2

전 세계적으로 수용 가능한 형식을 찾고 있다면

MISRA / JSF / AUTOSAR는 C / C ++ 코드 이름 지정 및 구성을위한 모든 업계 표준의 거의 100 %를 지원합니다. 문제는 그들이 무료로 구할 수 없다는 것입니다. 즉, 각각의 가이드 북은 약간의 비용이 듭니다. MISRA 2008 C / C ++ 코딩 표준 책의 가격은 아마도 약 50 USD라는 것을 알고 있습니다.

이를 저널 작성시 참고 문헌 및 추가 읽기에 대한 하버드 참조라고 생각할 수 있습니다. MISRA를 사용했으며 함수와 변수의 이름을 지정하고 올바르게 사용하도록 구성하는 좋은 방법입니다.

당신이 뭔가 일시적인 것을 찾고 있다면

파이썬과 자바에 제공 한 참조는 괜찮습니다. 사람들이 javadoc 스타일의 주석, 이름 지정 및 코드 구성을 채택하는 것을 보았습니다. 사실, 마지막 프로젝트에서 Java와 비슷한 함수 / 변수 이름으로 C ++ 코드를 작성해야했습니다. 이 뒤에 두 가지 이유 :

1) 따라 가기가 더 쉬웠다.

2) 생산 코드 요구 사항은 안전에 중요한 소프트웨어 시스템 표준에 맞지 않았습니다.

3) 레거시 코드는 (어쨌든) 그 형식으로되어 있습니다.

4) Doxygen은 Javadoc sytle 주석을 허용했습니다. 그 당시 우리는 doxygen을 사용하여 프로덕션 직원을위한 문서를 생성했습니다.

많은 프로그래머들이 이것에 반대 할 것이지만, 개인적으로 C / C ++에서 javadoc 스타일 함수 / 변수 명명을 채택하는 데 아무런 문제가 없다는 것입니다. 과정 예, 흐름 제어, 스레드 안전 등을 구성하는 관행은 관계없이 해결되어야합니다. 그러나 나는 여기서 신청자가 아닙니다. 또한 프로덕션 코드 형식 요구 사항이 얼마나 엄격한 지 모르겠습니다. 주제를 벗어난 영역으로 전환하지 않고 요구 사항을 검토하고 특정 명명 규칙에 얼마나 의존하는지 확인하고 내 답변 및 다른 답변에서 언급 한 솔루션을 사용하는 것이 좋습니다.

이것이 도움이 되었기를 바랍니다!?


실제로 나는 이것을 개인 C 코드를 요구했다. 그러나 나는 당신의 제안을 기억할 것입니다.
Aseem Bansal

@AseemBansal 개인적이거나 전문적인 사람들은 배우고 이력서를 착용하는 것이 좋습니다 :) .... 당신까지.
hagubear

0

명명하는 동안 고려해야 할 중요한 사항은 거의 없습니다.

  1. actionObject 또는 ObjectAction 유형을 확인하십시오. (Object는 C가 아닙니다. 그러나 일반적으로 다른 객체 지향 언어로 갈 때) 도움이됩니다.

  2. 휴식은 일관성 있고 짧고 설명 적입니다.

  3. 또한 모든 변수와 함수를 정의하는 유일한 목적을 갖습니다. 예 : 값을 임시로 저장하는 경우 int의 경우 nTempVal로 이름을 지정하십시오.
  4. 변수는 명사이고 메소드는 동사 여야합니다.

6
헝가리어 표기법 (유형을 나타내는 문자로 변수 앞에 접두사)을 붙이면 통증이 없습니다. 고맙게도 대부분 패션에서 벗어났습니다.
로봇 고트

@StevenBurnap 왜 헝가리어 형식을 피해야하는지 궁금했습니다. 나는 그것이 그들이 학교에서 우리에게 가르쳐 준 것이라고 믿고 있으며 일부 직장에서도 그러한 코드를 보았습니다. 헝가리어가 아닌 경우 어떤 것을 추천 하시겠습니까? 감사합니다
JNL

1
최상의 명명 규칙은 일관되게 사용되는 것으로, 명확하고 설명적인 이름은 과도한 약어없이 중복되는 접두사를 피하지 않으면 서 비교적 짧게 유지하는 것이 이상적입니다. 헝가리어 표기법은 실제 유용성이 거의 없으며 코드를 읽기 어렵게 만들고 유형을 변경하기 어렵게합니다.
로봇 고트

2
다음은 원래 의도와 헝가리 표기법이 된 가증 한 내용에 대한 설명입니다. joelonsoftware.com/articles/Wrong.html
Residuum

@Residuum 좋은 링크였습니다. 많은 도움이되었습니다. 감사합니다.
JNL

0

대부분의 대답은 좋지만 C ++ 또는 Java와 같은 다른 언어에서 네임 스페이스를 사용하는 것과 비슷한 라이브러리 및 포함 파일의 명명 규칙에 대해 이야기하고 싶습니다.

라이브러리를 빌드하는 경우 내 보낸 심볼의 공통 접두사 (예 : 전역 함수, typedef 및 변수)를 찾으십시오. 이렇게하면 다른 라이브러리와의 충돌을 막고 함수가 사용자의 라이브러리에서 오는 것으로 식별됩니다. 이것은 헝가리어 표기법의 약간의 응용 프로그램입니다.

더 나아가서 내 보낸 심볼을 그룹화 할 수도 있습니다. libcurl은 전역 심볼에 curl_ *, 다른 인터페이스에 curl_easy_ *, curl_multi_ * 및 curl_share_ *를 사용합니다. 따라서 모든 함수에 curl_ *를 사용하는 것 외에도 다른 인터페이스에 대해 다른 수준의 "네임 스페이스"를 추가했습니다. curl_multi_ * 핸들에서 curl_easy_ * 함수를 호출하면 잘못된 것으로 보입니다 . http : // curl 의 함수 이름을 참조하십시오 . haxx.se/libcurl/c/

내 보낸 심볼에 대한 규칙을 유지하려면 #includeed 파일 에서 정적 함수에 대한 규칙을 사용해야 합니다. 이러한 함수의 공통 접두사를 찾으십시오. "my_string"이라는 파일에 정적 문자열 유틸리티 함수가 있습니까? 모든 함수 앞에 my_string_ *를 붙입니다.


내 보낸 기호는 올바른 경우 전역 변수, 함수, typedef 등을 의미합니다. 내 보낸 심볼을 그룹화하는 방법에 대해 설명해 주시겠습니까? 이전 단락에서 이미 설명했다고 생각했습니다. 세 번째 단락에서 무엇을 추가 했습니까?
Aseem Bansal 2018 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.