명명 충돌을 피하는 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_action과 another_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.