명명 충돌을 피하는 C 프로젝트


13

중형 C 라이브러리 프로젝트의 함수 명명 규칙에 대한 실용적인 실제 조언을 찾기 위해 고심하고 있습니다. 내 라이브러리 프로젝트는 자체 헤더가있는 몇 개의 모듈과 하위 모듈로 구분되며 OO 스타일을 느슨하게 따릅니다 (모든 함수는 전역을 제외하고 특정 인수를 첫 번째 인수로 사용합니다). 그것은 우리에게 다음과 같은 것을 놓았습니다.

MyLib
  - Foo
    - foo.h
    - foo_internal.h
    - some_foo_action.c
    - another_foo_action.c
    - Baz
      - baz.h
      - some_baz_action.c
  - Bar
    - bar.h
    - bar_internal.h
    - some_bar_action.c

일반적으로 기능 (예를 들어) 스틱 너무 크다 some_foo_actionanother_foo_action하나 개 foo.c, 구현 파일 대부분의 기능 정적을하고, 하루에 전화.

클라이언트 프로그램과 사용자의 충돌을 피하기 위해 라이브러리를 빌드 할 때 내부 ( "모듈 개인") 심볼을 제거 할 수 있지만 문제는 라이브러리에서 심볼의 이름을 지정하는 방법입니다. 지금까지 나는하고있다 :

struct MyLibFoo;
void MyLibFooSomeAction(MyLibFoo *foo, ...);

struct MyLibBar;
void MyLibBarAnAction(MyLibBar *bar, ...);

// Submodule
struct MyLibFooBaz;
void MyLibFooBazAnotherAction(MyLibFooBaz *baz, ...);

그러나 나는 미친 긴 기호 이름으로 끝납니다 (예보다 훨씬 길다). 이름 앞에 "가짜 네임 스페이스"를 붙이지 않으면 모듈의 내부 심볼 이름이 모두 충돌합니다.

참고 : 낙타 케이스 / 파스칼 케이스 등은 신경 쓰지 않고 이름 자체 만 신경 쓰십시오.

답변:


10

접두사 (잘, 부착)는 실제로 유일한 옵션입니다. 표시되는 일부 패턴 <library>_<name>(예 : OpenGL, ObjC 런타임), <module/class>_<name>(예 : Linux의 일부) <library>_<module/class>_<name>(예 : GTK +)이 있습니다. 당신의 계획은 완벽하게 합리적입니다.

긴 이름이 예측 가능한 경우 반드시 나쁜 것은 아닙니다. 단일 소스 파일에서 관련 기능을 고수하기에 너무 긴 미친 이름과 기능 으로 끝나는 사실 은 다른 우려를 불러 일으 킵니다. 좀 더 구체적인 예가 있습니까?


어디에서 왔는지 알 수 있습니다. 별도의 파일로 분할하는 데 너무 관대 한 것인지 궁금했지만 가독성, 유지 관리 및 git mergeing에 많은 도움 이됩니다. 예를 들어 OpenGL로 UI를 그리기위한 모듈이 있으며 .c필요한 각 요소 ( slider.c, indicator.c등) 마다 별도의 파일이 있습니다. 이 요소 구현에는 주 그리기 기능이 수백 줄 정도 있으며 그 static안에는 많은 도우미가 있습니다. 또한 UI 모듈 내에서 몇 가지 순수한 지오메트리 함수를 호출합니다. 그게 꽤 전형적인가요?
Dan Halliday 2016 년

긴 이름의 좋은 예는 내 오디오 모듈이 될 수 있습니다 - 나는 계층 구조처럼 가지고 Audio Module > Engines > Channels > Filters있는 같은 것을 의미한다 MyLibAudioEngines<EngineName>Channel<ActionName>. 또는 내 필터 하위 모듈에서 : MyLibAudioFilters<FilterName><Type><Action>예. MyLibAudioFiltersBigSoundingCompressorFloat32Process
Dan Halliday 2016 년

그 중 어느 것도 비합리적으로 보이지 않습니다. 함수에 대한 수백 줄은 약간 긴 것처럼 보이지만 그림을 그리는 것이 복잡하면 피하기 어려울 수 있습니다. 분기가 무겁거나 많은 지시 사항입니까?
user2313838

Re : 오디오 모듈 이름, AudioFilters / AudioEngines를 축약 할 수 있습니다. 이름에 따라 필터 또는 모듈인지 쉽게 알 수 있다고 생각합니다. Float32와 같은 데이터 유형 한정자는 약어가 C 프로그래밍에서 일반적이므로 약어 (예 : 'd', 'f') 일 수도 있습니다.
user2313838

답변 주셔서 감사합니다. 때로는 C 프로그램 아키텍처에 대한 정보를 얻는 것이 거의 불가능하다고 느낍니다 (특히 고급 언어와 비교할 때). 내가 읽은 많은 C 서적은 여러 개의 모듈 또는 하나 이상의 파일을 갖는 아이디어를 간신히 고려합니다! 전반적으로, 나는 더 긴 이름의 약어로 살 것인지를 제외하고는 크게 변하지 않을 것이라고 생각합니다.
Dan Halliday 2016 년

5

C 라이브러리의 일반적인 규칙은 라이브러리 이름을 외부 적으로 사용 가능한 이름의 접두사로 사용하는 것입니다.

struct MyLibFoo;
void MyLibAFooAction(...);

라이브러리의 여러 단위에서 여전히 액세스 가능한 라이브러리 내부 이름의 경우 엄격한 규칙은 없지만 라이브러리 이름의 접두사와 내부 함수임을 나타내는 표시를 사용합니다. 예를 들면 다음과 같습니다.

struct MyLibInternalFooBaz;
void MyLibInternalFooBazAction();

나는 이것이 길고 입력하기 어려운 이름으로 이어질 수 있지만, 불행히도 C ++ 네임 스페이스와 같은 메커니즘이 없기 때문에 지불 해야하는 가격입니다. 이름의 길이를 줄이려면 명확성을 기하기 위해 이름에 약어를 사용하도록 선택할 수 있지만 장단점을 신중하게 고려해야합니다.


3

긴 접두사를 피하려면 iOS 및 OS X에서 Apple이하는 것과 같은 라이브러리 이름을 약어로 사용할 수 있습니다.

  • NSString은 OS의 NextStep 루트에있는 문자열입니다.
  • CALayer는 핵심 애니메이션 레이어입니다

2

함수 포인터로 전역 구조 변수를 미리 채우는 것은 어떻습니까?

lib.h

#pragma once

typedef struct
{
    void (*doFoo)(int x);
    const char *(*doBar)(void *p);
} YourApi;

extern const YourApi yourApi;

lib.c :

#include "lib.h"

#include <stdio.h>

static void doFoo(int x)
{
    printf("Doing foo %d\n", x);
}

static const char *doBar(void *p)
{
    printf("Doing bar: %p\n", p);
    return "Hello";
}

const YourApi yourApi = {
    doFoo,
    doBar};

마구:

#include "lib.h"

int main()
{
    yourApi.doFoo(42);
    yourApi.doBar("asd");
}

정적 키워드는 범위를 번역 단위로 제한하므로 다른 키워드와 충돌하지 않습니다.

사용자는 다음과 같은 포인터를 사용하여이 단축 될 수 있습니다 YourApi *ya = &yourApi다음, 사용 ya->doFoo(...).

또한 테스트를 위해 라이브러리를 조롱하는 좋은 방법을 제공합니다.


멋진 패턴, 약간의 상용구가 필요하지만 자동 완성 기능이 훨씬 유용합니다.
Rick Love
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.