Autor Wątek: Nazewnictwo klas, zmiennych, funkcji itd.  (Przeczytany 6364 razy)

Offline Walian

  • Użytkownik

# Lipiec 06, 2012, 22:09:53
Wątek zakładam, ponieważ jestem ciekaw jakie stosujecie u siebie nazewnictwo wszelkich bytów istniejących w kodzie. Wiadomo, że wielu programistów stosuje różne podejścia. Są też takie ogólnie przyjęte stosowane przez większość. Jednak, gdy przeglądam kody źródłowe różnych aplikacji (nie tylko C++) to zauważam, że jest duża rozbieżność.

Może podam przykłady, a Wy napiszcie, które możliwości wybieracie:
1.) W klasie tworzycie prywatny wskaźnik na obiekt, niech to będzie obiekt klasy D3D:
- m_D3D: czyli prefix "m_" oznaczający "member".
- m_pD3D: bardziej sprecyzowany prefix, oznaczający że jest to wskaźnik.
- D3D: bez prefiksów itp. Pełne uproszczenie.
- pD3D (Ja stosuję ten wariant)
- inne nazewnictwo - jakie?

2.) Tworzycie zmienną globalną, niech to również będzie wskaźnik na obiekt klasy D3D:
- g_D3D: czyli prefix "g_" oznaczający "global".
- g_pD3D: analogicznie jak w pkt. 1.
- pD3D (Ja stosuję ten wariant, pamiętając, który wskaźnik należy do klasy, a który jest globalny)
- D3D: analogicznie jak w pkt. 1.
- inne nazewnictwo - jakie?

3.) Tworzycie nazwę klasy, np. weźmy klasę D3D:
- class D3D
- class CD3D (Ja stosuję ten wariant)
- class D3DClass
- inne nazewnictwo - jakie?

4.) Nadajecie nazwę pliku, który zawiera definicję klasy lub kod jej metod, np. weźmy klasę D3D:
- D3D.h / D3D.cpp
- CD3D.h / CD3D.cpp (Ja stosuję ten wariant)
- D3DClass.h / D3DClass.cpp
- inne nazewnictwo - jakie?

5.) Nazewnictwo zwykłych zmiennych (wskażcie wariant lub podajcie swój):
- float fValue
- float value
- DWORD dwValue
- DWORD value
- JakasStruktura js;
- JakasStruktura jakasStruktura;
Tutaj zazwyczaj staram się nadawać zmiennej możliwie najkrótszą nazwę, ale tak, by jednocześnie dawała mi ona do zrozumienia za co odpowiada zmienna, dzięki czemu nie muszę stosować prefiksów. Czasami może zajść potrzeba zmiany typu zmiennej na inną - głupio wtedy wszędzie w kodzie zmieniać bądź usuwać prefiks.

Pytam, bo interesuje mnie jakie argumenty przemawiają za Waszymi wyborami. Ja wiele razy zmieniałem swoje podejście, czasami stosuję wyjątki w nazewnictwie.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline hck

  • Użytkownik

# Lipiec 06, 2012, 22:23:04
1) pełne uproszczenie, nazwa powinna być jak najkrótsza i po nazwie powinno rozpoznać się czym ten obiekt jest, dla D3DDevice: device, dla DeviceContext: ctx.

2) nie stosuję zmiennych globalnych

3) Osobiście nie toleruję przedrostków "C" w nazwach klas, nerwicy dostaję jak coś takiego widzę... Stosuję nazwy takie jak: MySuperExtraFrameworkGraphics, MySuperExtraFrameworkInput itd.

4) Pliki zawsze mają taką samą nazwę jak klasa, która się w nich znajduje.

5)  - float value
     - DWORD value
     -JakasStruktura js

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Lipiec 06, 2012, 22:23:48
1) void *whatever, *second_whataver;
2) raczej unikam
3) class MojaKlasa
4) whatever.h / whatever_name_id.h
5) float zmienna, druga_zmienna;

Czyli podsumowując, stosuję trzy konwencje:
- MojaNazwaCzegośTam - klasy, czasem niektóre globale (duże obiekty), większość funkcji/metod
- moja_nazwa_zmiennej - zmienne lokalne, globalne, pola obiektów, funkcje ststyczne
- SAMEDUŻELITERY - makra, enumy, tablice "const"

Ale wszystko to kwestia indywidualna dopóki szef nie powie inaczej.

Offline koirat

  • Użytkownik

# Lipiec 06, 2012, 22:42:34
Wszystko tu napisane będzie subiektywnie.

1. jeszcze może być takie "d3D" zmienne w notacji wielbłądziej.
2. Nie tworzymy zmiennych globalnych (innych niż stałe). Jak już naprawdę musimy (bo szef kazał czy coś) to robimy Singelton i tam pakujemy zmienne.
3. Klasy tworzymy PascalCase  KlasaONazwieTakiej
4. Plik o nazwie klasy, bez bajerów

5.
float value;
unsigned int value; <-- na codzień
DWORD value; <-- jak rzeźbimy w WinApi
JakasStruktura jakasStruktura;
JakasStruktura js; <-- rzadko i tylko dla zmiennych lokalnych wewnątrz funkcji jeśli będą używane do max 2-3 linijek poniżej.
Nazwa ma być krótka ale treściwa. W pierwszej kolejności treść a później długość, Zdarzają mi się czteroWyrazówki.  przykładowoTakDługaNazwa jeszcze przejdzie, w końcu mam intellisense.

Offline siso

  • Użytkownik

# Lipiec 06, 2012, 22:57:04
Nazwy powinny dobrze opisywać dany element. Nie powinny być ani za długie ani za krótkie. Są wszelako od tego wyjątki. Przykładowo "i" będzie znakomitą nazwą dla indeksu pętli, ale nie ma prawa (no, prawie ;) ) być memberem w klasie.

Unikaj wszelkich upiększaczy jak "m_", "g_", __cokolwiek", bo zmniejszają czytelność i zdradzają, że nie jesteś na bieżąco ;)

Offline Walian

  • Użytkownik

# Lipiec 06, 2012, 23:14:55
Spokojnie Panowie, nie należę do grupy osób stosujących zmienne globalne. Unikam ich za wszelką cenę. Zastosuję jedynie, gdy robię na szybko testową aplikację, która ma wypluć jakiś komunikat lub dane do pliku i nie chce mi się tworzyć specjalnie do tego celu klasę ;-)

Cytat: hck
3) Osobiście nie toleruję przedrostków "C" w nazwach klas, nerwicy dostaję jak coś takiego widzę... Stosuję nazwy takie jak: MySuperExtraFrameworkGraphics, MySuperExtraFrameworkInput itd.
No właśnie m.in dlatego pytam. Nie chcę pisać kodu, który będzie drażnił innych. Mnie bardziej drażni dostawianie "Class" na końcu nazwy każdej klasy. Natomiast przedrostek "C" stosuję, by wyraźnie zaznaczyć, że w pliku znajduje się klasa + ew. jej typy danych, a nie jakieś tam gołe globalne API czy cuś.

Cytat: koirat
unsigned int value; <-- na codzień
Ja zazwyczaj używam aliasów: UINT, ULONG...

Cytat: siso
Unikaj wszelkich upiększaczy jak "m_", "g_", __cokolwiek", bo zmniejszają czytelność i zdradzają, że nie jesteś na bieżąco ;)
Ja ich nigdy nie stosowałem, bo osobiście mnie wnerwiają. Wg mnie niepotrzebnie wydłużają kod, zmniejszając czytelność i sprawiają wrażenie, że koder ma problemy z zapamiętywaniem, która zmienna jest lokalna, a która lokalna. Natomiast widzę, że nagminnie jest to stosowane, w dodatku nie wiem skąd się to wzięło, ale obstawiam, że z jakiejś książki (Symfonia?). W każdym razie mnie się to wydaje niepraktyczne i widzę, że Wam też.

Cytat: Krzysiek K.
- SAMEDUŻELITERY - makra, enumy, tablice "const"
To akurat oczywiste dlatego o tym nie wspomniałem.

Offline lukasyno

  • Użytkownik

# Lipiec 06, 2012, 23:19:36
1. wskaznik czy zmienna, pisze tak samo (ale malo w c/c++ klepie) czyli napisal bym d3D.
2. ...
3.class D3D.
4. ...
5. float value, DWORD value
a to JakasStruktura jakasStruktura; jest dosc ciekawe zagadanienie majac np Klase
DisplayObject
raczej bym nie pisal displayObject tylko szukal bym zastosowania tej klasy np hero/rock/scrollbar czy czym kolwiek to mialo by byc ;) Oczywiscie raczej w projektach to klasa hero dziedziczyla by po DisplayObject i to juz analogicznie by uproscilo sprawe z nazwa ;) Hero hero;

Offline Kos

  • Użytkownik
    • kos.gd

  • +1
# Lipiec 06, 2012, 23:24:23
Notacja węgierska jest bardzo spoko, jeśli się jej używa rozważnie. Rozważnie as in "wpisuj w nazwie zmiennej nie to, co jest oczywiste, tylko to, co jest przydatne" (a i to tylko wtedy, gdy jest taka potrzeba dla czytelności). Czyli nie typ danych, nie prywatność, ale np. kontekst - jeśli kontekstów może być wiele. Przykład: w shaderach lubię wektorom przykleić etykietkę w jakiej przestrzeni są.

Tu więcej na ten temat:

Joel Spolsky - Making Wrong Code Look Wrong

Offline ajuc

  • Użytkownik
    • strona domowa

# Lipiec 06, 2012, 23:36:51
1. someField - camel case z małej litery. I raczej bym dał d3d, niż d3D, bo traktuję 3d jako jedno słowo, i ładniej tak wygląda imho. Duże litery obok siebie walą po oczach i sugerują, że coś jest stałą.

2. nie używam. Mam strukturę, która zawiera referencję do wszystkiego (game ma w środku terrain, objects, relations, ui, itp,  które mają referencję do wszystkiego). Jak chcę móc robić efekty uboczne z jakiejś funkcji, to przekazuję jej tą strukturę. Przynajmniej wiadomo, że ta funkcja może zmienić cokolwiek.

3. SomeClass dla klas. ISomethingable dla interfejsów (znaczy się klas abstrakcyjnych).

4. nazwy plików bez dużych liter someclass.h someclass.cpp, bo wielkośc liter nie ma znaczenia na windowsie a ma na linuksie, i naciąłem się na to kiedyś (ktoś developował na windowsie, miał inną wielkość liter w inkludzie niż w nazwie pliku, jemu działało, a na linuksie nie kompilowało się. Albo ktoś zakomitował plik z inną wielkością liter niż oryginalna  - na windowsie to był ten sam plik, na linuksie to były 2 pliki, i potem się dziwy działy :). Najprościej zawsze używać małych liter w nazwach plików tylko.

5.
float value;
DWORD value;
JakasStruktura js; // mały scope
JakasStruktura rolaZmiennej; // większy scope, parametry funkcji, itp
// raczej nie robię zmiennych o nazwach jak typ,
// bo bez sensu sie powtarzac, że Entity jest entity.
// A rola obiektu czasem jest istotna. Przykład:

bool lineOfFireOccluded(Entity* shooter, Entity* target); // fajnie

bool lineOfFireOccluded(Entity* e1, Entity* e2); // mniej fajnie, ale przynajmniej krotko

bool lineOfFireOccluded(Entity* entity, Entity* entity2); // ani krótko, ani fajnie, ale z rozpędu się tak czasem napisze


Poza tym z ciekawostek (z jakiegoś artykułu to wziąłem, nie pamiętam skąd, ale przydatne) - jeśli funkcja konwertuje jedenRodzaj danych na innyRodzaj, to nazywam ją innyRodzajFromJedenRodzaj zamiast jedenRodzajToInnyRodzaj. Przykład:

string encodedPassword = encodedFromPlain(plainPassword); // fajnie
string encodedPassword = plainToEncoded(plainPassword); // mniej fajnie

EDIT: o właśnie z tego artykułu Spolskyego to wziąłem :)
« Ostatnia zmiana: Lipiec 06, 2012, 23:41:34 wysłana przez ajuc »

Offline yarpen

  • Użytkownik

  • +1
# Lipiec 06, 2012, 23:49:41
Nie ma to zadnego znaczenia, pisz jak ci najszybciej/najwygodniej. Uzywalem w zyciu z 10 roznych konwencji, zadnej nie uwazam za gorsza/lepsza niz inne, byle bylo w miare spojnie.

Offline Walian

  • Użytkownik

# Lipiec 07, 2012, 00:52:00
Cytat: Kos
Tu więcej na ten temat:

Joel Spolsky - Making Wrong Code Look Wrong
Poczytam w któryś dzień jak znajdę na to czas.

Cytat: ajuc
4. nazwy plików bez dużych liter someclass.h someclass.cpp, bo wielkośc liter nie ma znaczenia na windowsie a ma na linuksie [...]
Masz rację, ale ja mimo wszystko wolę używać tutaj notacji CamelCase, bo wg. mnie polepsza to czytelność. A jeśli dodatkowo będę pilnował nazw plików to na Linuksie nic się nie rozwali. Skoro miałeś takie problemy to widocznie spotkał Cię pech, że trafiłeś na osoby, które tego nie dopilnowały ;-)

Cytat: ajuc
string encodedPassword = encodedFromPlain(plainPassword); // fajnie
string encodedPassword = plainToEncoded(plainPassword); // mniej fajnie
No faktycznie wariant pierwszy jest czytelniejszy. Mam np. funkcje IntToStr(). Ale nigdy nie myślałem, by ją zamienić na StringFromInt(). Może i czytelniejsze, ale... sam nie wiem. Mimo wszystko wydłużyłoby to nazwę funkcji. Ale przy innych, mniej "standardowych" konwersjach ten pomysł mógłby się sprawdzić.

Cytat: yarpen
Nie ma to zadnego znaczenia, pisz jak ci najszybciej/najwygodniej. Uzywalem w zyciu z 10 roznych konwencji, zadnej nie uwazam za gorsza/lepsza niz inne, byle bylo w miare spojnie.
No tak, ale czasami warto zapytać o zdanie innych niż pisać wszystko po swojemu. Bo to, że mnie pasuje nie musi być równoznaczne, z tym, że tak jest poprawnie logicznie i czytelnie. A jeśli kiedyś będę chciał opublikować mój kod np. tu na forum to chciałbym by nie przyprawiał analizujących o irytację. Też wiele razy zmieniałem sposób pisania. Zaczynałem od jakas_nazwa_funkcji(). Teraz żadnej funkcji tak bym nie nazwał.

A co robicie, gdy do instrukcji warunkowej przynależy tylko jedna linia kodu:
if (smth)
    DoSomthingeElse();
Stosujecie nawiasy klamrowe czy raczej ich unikacie? Wg mnie niepotrzebnie wydłużają kod i zmniejszają czytelność. Czasami można też odnieść wrażenie iż programista nie zdaje sobie sprawy, że w tym przypadku są zbędne.

Offline _OskaR

  • Użytkownik

# Lipiec 07, 2012, 01:25:19
Ja ich nigdy nie stosowałem, bo osobiście mnie wnerwiają. Wg mnie niepotrzebnie wydłużają kod, zmniejszając czytelność i sprawiają wrażenie, że koder ma problemy z zapamiętywaniem, która zmienna jest lokalna, a która lokalna. Natomiast widzę, że nagminnie jest to stosowane, w dodatku nie wiem skąd się to wzięło, ale obstawiam, że z jakiejś książki (Symfonia?). W każdym razie mnie się to wydaje niepraktyczne i widzę, że Wam też.
Mi to nie przeszkadza :-P Przynajmniej od razu widać, co jest memberem klasy, a co jest lokalne w funkcji.
Wg mnie niepotrzebnie wydłużają kod i zmniejszają czytelność. Czasami można też odnieść wrażenie iż programista nie zdaje sobie sprawy, że w tym przypadku są zbędne.
Może wydłużają kod, ale zmniejszają ryzyko popełnienia błędu.

Offline radsun

  • Użytkownik
    • CaRpg

# Lipiec 07, 2012, 01:25:56
Co do ostatniego pytania to nie stosuje nawiasów chyba że jest tam kilka linijek.
Kod: (cpp) [Zaznacz]
if(costam)
   for(...)
       costam2();
Kod: (cpp) [Zaznacz]
if(costam)
{
   for(...)
      costam2();
}
Ta pierwsza opcja mi za bardzo pythona przypomina i zawsze to więcej loc :)

Offline Xion

  • Moderator
    • xion.log

# Lipiec 07, 2012, 01:37:38
Cytuj
string encodedPassword = encodedFromPlain(plainPassword); // fajnie
string encodedPassword = plainToEncoded(plainPassword); // mniej fajnie
string encodedPassword = passwords.encode(plainPassword); // najfaniejsze"Namespaces are honking great idea - let's do more of those!"

Cytuj
Czasami można też odnieść wrażenie iż programista nie zdaje sobie sprawy, że w tym przypadku są zbędne.
Czy o whitespace'ach powiesz to samo i zaczniesz zapisywać cały kod w jednej linijce?... No właśnie :) A żeby nie było że podaję przykłady z powietrza, spójrz na tę oto dyskusję na temat opcjonalnych średników w JS: https://github.com/twitter/bootstrap/issues/3057 . Tak, 200+ odpowiedzi z powodu takiej bzdury, i jednym z głównych 'argumentów' jest właśnie "nie będe używał X bo wiem że to zbędne!". W praktyce to nic innego jak Argument z Przerośniętego Ego; nie używaj go, proszę :)

Cytuj
Ta pierwsza opcja mi za bardzo pythona przypomina (...)
To ma być wada? ;)

Offline Asmodeusz

  • Użytkownik
    • Bogumił Wiatrowski: Blog

# Lipiec 07, 2012, 03:58:49
1. W przypadku prostych klas/struktur (mało metod, pola publiczne) żadnych przedrostków, w złożonych przypadkach (kradzione z Symbiana) przedrostki i/s/c/m. i - inside value (pole-zmienna), s - statyczne, c - stałe, m - mutable. Dodatkowo, nazwy staram się układać tak, żeby różniły się na jak najwcześniejszym znaku (Intellisense).

2. Namespace i żadnych dodatkowych oznaczeń. Np. Globals::MemoryLimit, GFX::dev (D3D device), GFX::ctx (D3D context).

3. StandardowaFormaNazwy, dla interfejsów IUnavoidable, klasy-rozszerzenia zawsze mają nazwę w postaci KlasaBazowaRodzajRozszerzenia - np. RendererDX11Implementation.

4. Od nazwy głównej klasy w pliku, w przypadku braku głównej klasy od zastosowania (np. Hashing.h - z interfejsem do generowania MD5, SHA1 itd., w formie binarnej, base64 i hex).

5. Kilka reguł, których się trzymam:
* Wszelkie zmienne z ilością/wielkością mają nazwę nKontener (ilość elementów zmiennej kontener).
* Indeks w pętli - i, j, k; iteracja po współrzędnych - x, y, z; tymczasowo indeks poza pętlą (np. pozycja obiektu do usunięcia) idx.
* kKontener - kontener zaalokowany na stosie (_alloca).
* self - odpowiednik "this" w wywołaniach wolnych funkcji (extension methods w C#, obiekt podstawowy w Python C API).

Nie unikam długich nazw - istotniejsze jest, żeby nie mieć dziesiątek zmiennych o zaczynających się identycznie nazwach.

6. Podział na linie i opcjonalne nawiasy. Trzymam się zasady zapisywania wyrażenia bez nawiasów klamrowych w jednej linii. Przykładowo stosuję takie dwa zapisy:
if(condition) return value;if(condition)
{
    return value;
}

Podepnę się do pytania, zawsze mnie ciekawiło: jaka jest kolejność metod w plikach źródłowych? Przypadkowa, ustalona z góry, sortujecie ręcznie? Mi wystarcza (jak na razie) chaos + outline, choć mam delikatne wrażenie, że kiedyś będę przeklinał przypadkowy układ.
« Ostatnia zmiana: Lipiec 07, 2012, 04:04:11 wysłana przez Asmodeusz »