2011-02-01

Notacja węgierska użyta wygodnie

Charles Simonyi stworzył dawno temu (w skali czasu istnienia C/C++) pewne standardy odnośnie nazewnictwa zmiennych i funkcji - zwane notacją węgierską. Tak, tą samą notacją, na którą narzekają tysiące programistów, mających do czynienia z WinAPI czy innymi wynalazkami Microsoftu. Co ciekawe - akurat w WinAPI wspomniana notacja jest używana niepoprawnie. Istnieje możliwość takiego wykorzystania przedrostków, żeby nie przyprawiały o ból głowy - również na innych platformach.

Po co w ogóle notacja węgierska? Porównajmy następujące zapisy:
int width
int pcWidth
int a_pcWidth
Z pierwszego wynika, że zmienna przechowuje szerokość. Z drugiego - że zmienna przechowuje szerokość wyrażoną w jednostkach "pc" (tu: procenty). Z trzeciego - że zmienna jest argumentem, przechowującym szerokość wyrażoną w jednostkach "pc". Ilość znaków różni się niewiele - różnica przekazu jest znaczna. Podobnie z nazwami funkcji:
int to_pixels(int width);
int pc_to_pixels(int width);
int pc_to_px(int pcWidth);
int px_from_pc(int pcWidth)
Co ciekawe, wyłącznie ostatni zapis jest w pełni zgodny z oryginalną NW. Podstawowa zasada dla nazw funkcji i metod: jeśli format czy jednostka wartości zwracanej nie wynika jasno z typu, należy podać ją jako pierwszą część nazwy funkcji. Co ciekawe, w formie suffiksowej ta zasada występuje często na różnych platformach (np. suffix C w nazwie funkcji/metody w Symbianie informuje, że zwrócony obiekt umieszczony jest na CleanupStacku i musi być z niego usunięty przez wołającego, suffiksy A oraz W w WinAPI rozróżniają wersje funkcji używające łańcuchów 16-bit i 8-bit), gdzie nie budzi żadnych obiekcji.

Moja propozycja jest taka, aby wszędzie, gdzie tylko to konieczne, notacja węgierska była używana. Prefiksy są różne, jednolity standard w zasadzie nie istnieje. Każdy programista używający NW prędzej czy później zbuduje sobie własną listę używanych prefiksów. Jeśli komuś się nie chce/nie ma pomysłu, poniżej moja (wstępna) lista.
  • px - piksele
  • pc - procenty
  • pt - partial, przy liczbach zmiennoprzecinkowych oznacza zakres [0; 1]
  • cb - ilość bajtów
  • cch - ilość znaków
  • cv - ilość wartości, odpowiednik ilości znaków przy tablicach innych niż znakowe (rozmiar tablicy)
  • w/ws - world space
  • c/cs - camera space
  • s/ss - screen space
  • o/os - object space
  • t/ts - tangent space
  • an - angle
  • n - numer (również: stały indeks)
  • ix - indeks (np. w tablicy, wektorze)
  • h - uchwyt
  • p - wskaźnik, za który kod obsługujący tą zmienną jest odpowiedzialny (musi przekazać lub zwolnić wskazywaną pamięć)
  • lp - "daleki wskaźnik", wskaźnik, za który nie bierzemy odpowiedzialności
  • fn - funktor, wskaźnik do funkcji, wszystko, co da się wywołać
  • m_/m/i - member, internal - pole niestatyczne klasy (z założenia i jest dostępne wyłącznie dla implementacji metod, jego wartość nie jest w żaden pośredni ani bezpośredni sposób dostępna z zewnątrz, służy np. do przechowywania tymczasowego stanu pomiędzy wywołaniami asynchronicznymi)
  • a - argument funkcji
  • ao_/aout_/out - argument wyjściowy, nie jest w funkcji odczytywany, wyłącznie zapisywany
  • ar_/aref_/ref - argument-referencja, może być odczytany i zapisany
  • t - thread-insecure, oznaczenie zmiennej, która może być przyczyną problemów w synchronizacji międzywątkowej
  • tm/-M - thread-mutex, oznacza albo zmienną-muteks, albo fakt, że funkcja korzysta z muteksu do synchronizacji/upewnienia się o jednolitości danych
  • x/-X - cross-thread, zmienna używana w wielu wątkach lub funkcja odwołująca się do pracujących wątków (zwykle oznacza zmienną volatile)
  • v - variable, częste oznaczenie pól mutable, zmiennych bardzo często zmieniających wartość, zmiennych oznaczonych volatile celem uniknięcia ewentualnych problemów
  • -C - create, wartość zwracana jest nową wartością, wywołujący ma obowiązek ją zwolnić lub przekazać dalej do zwolnienia, używane w nazwach funkcji/metod
  • -D - destroy, przekazana wartość (albo this) jest niszczony, używane tylko przy funkcjach/metodach
  • k - stała
Oczywiście lista nie jest kompletna (ba, daleko jej do bycia kompletną), niemniej jednak pokrywa zdecydowaną większość nie-zawsze-jasnych sytuacji w moim kodzie. Inspirowane oryginalną notacją węgierską, WinAPI, API Symbiana oraz kilkoma innymi sposobami zapisu. Dodam jeszcze, że ogólna zasada budowania nazwy z wykorzystaniem powyższych modyfikatorów to: [zakres i odpowiedzialność za ewentualne zniszczenie]-[modyfikatory stanu: wątki, const, mutable]-[typ/jednostka wartości]-nazwa-[sufiksy]. I, co ważniejsze - używać tylko tych modyfikatorów, które są sensowne (nie ma np. sensu zapis tmMutex - samo mutex jest wystarczająco jasne ;-) ).

Brak komentarzy:

Prześlij komentarz