2011-08-05 11 views
18

jestem stwierdzenia, że ​​co ja za „najlepsze praktyki” do użycia nazw w C++ boli czytelności mojego kodu, a co mnie pytanie jak z nich korzystać również.C++ nazw najlepszych praktyk dylemat

Mój program składa się z kilku różnych modułów, które są najczęściej budowane w bibliotekach, że „głównym” aplikacja używa. Każda biblioteka używa własnej przestrzeni nazw, a ich przestrzenie nazw są "wewnątrz" przestrzeni nazw projektu, aby pomóc w projektowaniu przeciwko konfliktom nazw z kodem firm trzecich. Tak więc kończę z nazwami klas, takimi jak "myproject :: logging :: Logger" i "myproject :: reporting :: ReportType" (Jak wymyślono przykłady).

tej pory tak dobrze. A w moich plikach .cpp nie mam problemu. Używam "using myproject :: logging" na przykład na górze strony i mogę bez problemu odnieść się do mojej klasy Logging. W mało prawdopodobnym przypadku konfliktu między dwiema moimi przestrzeniami nazw mogę wprost powiedzieć, który z nich chcę. To działa dobrze.

Pliki nagłówkowe są różne choć. Uważa się za złą praktykę umieszczanie instrukcji użycia w plikach nagłówkowych, ponieważ wpłyną one na niepowiązany kod, który może ich nie oczekiwać. Dlatego zawsze w pełni kwalifikuję wszystkie nazwy w plikach .hpp. To było trochę brzydkie, ale do tej pory było to możliwe, więc zniosłem to. Ale teraz zwiększam używanie kodu szablonu w moich bibliotekach, co oznacza, że ​​jest teraz o wiele więcej aktualnego kodu w moich plikach .hpp. A całkowite zakwalifikowanie każdego nazwiska powoduje, że kod jest praktycznie nieczytelny ze względu na długość nazw typów.

Zaczynam odczuwać, że korzyści wynikające z używania przestrzeni nazw i najlepszych praktyk w ich używaniu zaczynają być przeważane przez nieodwracalny kod, który muszę napisać. Zaczynam się zastanawiać, czy lepiej byłoby zrezygnować z używania przestrzeni nazw, aby zyskać korzyść z bardziej czytelnego kodu i naprawić konflikty nazw, jeśli i kiedy się pojawią.

Alternatywą jest użycie krótkich, jednowarstwowych przestrzeni nazw, więc zamiast "myproject :: logging :: Logger" miałbym tylko "log :: Logger", co bardzo by pomogło, ale znacznie zwiększyłoby prawdopodobieństwo konfliktów przestrzeni nazw. , a także mają przestrzenie nazw przekazują mniej użytecznych informacji.

Jak mówiłem, to tylko naprawdę wpływa kod w plikach .hpp jak ja szczęśliwie używając „używając nazw” w moich plikach wdrożeniowych aby łatwiej zarządzać, ale jest staje się problemem, jak patrzę na moja matrycy kod w plikach .hpp teraz i myśleć „eww ....”, który nie może być dobre: ​​P

ktoś ma jakieś praktyczne porady?

+2

'dyrektyw using' są scoped, więc może można dokonać pewnych Shorthands przestrzeni nazw, które nie przeciekają na zewnątrz pliku nagłówka? –

Odpowiedz

13

Byłem w tej sytuacji wcześniej. Często jest tak, że wiele funkcji/klas w nagłówkach jest naprawdę "implementacją", chociaż z natury szablonów w C++ jesteś zmuszony umieścić je w pliku nagłówkowym. Dlatego właśnie umieszczam wszystko w przestrzeni nazw "szczegółów" lub "implementacji", gdzie mogę wygodnie używać "używania przestrzeni nazw". Na koniec "rzucam" to, co ludzie powinni używać w odpowiednim miejscu. W ten sposób:

namespace myproject { namespace somemodule { 

namespace _implementation { 

using namespace myproject::othermodule; 
using namespace myproject::yetanothermodule; 

template <...> 
class some_internal_metafunction{ 
... 
}; 

template <...> 
class stuff_people_should_use_outside { 
... 
}; 

} // namespace implementation  

using stuff_people_should_use_outside ; 
}} // namespace myproject::somemodule 

Takie podejście może jednak zwiększyć nieco nazwy w raportach kompilatora.

Alternatywnie można zrezygnować z przestrzeni nazw modułów. Ale może to nie być dobry pomysł na bardzo duży projekt.

+2

Czy musi to być 'using _implementation :: stuff_people_should_use_outside;'? – Hugues

+0

@dsign: Należy rozważyć aktualizację odpowiedzi! – abhiarora

5

osobiście? Pozbyłbym się części "myproject". Jaka jest szansa, że ​​twoja biblioteka użyje dokładnie tej samej nazwy przestrzeni nazw, co inne i, które mają zdefiniowany symbol o tej samej nazwie co inny?

Również chciałbym zaproponować skrócenie nazwy do przestrzeni nazw można oczekiwać, aby być używane w nagłówkach.

+6

"Jaka jest szansa, że ​​twoja biblioteka użyje dokładnie tej samej nazwy przestrzeni nazw co druga i będzie miała zdefiniowany symbol o tej samej nazwie co inny" dla danego przykładu, "logger :: Logger", powiedziałbym, że szansa jest całkiem wysoko, że są dwa takie na świecie. Każdy, kto próbuje korzystać z obu bibliotek w jednym programie jest mniej prawdopodobny, ale na prawdopodobieństwie ':: myproject :: Logger' jest nieco bezpieczniejszy niż' :: logging :: Logger' (zakładając, że "myproject" jest zastąpiony rzeczywistą nazwą projektu , ofc). –

0

Jeśli twój projekt nie jest bardzo bardzo duży (mam na myśli, bardzo duży), wystarczy użyć tylko myproject. Jeśli naprawdę chcesz podzielić projekt na części, możesz użyć bardziej ogólnych przestrzeni nazw. Na przykład, gdy budowałem silnik gry, wybrałbym przestrzenie nazw takie jak MyEngine :: Core, MyEngine :: Renderer, MyEngine :: Input, MyEngine :: Sound itd.

+0

To nie tylko * rozmiar * projektu - to zmienność kodu, szczelność cykli wydawniczych, prawdopodobieństwo podobnych wymagań funkcjonalnych/podmiotów itp. Oraz zakres koordynacji, który jest praktyczny między deweloperami. Na przykład, w dużej mierze niezależni deweloperzy (powiedzmy w różnych krajach) z napiętymi cyklami wydawniczymi, piszącymi wiele nowych kodów, aby robić podobne rzeczy (np. Różne formuły cen papierów wartościowych) będą bardziej skłonni domagać się niezależnych przestrzeni nazw niż pojedynczy deweloper, w głównej mierze dostosowujący implementację istniejących funkcje .... –

2

Moje doświadczenie było takie, że jest dużo wygodniej jest mieć jeden obszar nazw dla całego kodu z powodów wymienionych w oryginalnym wpisie. Ta przestrzeń nazw chroni twoje identyfikatory przed kolidowaniem z identyfikatorami z bibliotek stron trzecich. Twoja przestrzeń nazw jest twoją dominacją i łatwo jest zachować jej nazwę bez konfliktów.

+0

"Twoja przestrzeń nazw to twoje królestwo" - jeśli nazwiesz ją GUID lub coś takiego. Niepowtarzalny, niezapomniany i krótki: wybierz dwa ;-) –

+1

Niezapomniany nie jest konieczny, zawsze możesz go wyszukać. A więc wyjątkowy i krótki. –

+1

Więc kończy się wywoływanie przestrzeni nazw najwyższego poziomu 'hFPu9_'. W praktyce nie ma tu większego problemu, ale w zasadzie dwa niepowiązane projekty mogą wybrać ten sam obszar nazw najwyższego poziomu, a wtedy masz kłopoty. Właśnie dlatego Java używa odwrotnych nazw domen. Zapewnia wyjątkowość kosztem zwięzłości. –

18

Oto co robię.

W <mylibrary.h>:

namespace myproject { 
    namespace mylibrary 
    { 
    namespace impl 
    { 
     using namespace otherlibrary; 
     using namespace boost; 
     using namespace std; 
     using namespace whatever::floats::your::boat; 

     class myclass; 
     class myotherclass; 
    }; 
    using impl::myclass; 
    using impl::myotherclass; 
    }; 
}; 

W źródle:

#include <mylibrary.h> 
using namespace myproject::mylibrary; //clean! 
+0

To szwy jak dobre rozwiązanie. Nie rozumiem liczby linii komentarza/żartów Maxima. –

+0

Rozumiem. otrzymujesz 2x linie dla prototypów funkcji. Jeden dla prototypu funkcji, a drugi dla "using impl :: function" :(To jest dobre dla klas –

Powiązane problemy