C projesi adlandırma çatışmalarından kaçınmak


13

Orta büyüklükte bir C kütüphane projesi için işlev adlandırma kuralları hakkında pragmatik gerçek dünya tavsiyesi bulmakta zorlanıyorum. Kütüphane projem, kendi başlıkları ile birkaç modüle ve alt modüle ayrılmıştır ve gevşek bir şekilde OO stilini izler (tüm işlevler, ilk argüman olarak belirli bir yapı alır, global yok vb.). Bizim gibi bir şey koydu:

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

Genellikle işlevler (örneğin) yapışmak için çok büyüktür some_foo_actionve another_foo_actionbir foo.cuygulama dosyasında, çoğu işlevi statik hale getirin ve bir gün olarak adlandırın.

Kullanıcılarımın istemci programlarıyla çakışmaları önlemek için kitaplığı oluştururken dahili ("modül özel") simgelerimi çıkarmayla başa çıkabilirim, ancak soru kitaplığımdaki sembollerin nasıl adlandırılacağıdır? Şimdiye kadar yapıyorum:

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

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

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

Ama ben son derece çılgın sembol isimleriyle bitiyorum (örneklerden çok daha uzun). İsimlere "sahte ad alanı" ön eki koymazsam, modüllerin dahili sembollerinin tümü çakışır.

Not: Camelcase / Pascal davası vb. Umurumda değil, sadece isimlerin kendileri.

Yanıtlar:


10

Ön ek (kuyu, ek) gerçekten tek seçenektir. Göreceğiniz bazı desenler <library>_<name>(örn. OpenGL, ObjC çalışma zamanı), <module/class>_<name>(örneğin Linux'un bazı bölümleri), <library>_<module/class>_<name>(örn. GTK +). Şemanız son derece makul.

Uzun isimler tahmin edilebilirlerse kötü olmak zorunda değildir. Tek bir kaynak dosyada ilgili işlevlere bağlı kalmayacak kadar büyük çılgın uzun isimler ve işlevlerle bitiyor olmanız farklı endişeleri ortaya çıkarır. Daha somut örnekleriniz var mı?


Nereden geldiğini görüyorum - Ayrı dosyalara bölme konusunda çok bilgili olup olmadığımı merak ettim, ancak okunabilirlik, bakım ve git mergeing. Bir örnek olarak OpenGL ile UI çekilmesi için bir modüle sahip, ve ayrı, .cI (gereken her bir eleman için dosya slider.c, indicator.cvs.). Bu eleman uygulamaları, belki de birkaç yüz satır uzunluğunda bir ana çizim fonksiyonuna ve staticiçinde çok sayıda yardımcıya sahiptir. Ayrıca UI modülünden birkaç saf geometri fonksiyonu çağırırlar. Bu kulağa oldukça tipik geliyor mu?
Dan Halliday

Uzun isimlerin daha iyi örnek benim ses modülü olabilir - Bir hiyerarşi gibi var Audio Module > Engines > Channels > Filtersolan gibi bir anlama gelir MyLibAudioEngines<EngineName>Channel<ActionName>. Veya filtrelerim alt modülünde: MyLibAudioFilters<FilterName><Type><Action>örn. MyLibAudioFiltersBigSoundingCompressorFloat32Process
Dan Halliday

Bunların hiçbiri mantıksız görünmüyor. Bir işlev için birkaç yüz satır biraz uzun görünüyor, ancak çizdiğiniz şey karmaşıksa, bundan kaçınmak zor olabilir. Şubesi ağır mı yoksa sadece bir sürü talimat mı?
user2313838

Re: ses modülü isimleri, ben bir filtre veya modül isme dayalı olup olmadığını söylemek kolay olacağını düşünüyorum olarak AudioFilters / AudioEngines kısaltmak olabilir. Float32 gibi veri tipi niteleyicileri de C programlamasında yaygın olduğu için kısaltılabilir (örneğin 'd', 'f').
user2313838

Yanıtlarınız için teşekkürler - bazen C program mimarisi hakkında (özellikle üst düzey dillerle karşılaştırıldığında) iyi bilgi almak neredeyse imkansızdır. Okuduğum birçok C kitabı, birden fazla modül veya birden fazla dosyaya sahip olma fikrini neredeyse hiç düşünmüyor! Genel olarak, bazı uzun isimler için kısaltmalar ile yaşamayı düşünüp düşünmemenin dışında çok fazla değişeceğimi sanmıyorum.
Dan Halliday

5

C kitaplıkları için genel kural, harici olarak kullanılabilir adlar için kitaplık adını önek olarak kullanmaktır;

struct MyLibFoo;
void MyLibAFooAction(...);

Kütüphanenin birden çok biriminde hala erişilebilir olması gereken kütüphane dahili adları için katı bir kural yoktur, ancak kütüphane adının bir önekini ve bunun dahili bir işlev olduğunu gösteren bir işaret kullanırım. Örneğin:

struct MyLibInternalFooBaz;
void MyLibInternalFooBazAction();

Bunun oldukça uzun ve yazılması zor isimlere yol açabileceğini kabul ediyorum, ancak maalesef C ++ ad alanları gibi bir mekanizmaya sahip olmadığımız için ödemek zorunda olduğumuz fiyat bu. İsimlerin uzunluğunu azaltmak için, bazı netliklerle, adlarınızda kısaltmaları kullanmayı tercih edebilirsiniz, ancak avantajları ve dezavantajları dikkatlice tartmanız gerekir.


3

Uzun öneklerden kaçınmak istiyorsanız, Apple'ın iOS ve OS X'te yaptığı gibi kütüphane adlarını kısaltabilirsiniz:

  • NSString, işletim sisteminin NextStep köklerinden gelen bir dizedir
  • CALayer bir Çekirdek Animasyon katmanıdır

2

Genel bir yapı değişkeninin fonksiyon işaretçileriyle doldurulmasına ne dersiniz?

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};

Kablo ağı:

#include "lib.h"

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

Statik anahtar kelime kapsamı çeviri birimiyle sınırlar, böylece başkalarıyla çarpışmaz.

Kullanıcı daha sonra benzer bir işaretçi YourApi *ya = &yourApikullanarak ve sonra kullanarak kısaltabilir ya->doFoo(...).

Ayrıca, kitaplığınızı test etmek için alay etmenin güzel bir yolunu sunar.


Serin desen, biraz kazan plakası gerektirir, ancak bu otomatik tamamlamayı çok daha kullanışlı hale getirecektir.
Rick Love
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.