Czy istnieje wspólna konwencja wielkich liter w C ++? [Zamknięte]

13

Dużo pracuję w Pythonie i Javie, a oba te języki mają dość powszechne (choć nie uniwersalne) konwencje dotyczące używania wielkich liter w identyfikatorach: zarówno PascalCasedla nazw klas, jak i ALL_CAPSdla stałych globalnych, ale dla innych identyfikatorów dużo używa kodu Java, mixedCasepodczas gdy dużo używa kodu Python underscore_delimiters. Wiem, że żaden język ani biblioteka nie wymusza żadnych wielkich liter, ale odkryłem, że kiedy trzymam się standardowych konwencji dla języka, którego używam, mój kod wydaje się znacznie bardziej czytelny.

Teraz zaczynam projekt w C ++ i chciałbym zastosować ten sam pomysł. Czy jest jakaś najczęstsza konwencja wielkich liter, o której powinienem wiedzieć?

David Z
źródło
Problem z camelCase polega na tym, że nie działa dobrze z preprocesorem. Nie jest to duży problem, zwłaszcza że zwykle można uniknąć preprocesora.
Pubby
Musiałem zmierzyć się z tą decyzją zaledwie kilka dni temu. W końcu było to oczywiste, ponieważ zarówno standardowa biblioteka, jak i boost wykorzystują underscore_lowercase_delimiters. Ponieważ używam boosta jako boostera STL, wszystko będzie rozproszone o moim kodzie. Inne biblioteki, których używam, a mianowicie PascalCase (SFML), mogą być łatwiej zawarte, dzięki czemu każda metoda jest dość standardowa.
Maks.
@ Pubby8: z ciekawości: w jaki sposób camelCase koliduje z preprocesorem?
Joachim Sauer
@ JoachimSauer Poszczególne słowa w camelCase mogą mieć inną wielkość liter, ale makra nie mogą zmieniać wielkości liter. Staje się to problemem, jeśli chcesz makro, które bierze część słowa jako argument - być może będziesz musiał podać oba przypadki jako argumenty: makro (x, X). Jest to dość niewielki problem, ale powinien być znany, jeśli zamierzasz korzystać z preprocesora.
Pubby

Odpowiedzi:

27

Czy jest jakaś najczęstsza konwencja wielkich liter, o której powinienem wiedzieć?

C ++ jest oparty na C, który jest wystarczająco stary, aby opracować całą masę konwencji nazewnictwa do czasu wynalezienia C ++. Następnie C ++ dodał kilka, a C nie był bezczynny, myśląc o nowych. Dodaj do tego wiele języków pochodnych C, które rozwinęły konwencje nazewnictwa C wynalazcy do tego stopnia, że ​​zapłodnili ponownie C i C ++ ... Innymi słowy: C ++ nie ma jednej, ale wiele takich konwencji.

Jednak jeśli szukasz jednej konwencji nazewnictwa, równie dobrze możesz przyjrzeć się standardowej konwencji nazewnictwa biblioteki , ponieważ jest to jedyna, którą wszyscy programiści C ++ będą musieli znać i być do niej przyzwyczajeni.

Jednak najważniejszą zasadą jest: Bądź konsekwentny!

Co ciekawe, kiedy zaczynałem od mieszania PascalCase i camelCase i brałem udział w licznych projektach z jeszcze liczniejszymi konwencjami nazewnictwa, z biegiem lat coraz bardziej utknąłem w konwencji standard_library_convention. Nie pytaj mnie dlaczego.

sbi
źródło
Dzięki za informację ... więc standardowa biblioteka to podkreślenia? (przynajmniej bardziej niż cokolwiek innego?) Myślałem w ten sposób, ale trudno mi było powiedzieć z powodu takich rzeczy, jak iostream, w którym połowa nazw metod wydaje się być tym samym rodzajem wymieszanych fragmentów słów jak ANSI C :-P
David Z
5
@David: Biblioteka iostreams ma prawdopodobnie 25 lat i (z wyjątkiem C lib lub oczywiście) może być najstarszą częścią C ++ std lib. Mamy nadzieję, że nikt przy zdrowych zmysłach nie zaprojektowałby go w taki sposób, jak obecnie, i mam nadzieję, że nawet ci, którzy nie mają zdrowego rozsądku, nie wybraliby identyfikatorów w sposób, w jaki są używane w bibliotece strumieni. (Chodź, tam funkcje nazwane egptr, sputni uflowjak underflow. To jest po prostu zabawne!) W każdym razie, tak, lib std obecnie używa all_lowercase_with_underscores.
sbi
@sbi Dowiedziałem się, że biblioteka iostream nie jest już uważana za standardową bibliotekę dla C ++. I jak wspominasz, jego identyfikatory nie są przydatne jako konwencja programowania ;-)
umlcat,
2
@umlcat: Biblioteka iostreams (w szablonie z wersji przyjętej dla C ++ 03) jest zdecydowanie uważana za część standardowej biblioteki C ++.
sbi 11.11.11
Poszedłem też tą samą trasą. Myślę, że powodem jest camelCase jest nieco łatwiejszy do pisania i chciałem się tam lenić. Później dowiedziałem się, że spędziłem więcej czasu na czytaniu i refaktoryzowaniu kodu niż na pisaniu, a snake_case jest łatwiejszy do odczytania. Chodzi więc o minimalizację wydatków na energię. Teraz gram z użyciem małych liter dla klas. Jest to niekonwencjonalne, ale myślę, że przełączanie go i zmienianie ważnych instancji i typów małych liter poprawia czytelność mojego kodu. Myślę, że może to jest właściwa droga. Wielkie litery, co ważne, jak w języku humańskim.
PSkocik
19

Najpierw ustalmy, że ALL UPPERCASE jest odleżyną i należy ją zminimalizować.

Dlatego w C i C ++ jest on używany jako konwencja dla makr i tylko makr, ponieważ makra są równie brzydkie, by nie powiedzieć zło.

Wczesne C nie miało stałych, więc stałe musiały być wyrażone jako makra. Ponadto, w tych wczesnych dniach programy były znacznie krótsze, więc można było zastosować praktyki, które są dziś niezbyt dobre (np. IIRC Brian Kernighan napisał kod z dużą ilością makr innych niż wielkie litery). Ponadto w tamtych czasach istniały klawiatury, które nie miały małych liter; Użyłem jednego takiego, na norweskim komputerze Tandberg EC-10, około 1980 lub 1979, tak myślę.

Tak więc Java od początku przyjęła konwencję wielkich liter dla stałych C. Tymczasem, a może nawet wcześniej (nie jestem pewien chronologii tutaj), C ma stałe. Jednakże, chociaż oczywiście niektórzy / wielu programistów C utknęło we wcześniejszej konwencji z konieczności stałych jako makr pisanych wielkimi literami, programiści C ++ byli bardziej rozsądni.

Dużym problemem w dzisiejszych czasach jest to, że najpierw ludzie uczą się Java, a najpierw C (z konwencjami ze średniowiecza), a potem przychodzą do C ++, zabierając ze sobą tę okropną konwencję wielkich liter.

Więc,

    int const answer = 42;    // Nice, good, OK.
    const int ANSWER = 0x2A;  // Ouch!
    #define COMPANYNAME_ANSWER 052  // Oh kill me, please.

Może pomyślałeś, że w żartach wspomniałem o klawiaturach pisanych tylko wielkimi literami. O nie. Ponieważ jest to tylko najstarsze, najbardziej archaiczne ograniczenie technologii, które doprowadziło do konwencji nazewnictwa lub przynajmniej wpłynęło na to, jak źle się wydawały. Następnie pojawił się problem z 7-bitową transmisją szeregową, która spowodowała odpowiednie problemy z używanymi kodami znaków (kodowanie znaków w gazecie), co oznaczało, że musiałeś ograniczyć się do liter alfabetu angielskiego, od A do Z.

Właściwie polecam nadal to robić. Tam jesteśmy! Nie dotarliśmy dalej.

W chwili obecnej, począwszy od 2011 r., Standardowe C ++ obsługuje ogólne Unicode w nazwach (i robi to od 1998 r.), Podczas gdy rzeczywiste implementacje C ++ nie. W szczególności kompilator g ++ ma charakter narodowy. Wynika to z ograniczeń technologicznych średniowiecza.

Więc,

    double blueberryJamViscosity  = 0.0;    // OK
    double blåbærsyltetøyViskositet = 0.0;  // Ouch!

Wreszcie, jeśli chodzi o podkreślenia kontra przeplatane wielkie litery,

  • Zarezerwuj łatwo rozpoznawalny formularz dla nazw typów.
  • Zarezerwuj ALL UPPERCASE dla makr.
  • Bądź konsekwentny.

Myślę, że tak naprawdę, z wyjątkiem reguł takich jak „ogólnie unikaj nazwy jednoliterowej, z wyjątkiem (pętli, szablonu param, bla bla)” i „unikaj używania l, łatwo mylonego z 1” i „unikaj wielkich liter O, łatwo mylących z 0 ”. Ponadto, oczywiście, unikaj używania nazw zastrzeżonych, takich jak rozpoczynanie od znaku podkreślenia, a następnie wielkich liter, zawierających dwa kolejne znaki podkreślenia lub rozpoczynanie od znaku podkreślenia i znajdowanie się w globalnej przestrzeni nazw.

Pozdrawiam i hth

Alf P. Steinbach
źródło
Alf, ISTR Stroustrup wspominając o kopiowaniu D&E C constz C ++, więc musiało się to zdarzyć bardzo dawno temu i na długo przed Javą, prawdopodobnie dla C89.
sbi
2
Aha i serdecznie +1za „Bądź konsekwentny!” Czytając to, zastanawiam się, dlaczego zapomniałem wspomnieć o tej najważniejszej regule w mojej odpowiedzi, skoro nigdy nie zapomniałem powiedzieć o tym uczniom. Przypuszczam, że mi wybaczysz, jeśli dodam ją teraz do mojej odpowiedzi?
sbi
2

Zwykle trzymam się konwencji, którą widzę najbardziej w istniejących bazach kodu dla tego języka. W przypadku C ++ zwykle widzę camelCase. W przypadku Ruby lub PHP zwykle widzę takie rzeczy.

Realistycznie rzecz biorąc, najważniejsze jest to, aby wybrać konwencję stylu, która nie jest całkowicie szalona (dOnT_dO_tHiS) i być z nią zgodną. Spraw, aby styl nie zmieniał się w całym kodzie dla konkretnego projektu. Jeśli pracujesz nad istniejącym projektem, powinieneś wybrać styl, który już tam jest.

DeM0nFiRe
źródło
1

No cóż, jest System Węgierski, który jest naprawdę powszechny nawet teraz, ale wolę podciąć sobie gardło niż polecić. Aplikacje węgierskie są lepsze, ponieważ ich znaki opisowe naprawdę wskazują na semantykę, choć wydaje mi się, że jest to zbyt chętnie używane skróty, gdy wystarczy krótkie słowo. (Aby skorzystać z przykładu z tej strony Wikipedii, po co używać rwwiersza, gdy rowjest tylko jeden znak dłuższy? To nie tak, że występuje globalny niedobór samogłosek).

Jednak realistycznie najważniejsze jest przestrzeganie konwencji ludzi, z którymi pracujesz . Naprawdę. Większość konwencji działa wystarczająco dobrze, zwłaszcza jeśli jest konsekwentnie stosowana. Niespójność jest najgorsza (nawet bardziej niż węgierskie systemy, których nienawidzę). A jeśli jesteś sam, użyj tego, co chcesz.

Donal Fellows
źródło
1

Z tego, co widziałem, różni się w zależności od projektu.

Osadzone podkreślenia są prawdopodobnie bardziej tradycyjne / częściej używane w C na Uniksie. Biblioteka standardowa również to przestrzega, więc prawie na pewno powinna być traktowana jako domyślna, do użycia, chyba że istnieje wystarczający kod używający innej konwencji, aby absolutnie wymusić użycie tej innej konwencji.

Windows (na przykład) używa futerału wielbłąda do większości swoich funkcji, więc sporo osób, które pracują dla systemu Windows, robi to samo. Jest to również dość powszechne wśród ludzi, którzy są naprawdę bardziej przyzwyczajeni do innych języków i starają się traktować C ++ tak, jakby to był dziwny wariant czegoś innego.

Jerry Coffin
źródło
1

Użyłem zarówno standardowej biblioteki, jak i boost jako odniesień do konwencji nazewnictwa. Istnieje jednak problem z tym rozwiązaniem.

Biblioteka standardowa korzysta z konwencji nazewnictwa zaprojektowanej w celu ograniczenia kolizji z kodem. Częścią rozwiązania jest użycie wszystkich małych liter. Stąd użycie podkreślników zamiast camelCase.

Uważam, że camelCase jest czytelny. PascalCase jest często używany do nazw klas, ponieważ reprezentuje odpowiednik właściwego rzeczownika. Jednak złamię tę zasadę dla funktorów, które są bardziej reprezentatywne dla czasownika.

Staram się nie używać makr. Jednak kiedy to robię, makra wyglądają jak funkcje, kiedy mogą. Używam również wartości stałych lub wyliczeń zamiast stałych manifestu, dodatkowo unikając wielkich liter. Zazwyczaj poprzedzam te symbole literą „k”, aby wskazać, że są one stałe.

// instead of a manifest constant
#define HOURS 24

// use const
const int kHours = 24; 

// or enum
enum {
    kHours   = 24,
    kMinutes = 60
};
Bill Door
źródło
0

Odnośnik opisuje konwencję nazewnictwa, która jest bardzo podobna do tych, które z powodzeniem stosowałem w co najmniej trzech firmach, w których pracowałem w przeszłości.

W przeciwieństwie do wcześniejszej odpowiedzi, unikałbym przestrzegania konwencji nazewnictwa Biblioteki Standardowej C ++ we własnym kodzie, choćby z innego powodu niż unikanie kolizji nazw z Biblioteką Standardową.

Ta poprzednia odpowiedź SO na pokrewny temat może również być interesująca: /programming/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier

Gryźć
źródło
Umm, możesz użyć tej samej konwencji nazewnictwa bez używania tych samych nazw ... a jeśli naprawdę chcesz tych samych nazw, nadal jesteś chroniony przez przestrzenie nazw, np . std::stringVs. gnawme::string
einpoklum,