Dobre standardy programowania - nazewnictwo zmiennych

0

Witam,
chciałem się zapytać Was, bardziej doświadczonych programistów, czy macie jakieś swoje ulubione standardy nazywania zmiennych/obiektów w waszych programach? Chodzi mi o to, że właśnie stworzyłem klasę o nazwie nazwa_klasy i zastanawiam się jak nazwać obiekt takiej klasy O_o... Najbardziej by mi pasowała taka nazwa jak nazwa klasy, ale tak nie można :/. No i właśnie zastanawiam się nad wyrobieniem sobie jakiegoś standardu ;)

Często bywa również tak, że mam metodę w której przypisuję obiektom klasy wartości i wówczas również jest problem jak nazwać takie parametry... Chodzi mi o taki przykład

void metoda_przypisania_zmiennych(int A, double B)
{
this->A = A;
this->B = B;
}

bez this byłoby czytelniej, ale powstaje wówczas pytanie jak nazwać zmienne w parametrach funkcji, by je jakoś odróżnić...
pozdrawiam

0

Poczytaj: http://pl.wikipedia.org/wiki/Notacja_węgierska

A klasy ja nazywam np. CGame, a obiekt to małą literą np. game

0

Osobiście wszelkie parametry funkcji poprzedzam znakiem "_". W Twoim wypadku mogło by to wyglądać tak:

void metoda_przypisania_zmiennych(int _A, double _B)
{
this->A = _A;
this->B = _B;
}
0

Po pierwsze nazwa metody lub zmiennej ma odwzorowywać to co w niej naprawdę się znajduje. Za pół roku zobaczysz fragment:

void metoda_przypisania_zmiennych(int A, double B){} 

i co pomyślisz? Zaczniesz czytać kod żeby zrozumieć o co chodzi, a to jest problem.
Gdybyś np. napisał:

void ustalPozycje(int x, double y){} 

problemu by nie było.

Z takich lepszych standardów.
-Klasy zaczynasz dużą literą i potem camelCase.
-Metody i zmienne zaczynasz małą literą i potem camelCase.

Zmienne jednoliterowe lub z nazwą bez znaczenia generalnie odpadają z kilkoma wyjątkami (np. "i" przy iteracji).
Rozbijaj kod na jak najwięcej małych funkcji.

0
mcoder napisał(a):

Poczytaj: http://pl.wikipedia.org/wiki/Notacja_węgierska

O notacji węgierskiej czytałem, ale ona jest bez sensu - tam jest kilkadziesiąt typów... To jest nie do zapamiętania i wszystko się miesza i nie wygląda to zbyt estetycznie...

mcoder napisał(a):

A klasy ja nazywam np. CGame, a obiekt to małą literą np. game

Ja rozważałem pisać nazwy klas z dużych liter np. NAZWA_KLASY, ale doszedłem do wniosku, że to również nie wygląda zbyt estetycznie a do tego makra również są pisane dużymi literami i nie chcę by się to przeplatało...
W nazwach stosuję podkreślnik, ale również zamierzam z niego zrezygnować na rzecz: NazwaKlasy
Wówczas obiekty mógłbym nazywać np. tak NazwaKlasy nazwaklasy lub NazwaKlasy nazwa_klasy
Niestety ciągle się waHam...

AlfaLeporis napisał(a):

Osobiście wszelkie parametry funkcji poprzedzam znakiem "_". W Twoim wypadku mogło by to wyglądać tak:

void metoda_przypisania_zmiennych(int _A, double _B)
{
this->A = _A;
this->B = _B;
}

Ja kiedyś dawałem f_ co informowało, że jest to zmienna funkcji, ale również trochę się do tego zniechęciłem...

2

W C++ jest o tyle trudniej niż w innych językach, że pisze w nim bardzo dużo osób, które są już ugruntowane w dziedzinie programowania. Z racji braku oficjalnych zaleceń organizacji, która sprawuje nad nim pieczę (komitet standaryzacyjny) stosują standardy, które poznali gdzie indziej. Dlaczego, w przeciwieństwie do Javy, C# czy Pythona ciężko powiedzieć o tych jedynych i właściwych.

Najpierw zdefiniujmy kilka stylów: camelCase, _camelCase, PascalCase, underscore_case.

Takie są moje preferencje:
Nazwy klas: PascalCase.
Nazwy metod: PascalCase.
Parametry: camelCase.
Pola: _camelCase. Czasem nie poleca się rozwiązań z podkreśleniami z przodu z tego względu, że są to nazwy zarezerwowane dla wewnętrznej implementacji czy kompilatora. Nie ma z tym jednak większych problemów. Możesz też użyć camelCase_.
Zmienne: camelCase.

Inni jako nazwy funkcji i metod stosują camelCase, a jeszcze inni underscore_case (też bardzo czytelne, także dla parametrów i zmiennych).
Kiedyś bardzo popularna (w C++ i swojego czasu w PHP) była notacja węgierska, czyli z przedrostkiem oznaczającym typ albo zasięg zmiennej (np. m_cośtam czy lpszCośtam). Nadal można ją często zauważyć w kodach C++ Microsoftu (i nadal w nagłówkach WinAPI). Obecnie raczej wszyscy są zgodni, że to złe rozwiązanie.

Najważniejsze jest jednak to, by trzymać się jednego stylu w jednym projekcie. Nie ma nic gorszego niż brak konsekwencji.

0

Ale kombinujesz MichałWx... Po co chcesz cos wymyslac jakies swoje zasady?

1

Ja trzymam się takich standardów:

  • Nazwy klas w ProperCase.
  • Nazwy metod, funkcji, zmiennych i parametrów w camelCase.
  • Prywatne pola w klasie camelCase z sufiksem _; tu dodam, że pola publiczne są naprawdę rzadkością – jeśli są, to camelCase.
  • Akcesory pól prywatnych (jeśli są potrzebne) tak jak nazwa pola bez sufiksu (np. pole T foo_, getter T foo() const, setter T& foo()).
  • Stałe najczęściej UPPER_CASE.
  • Parametr template'owy oznaczający typ w UpperCase z prefiksem T (np. TOut); jeśli jest tylko jeden parametr, to po prostu T.
  • Parametr remplate'owy oznaczający wartość w UpperCase.

Mały przykład:

const int CONST_VALUE = 123;

class MyClass {
public:
    MyClass(int bar) : bar_(bar) {
        double myVar = 3.14;
    }
    
    bool foo(int baz) const {
        return baz == bar_;
    }
    
    int bar() const {
        return bar_;
    }
    
    int& bar() {
        return bar_;
    }

private:
    int bar_;
};

int main() {
    MyClass myClass(7);
}
0

Opisywac moze nie bede, ale mniej-wiecej cos w tym stylu:

#define BUFFER_SIZE 256

const int CONST_VALUE = 123;
 
class MyClass
{
public:
    MyClass(int bar):
        bar(bar)
    {
        ;
    }
 
    int getBar() const
    {
        return this->bar;
    }
 
    void setBar(const int bar)
    {
        this->bar = bar;
    }
    
    bool porownanieBarow(const int) const;
 
private:
    int bar;
};

template<class T>
bool porownaj(const T& a, const T& b)
{
    return a == b;    
}

template<class Input, class Output>
void copy(const Input& first, const Input& last, Output& result)
{
    // ...
}

bool MyClass::porownanieBarow(const int bar) const
{
    return this->bar == bar;
}

 
int main()
{
    MyClass my_class(10);
    return 0;
}

Edit: Dodam jeszcze wywolanie duuuzych funkcji, raczej w formie ciekawostki ;>

std::copy(
	istream_iterator<char>(cin),
	istream_iterator<char>(),
	ostream_iterator<char>(cout)
);
0

Ja stosuję notację:

  • klasy/przestrzenie nazw PascalCase z zachowaniem wielkości znaków w skrótach, czyli np. HTMLParser a nie HtmlParser
  • metody small_caps_snake_case
  • stałe BIG_CAPS_SNAKE_CASE
  • zmienne i parametry small_caps_snake_case
  • stanowcze nie notacji węgierskiej
  • składowe prywatne z przedrostkiem m_
0
winerfresh napisał(a):

Ja stosuję notację:

  • klasy/przestrzenie nazw PascalCase z zachowaniem wielkości znaków w skrótach, czyli np. HTMLParser a nie HtmlParser
  • metody small_caps_snake_case
  • stałe BIG_CAPS_SNAKE_CASE
  • zmienne i parametry small_caps_snake_case
  • stanowcze nie notacji węgierskiej
  • składowe prywatne z przedrostkiem _m_

Ta opcja mi najbardziej pasuje! Więc i ja ją przyjmę w swoich projektach jako standard ;-)
Nie wiem tylko czy dawać ten przedrostek m... Jakoś brzydko to wygląda :P a chwilowo nie odczuwam potrzeby odróżniania zmiennych prywatnych od publicznych - większość i tak jest prywatna.
Dzięki wszystkim za dyskusję!
pozdrawiam

0

Jeszcze zauważyłem, że wśród niektórych programistów (?), szczególnie tych początkujących (i nie tylko...), istnieje notacja n00bcase... :D

class CSklep
{
    int produkty_count;

    int getprodukty()
    {
    }

    void PokazILOSC()
    {
    }
}

Jak taki koder sam sobie pisze kod to pal go sześć, ale jak się taki w pracy trafi to o jejku...

--

A tak poważniej pisząc, to co z nazewnictwem kontrolek w GUI? Czy tu używacie notacji węgierskiej? Np. dla buttona btnExit czy może inne np. ExitButton? Co o tym sądzicie, nazewnictwo kontrolek w GUI (lub komponentów).

1

void metoda_przypisania_zmiennych(int _A, double _B)
{
this->A = _A;
this->B = _B;
}
Ważniejsze od konkretnego wyboru jest, by stosować go konsekwentnie w ramach jednego projektu.

np.

_b = b;
this->b = ab; // przedrostek a jak argument
m_b = b; // m jak member

itd.
wszystko jedno co wybierzemy, byleby nie było co funkcję inaczej.

1

Zacznijmy może od tego że we własnych projektach mamy więcej możliwości jeżeli chodzi o dobór standardu opisującego nazwy. W pracy już tak kolorowo często nie ma - jeden z góry określony standard, którego się trzymasz (co ma swoje logiczne uzasadnienie).
Ja opiszę tylko i wyłącznie swoje podejście do nazewnictwa, które sam sobie wyrobiłem wraz ze zdobywaniem doświadczenia - ustosunkowane jest to własnym stylem programowania jak i subiektywnym ocenieniem co w praktyce jest bardziej korzystne. Poza tym duży wpływ na mój styl miała książka "Kod doskonały. Jak tworzyć oprogramowanie pozbawione błędów". Wydaje mi się że i tak zdecydowanie bardziej istotnym czynnikiem jest stosowanie właściwie dobranych nazw dla danych typów, funkcji, zmiennych itp. Jeżeli wcześniejsza kwestia nie jest spełniona to żadna konwencja nie zda egzaminu, chociażby nie wiadomo jakby nie była dobrze przemyślana:

int x, y, pf, k, kk, anty_nie_wiadomo_co; 
std::string bardzo_lubie_swoja_klawiature_wiec_sobie_pisze_dlugie_nazwy_zmiennych = "a co mi tam!";
float tuBedzieCosFajnego = 0.0;

Być może jest to przerysowane, jednakże nie jeden kwiatek tego typu zdarzył się na 4p.

Nazwy klas - FooClass.
W żadnym wypadku żadne przedrostki "C" np. CFooClass - gdy pierwszy raz spotkałem się z takim stylem zarysowało się moim umyśle tylko jedno wielkie CWtf!
FOO_CLASS to już w ogóle jakieś totalne nieporozumienie.
Nie przepadam również za przedrostkami "I" np. IFooClass, chociaż już ma większy sens zastosowania aniżeli przykład z przedrostkiem C.
Jeżeli klasa jest implementacją jakiegoś wzorca projektowego to wówczas używam takiej składni: FooClass_Factory, FooClass_State itp.

Instancje klas: lowerCamelCase, bez żadnych notacji węgierskiej, która imho to zwykły przerost formy nad treścią - bardziej przeszkadza niż w rzeczywistości pomaga. Warta uwagi jest konwencja nazewnictwa zmiennych dla kontrolek gui, np. buttonExit. Początkowo sam mieszałem w dwóch stylach: buttonExit oraz exitButton. Zdecydowałem się jednak na pierwsze rozwiązanie z bardzo prostej przyczyny - auto-uzupełnianie nazw w środowisku/edytorze. Po wpisaniu "button" i np. ctrl+enter (czy też ctrl+spacja) i boom - mam już wszystkie przyciski. Tym sposobem nie muszę przeszukiwać w myślach za co dana kontrolka jest odpowiedzialna - to mi podpowie samo środowisko - wiem tylko że chodzi mi o knefel i tyle ;]

Funkcje składowe lowerCamelCase:
void fooFunction();
Nazwy dla argumentów funkcji to już bardziej złożona sprawa. Kiedyś stosowałem przedrostek _ lub pf i fa, lecz uznałem iż jest to zupełnie niepotrzebne. Jeżeli mówimy o konstruktorach to wszystkie nazwy zapisane są tak samo jak pola składowe. Jeżeli funkcja jest zwykłym setterem to np.

void Foo::setAge( int newAge ) { age = newAge; }

Proste i zrozumiałe.
Co do samych nazw funkcji składowych to w zależności od ich zastosowania dodaję prefiksy. Wiadomo settery i gettery z odpowiednimi przedrostkami set i get:
void setAge;
int getAge;
Funkcje zwracające wartość logiczną z przedrostkiem "is", np:
bool Foo::isStupid() const { return stupid; }

Co do samych składowych, to tutaj wychodzę z prostego założenia. Jeżeli piszę coś prostego to przeważnie nie używam żadnego rozbudowanego środowiska z rozmaitymi smerfnymi hitami w stylu panel "symbol browser" czy jak tam zwał. Korzystając ze zwykłego notepad++ (bez żadnych pluginów), nie ma tego typu rzeczy. Jednakże taki projekt jest na tyle prosty iż nie ma możliwości abym gdzieś się zastanawiał: "czy jakaś nazwa reprezentuje składową, argument funkcji, zmienną zdefiniowaną w danej funkcji or whatever". Natomiast w większych projektach, które mogą utrudnić sprawną pracę używam odpowiedniego środowiska. Na wierzchu otwarty wcześniej wymieniony panel - no problem. Nie potrzebuję przedrostków typu m_skladowa lub skladowa, czy też skladowa, z czego pierwsza wersja nota bene brzydko wygląda ;]

consty, enumy, define'y - FOO. W przypadku enum'ów, dodatkowo poprzedzam zastosowanie dla danej stałej np:
enum GameState = { STATE_PAUSE, RUN_STATE }; itp.
Makra też z dużej.

Poza tym, nie wiem dlaczego, ale nie lubię nazw zmiennych w forach i innych pętlach typu: i,j,k,x,y,z itd. Wolę jednoznacznie określić że coś jest np indeksem z jakiegoś tam kontenera, lub nadać nazwę row i column zamiast i oraz j w zagnieżdżonych forach, przy wyborze czegoś z tablicy 2d.

To tak w skrócie, co mi do głowy teraz przyszło. Każdy wyrabia swój styl, który bardziej mu odpowiada.

0

A co sądzicie o przedrostku T z delphi?
Jak dla mnie trochę brzydkie, ale skuteczne, przykładowo:

class TGame {} Game; //<-- Obiekt nie musi się nazywać myGame czy jakkolwiek inaczej

Na swoje potrzeby, gdy namespace nie jest określony przez konkretny produkt używam czegoś takiego:

namespace T
{
    struct Bag{};
    struct Sword{};
    class Player
    {
        T::Bag Bag;
        T::Sword Sword;
    };
}
/* ... */
T::Player Player;
2

Mi osobiście jest obojętnie czy ktoś pisze notacjeWielbłądzią(),

czy formatuje kod(){
w taki sposób;
}

czy może ()
{
w taki sposób;
}

czyPiszeOdtępy, Czy też może nie daje ich wcale.. PrzeCzYtAm KażDe KrEjZoLsTwO.
Ważne jest dla mnie, żeby był w tym konsekwentny. Jeżeli wali notacje węgierską, to niech to robi od samego początku do końca.
Dla mnie dobry styl to konsekwencja.

1
spartanPAGE napisał(a):

A co sądzicie o przedrostku T z delphi?

Taka jest konwencja w tym języku i raczej wypada się jej trzymać.

Przedrostek chyba bierze się stąd, że po pierwsze Delphi nie rozróżnia wielkości liter, a po drugie Turbo Pascal nie pozwalał na użycie tej samej nazwy jako typu i jako zmiennej (Delphi chyba pozwala...).
Dlatego nie mogło być game:Game na wzór Game game; używanego np. w C++, i ktoś wymyślił game:TGame, tożsame z game:tgame, GAME:TGAME, gaME:tgaME, GaMe:TgAmE itd.

0

A tak btw., jak u Was wygląda sytuacja z nadawaniem polskich nazw dla zmiennych, funkcji itd.? Akceptowalne? Sami tak piszecie? Czy może nie lubicie tego? Wiem że jest to pewne odskoczenie od głównego tematu, lecz zastanawia mnie Wasze zdanie.
Osobiście nie przepadam za polskimi nazwami, gdyż mieszanka angielskich słów wraz z polskimi jakoś nie przekonuje mnie. Czasami mam wrażenie iż osoba używająca polskich nazw jest dopiero początkująca. Może się mylę :]

1 użytkowników online, w tym zalogowanych: 0, gości: 1