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 mergeін. В якості прикладу у мене є модуль для малювання UI з OpenGL, і у мене є окремі .cфайли для кожного елемента , що мені потрібно ( slider.c, і indicator.cт.д.). У цих реалізаціях елементів є основна функція малювання, довжина якої може становити кілька сотень рядків, і значна кількість staticпомічників. Вони також називають кілька функцій чистої геометрії з модуля інтерфейсу користувача. Це звучить досить типово?
Ден Хеллідей

Кращим прикладом довгих імен може бути мій звуковий модуль - у мене є така ієрархія, Audio Module > Engines > Channels > Filtersяка означає щось подібне MyLibAudioEngines<EngineName>Channel<ActionName>. Або в підмодулі моїх фільтрів: MyLibAudioFilters<FilterName><Type><Action>напр. MyLibAudioFiltersBigSoundingCompressorFloat32Process
Ден Хеллідей

Нічого з цього не здається безпідставним. Кілька сотень рядків для функції здається трохи довгим, але якщо те, що ви малюєте, є складним, цього уникнути важко. Це гілка важка чи просто багато інструкцій?
user2313838

Що стосується: назви звукового модуля, ви можете скоротити AudioFilters / AudioEngines, як я думаю, було б легко сказати, чи це фільтр або модуль на основі імені. Класифікатори типу даних, такі як Float32, також можуть бути скорочені (наприклад, 'd', 'f'), оскільки такі абревіатури є поширеними в програмуванні на C.
user2313838

Дякуємо за ваші відповіді - іноді неможливо отримати гарну інформацію про архітектуру програми C (особливо порівняно з мовами вищого рівня). Багато читаних нами книг ледь вважають ідею мати декілька модулів або навіть більше одного файлу! В цілому, я не думаю, що я багато чого зміню, окрім розгляду того, чи жити з абревіатурами для деяких довших імен.
Ден Хеллідей

5

Звичайною умовою для бібліотек C є використання імені бібліотеки як префіксу для зовнішньо придатних імен, наприклад

struct MyLibFoo;
void MyLibAFooAction(...);

Для внутрішніх імен бібліотеки, які все ще мають бути доступними в декількох одиницях бібліотеки, немає суворої конвенції, але я б застосував префікс назви бібліотеки та вказівку, що це внутрішня функція. Наприклад:

struct MyLibInternalFooBaz;
void MyLibInternalFooBazAction();

Я погоджуюся, що це може призвести до імен, які досить довгі і важкі для введення, але, на жаль, це ціна, яку ми повинні платити за відсутність такого механізму, як C ++ простори імен. Щоб зменшити довжину імен, ціною якоїсь ясності ви можете скористатися абревіатурами у своїх іменах, але вам слід ретельно зважити переваги та недоліки.


3

Якщо ви хочете уникати довгих префіксів, ви можете скоротити імена бібліотеки, як, наприклад, Apple, що працює в iOS та OS X:

  • NSString - рядок з коренів NextStep ОС
  • CALayer - шар анімації Core

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.