Korzystanie z przestrzeni nazw w C++

9 grudnia 2009

Dziś chciałbym pomarudzić o tym jak to genialni programiści olewają i ignorują istnienie tak genialnego wynalazku w C++ jak przestrzenie nazw.

Przestrzenie nazw rozwiązują problem kolizji nazw, szczególnie znany osobom programującym w C, gdzie istnieje jedna globalna przestrzeń nazw dla wszystkich nazw. A tym samym utrudnia pisanie programów, i odrębnych modułów.

Do rozwiązania problemu przestrzeni nazw można użyć wielu różnych sposobów i mechanizmów. Jednym z nich jest stosowanie rożnych wymyślnych prefiksów i sufiksów do definiowanych nazw zmiennych, czy typów, a tym samym powstają długie i kłopotliwe nazwy będące potworkami i zlepkiem kilku słów.

Na szczęście w C++ możemy zapomnieć o tych potworkach i wyrażać się jasno, krotko i zwięźle, a wszystko poprzez zdefiniowanie zasięgu, w którym dane nazwy będą obowiązywać, czyli przestrzeni nazw. Wprowadzono je do języka C++ w wyniku głosowania na posiedzeniu w Monachium w lipcu 1993 roku.

Korzystanie z nazw zawartych w przestrzeniach nazw jest możliwe na 3 sposoby.

Standardowo poprzez jawne kwalifikowanie ich użycia, czyli podanie pełnego identyfikatora przestrzeni nazw:

std::string name = "malcom";

Skorzystanie z deklaracji używania, która stworzy synonim dla nazwy w bieżącym zasięgu lokalnym, aby można było korzystać bez kwalifikowania nazwy danej przestrzeni nazw:

using std::string;
string name = "malcom";

Przez dyrektywę używania udostępniając w bieżącym zasięgu wszystkie nazwy z danej przestrzeni nazw:

using namespace std;
string name = "malcom";

I tutaj dochodzimy do sedna notatki. W wielu przypadkach programiści korzystają z ostatniej metody, w większości używane do włączenia przestrzeni nazw standardowej biblioteki, co gorsza dyrektywę tą “wrzucają” odruchowo na samym początku pliku, tuż po włączeniu nagłówków. Często tłumaczą się tym, że “tak będzie lepiej, prościej”, że “nie będę musiał pisać std:: za każdym razem”, itd.

Może wydaje się to sensowne, ale jest beznadziejnym krokiem, za który powinno się zakazywać takim ludziom wykonywanie swojego zawodu! O mój boże, niektórzy idą jeszcze dalej i “robią to” także w plikach nagłówkowych, samobójcy, dla nich już nie ma ratunku.

Nie po to wprowadzono przestrzenie nazw, aby zaraz je “wyłączać” za pomocą dyrektywy używania i z powrotem włączać wszystkie nazwy do globalnej przestrzeni nazw. Oczywiście zabieg taki czasem się przydaje w pojedynczych jednostkach translacji (plikach cpp), szczególnie przy różnego rodzajach testach czy przykładach, ale w produkcyjnym kodzie jest to niestosowne, jest błędem, za który możemy słono zapłacić.

Najgorsze jest użycie takiej dyrektywy w nagłówku, wystarczy choć w jednym umieścić taką linijkę, a skutki będą oddziaływać na cały projekt, nazwy będą widoczne w globalnej przestrzeni w każdym miejscu programu. O ile to Twój program, i nie masz zamiaru rozpowszechniać kodu do dalszego użycia, problem pozostaje tylko Twój, i nic mi do tego. Ale gdy tworzysz oprogramowanie, które będzie wykorzystywane przez innych deweloperów, popełniłeś niewybaczalny błąd. Dyrektywa ta będzie oddziaływać także na kod programisty korzystającego z Twojego kodu, zaśmiecając jego globalną przestrzeń nazw i wprowadzając wiele problemów, nieraz tak ukrytych, że trudno znaleźć przyczynę. Nikt Ci tego nie wybaczy, w najlepszym przypadku “oleją” Twój kod i skorzystają z konkurencji, i zapewne nigdy nie spróbują skorzystać z jakiegokolwiek twojego kolejnego genialnego kodu w swoich kolejnych projektach.

Myślałem, ze wykorzystanie dyrektywy używania mogę spotkać jedynie w różnych kodach początkujących adeptów sztuki programowania, że takie błędy użycia tego mechanizmu w nagłówkach raczej jest nie możliwe. A jednak myliłem się, ostatnio natrafiłem przypadkiem na kod jakiegoś programisty, który szczycił się dobrą znajomością C++ z takim bublem w kodzie.

Tak, więc pozostaje odpowiedzieć na pytanie jak dobrze korzystać z przestrzeni nazw.

Bardzo prosto, używać zawsze pierwszego sposobu, czyli jawnie kwalifikować nazwę przestrzeni nazw. Jeśli, z jakiś powodów jest to kłopotliwe, bądź przestrzenie są kilkukrotnie zagnieżdżone, możemy wykorzystać deklaracje użycia tylko do tych nazw, które rzeczywiście będą nam potrzebne, a w pewnych sytuacjach także dyrektywę użycia. Z jednym małym wyjątkiem, używać using w jak najmniejszym zasięgu jaki tego wymaga. Przestrzenie nazw podlegają regułom zasięgu i widoczności, zatem “odkrywanie” przestrzeni powinno być podobne jak najmniejsze, podobnie jak zasięg zmiennych.

Czyli jeśli mamy funkcję, która wewnętrznie usilnie korzysta z std::string, najłatwiej jest skorzystać z deklaracji using w ciele funkcji:

void MyFunction() {
	using std::string;
 
	string str = "malcom";
	string::size_pos pos = str.find(...);
 
	...
}

Pisząc krotko, unikać jak ognia dyrektywy używania, a stosować jawne kwalifikowanie nazw i ewentualnie deklarację używania w celu łatwego i wygodnego posługiwania się nazwami z innych przestrzeni nazw.

Bjarne Stroustrup ma podobne zadnie na ten temat:

Osobiście uważam dyrektywy używania przede wszystkim za narzędzie służące do przechodzenia do korzystania z przestrzeni nazw. Można bardziej przejrzyście napisać większość programów, jeżeli korzysta się z jawnego kwalifikowania nazw i deklaracji używania tam, gdzie odnosimy się do nazw z innych przestrzeni nazw.

Notatka ta nie wyczerpuje całego tematu używania i korzystania z przestrzeni nazw, sygnalizuje jedynie problem bardzo zlej praktyki związanej z wykorzystaniem dyrektywy używania, nie tylko przez początkujących. Co w wielu przypadkach staje się złym nawykiem, który później jest źródłem wielu bledów nie tylko w naszym kodzie.

Przestrzenie nazw są wspaniałym narzędziem, i powinniśmy z niego korzystać, a także organizować nasz kod i jego strukturę z ich użyciem. I to nie tylko w sytuacji kiedy piszemy bibliotekę, czy moduł, ale także w wielu nieco większych programach pozwalają na lepszą organizację kodu oraz co ważne na używanie krótkich i zwięzłych nazw, niejednokrotnie tych samych w różnych miejscach, bez strachu przed kolizją nazw lub niejednoznacznością.

Przestrzenie nazw wydają się bardzo prostym mechanizmem i w rzeczywistości takim są, ale posiadają dosyć duże możliwości niż się może wydawać na pierwszy rzut oka. Kiedyś wspominałem o aliasowaniu przestrzeni nazw – mechanizmie, o którym niektórzy być może nie słyszeli, a zajmują się językiem C++ od dawna. Innym ciekawym narzędziem są anonimowe przestrzenie nazw które nieco różnią się od zwykłych nazwanych, mam nadzieję, że będę miał okazję za niedługo o tym trochę pomówić. Deklaracja używania pełni również jakieś funkcje w klasach i dziedziczeniu oraz wzorach.

Nadużywanie preprocesora w C++

30 listopada 2009

Wszyscy wiemy czym jest preprocesor Cpp i jak działa (dla niewtajemniczonych czym jest preprocesor, jakie oferuje funkcje i pułapki polecam jeden z rozdziałów Megatutoriala Xiona). Jest to narzędzie odziedziczone z C, operujące na tekście programu, a tym samym nie mające żadnego pojęcia o składni języka jaką przetwarza. Jest narzędziem, które używane nierozważnie może łatwo doprowadzić [...]

czytaj całość »

Modern C++

23 listopada 2009

W nawiązaniu do poprzedniej notatki, niejakim uzupełnieniem przedstawionych tam informacji i zapowiedzi o dzieleniu się głębszymi przemyśleniami i odczuciami jakimi mnie napełnił kolejny przeprowadzony code review, będą notatki przedstawiające nieco bardziej zaawansowane aspekty i techniki używane w C++.
Mam tu na myśli notatki traktujące o tytułowym “modern C++”, czyli nowoczesnym i zaawansowanym C++, gdzie głównie wykorzystywane [...]

czytaj całość »

Dlaczego w C++ jest lepiej?

18 listopada 2009

Skusiłem sie do napisania tej notatki w wyniku pogłębiającej się frustracji i zażenowania jakie mnie ogarnia, gdy po raz kolejny przeglądam jakiś kod źródłowy dowolnego oprogramowania napisanego (według jego autora) w C++. Niestety dosyć często się zdarza, że w rzeczywistości w ogóle to niewiele ma wspólnego z tym językiem, zastosowane techniki i styl mówią coś [...]

czytaj całość »

Trudne przypadki: buffer overflow

6 listopada 2009

Buffer overflow, czyli przepełnienie bufora jest jednym z najczęściej wykrywanych błędów w różnej maści oprogramowaniu. Błąd ten polega na zapisaniu do wyznaczonego obszaru pamięci większej ilości danych, niż zostało to przewidziane przez twórcę, powodując nadpisanie sąsiadujących z buforem komórek pamięci, co w ostateczności prowadzi do rożnych nieprzewidywanych zachowań aplikacji.
W najlepszym wypadku spowoduje to “wywalenie” się [...]

czytaj całość »

Active Template Library

23 października 2009

Ostatnio bawiłem sie z prostą aplikacją embedując kontrolkę Internet Explorera oraz silnik Gecko. Po raz pierwszy miałem nieco szerszy i dłuższy kontakt z technologią COM i XPCOM.
Nieodłączny związek z COM ma biblioteka ATL (Active Template Library), która w rzeczywistości jest zbiorem klas szablonowych języka C++ opracowanych przez Microsoft. Jak sie można domyślić z nazwy, [...]

czytaj całość »

Bakefile: shell rule

19 września 2009

O systemie budowania aplikacji bakefile, generującym odpowiednie pliki dla make i projekty dla różnych środowisk IDE, pisałem już w przeszłości. Jest to wspaniale narzędzie, szczególnie przy tworzeniu multi platformowego oprogramowania.
Dosyć często zdarza się, że chcemy dorzucić do makefile jakieś niestandardowe reguły oparte na wykonaniu kilku poleceń w powłoce systemowej. Bakefile zawiera odpowiednie mechanizmy do takich [...]

czytaj całość »

WP Math Captcha

17 września 2009

W poprzedniej notce wspomniałem o rezygnacji z dotychczas używanego filtru anty-spamowego, a z powodu takiego, że mój devblog ciągle nawiedzają jakieś spam boty i zaśmiecają bazę niepotrzebnymi komentarzami-śmieciami, musiałem coś zaaplikować, coś co ich powstrzyma i zmniejszy ten, jakże paskudny, proceder.
W celu tym przejrzałem katalog wtyczek do WP pod etykietą spam oraz rozejrzałem się po [...]

czytaj całość »

Zmiany na devblogu

17 września 2009

Przez ostanie 2 dni trochę pomęczyłem się z nowym designem i szablonem devbloga, czego skutkiem jest “wisząca” od wczoraj nowa odsłona. Stary szablon od dawna mi się już nie podobał i trochę mnie uwierał, ale nigdy nie chciało mi się tego zmienić, bo albo brak czasu, albo chęci. A ostatnio, robiąc wielki review swoich stron, [...]

czytaj całość »

Programowanie wymaga myślenia!

9 września 2009

Programowanie, optymalizacja i myślenie…
Sztuka programowania łączy w sobie te trzy sfery, umiejętne ich wyważenie staje się dobrym wyznacznikiem dla programisty. Bez jakiegokolwiek z nich traci on swój potencjał i staje się zwykłym koderem, klepiącym bez namysłu kod jaki inni mu każą. No cóż, tacy “robotnicy” są również potrzebni przemysłowi, aby wszystko kręciło się dalej.
Optymalizacja jest [...]

czytaj całość »

miniBlog

malcom.pinger.pl
22:15:23 07/03/2010
Powrot do zycia ;)
19:32:00 04/01/2010
first day on a new job ;)
18:33:32 14/12/2009
Popularnosc jezykow programowania
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
17:54:43 02/12/2009
Moge powiedziec poki co tylko tyle ze intro i muzyka z #Paradox mi sie wybitnie podoba ;p
01:35:01 02/12/2009
Lin Xu przedstawia nowe usprawnienia optymalizacyjne w VC2k10:
http://blogs.msdn.com/vcblog/archive/2009/12/01/gl-and-pgo.aspx
13:35:46 01/12/2009
Secret #Perl Operators
http://www.catonmat.net/blog/secret-perl-operators/
15:58:58 30/11/2009
Interlocked* Win32 - ciekawe zadanie dla chetnych ;p
http://groups.google.pl/group/pl.comp.lang.c/browse_thread/thread/c4ccf09a972ed50d
11:23:06 26/11/2009
W ostatnich dniach troche moich patchy do wxWidgets sie "przeforsowalo"...
23:00:04 22/11/2009
Troche sie rozczarowalem, mialem nadzieje, ze bedzie kontynuacja watku z ostatniego odcinka Stargate Universe...
22:14:56 21/11/2009
Pwtornie motyw "Polscy chłopcy w językach obcych" w Strefa rokendrola wolna od angola na "trocjce" ;)
14:35:39 17/11/2009
"People often write less readable code because they think it will produce faster code. Unfortunately, in most cases, the code will not be faster."
Krotka prezentacja o tym co potrafia wspolczesne kompilatory (odnosnie optymalizacji):
http://www.linux-kongress.org/2009/slides/compiler_survey_felix_von_leitner.pdf
01:10:43 17/11/2009
The Pirate Movie - swietny film z swietnym soundtrackiem, szczegolnie utwor (Song of) Victory.
Dla odmiany nieco metalowa wersja, cover Mayhayrona
http://www.youtube.com/watch?v=Ud8uAKW3U4o
00:11:46 08/11/2009
Bezstykowe karty Mifare sa bardzo wygodne w uzyciu. Gorzej jak ma sie ich kilka np. w portfelu (legitymacja, karta miejska) i chce sie jednej uzyc bez wyjmowania... co ostatnio doswiadczylem przy bramkach na WAT-cie. Zapewne przy metrze i kasownikach bedzie podobnie ;p
01:14:00 06/11/2009
Dziwny swiat, dziwni ludzie, teraz beda dublowoac wszelkie swoje "smieci" w sieci.
Moze warto zintegrowac rowniez wiekszosc for dyskusyjnych i wysylajac na jedno, wysylac na pol sieci?
23:10:46 20/10/2009
Ostatnio babralem sie z COM i XPCOM przy embedowaniu #IE i #Gecko do prostej aplikacji. Moze w xime oprze API na czyms podobnym... Latwe i przyjemne uzywanie spod C++ i C, czyli zewszad ;)
20:48:44 13/10/2009
Musialem napisac co mysle o nowym #tlen, bo nie potrafilem dluzej sie powstrzymac, przepraszam.
http://ekipa.tlen.pl/forum/index.php?showtopic=11310
10:38:53 12/10/2009
Kolumna "This Week in Boost" na "C++Next" mam nadzieje, ze bedzie ciekawa ;p
http://cpp-next.com/archive/2009/10/introducing-%e2%80%9cthis-week-in-boost%e2%80%9d/
13:53:47 06/10/2009
Polskie brzmienia w lacisnkim rocku - Amaryllis ;)
Mi szczegolnie przypadl do gustu utwor "Magnificat".
12:03:14 06/10/2009
Podazajac kierunkiem ostatniej wolnej strefy - "Polscy chłopcy w językach obcych", dzisiejsze poludnie sponsoruje Percival Schuttenbach ;)
http://www.youtube.com/watch?v=uQvvE5qNxi4
http://www.youtube.com/watch?v=Gb36Qyq8DyY
09:15:37 06/10/2009
Paskudny ten #tlen na #qt, kontrolki takie bleee, emulwoane/malowane nijak maja sie do natywnych.
18:22:56 29/09/2009
s2s @ #tlen jest online [via kaworu]
19:50:34 25/09/2009
Maly bug w wx'ach, a juz chcialem klnac na MS...
13:26:02 23/09/2009
Dla tych, ktorzy wciaz nie wiedza, ze jabber != xmpp ;p
http://forum.jabberpl.org/index.php?showtopic=7380
23:05:32 22/09/2009
Na USiu tez mnie "chca", ale zostane przy WAT, tylko 2x drozej ;p
21:43:24 20/09/2009
Szybka konwersja znakow konca linii win<>unix, bez zaprzegania perla, awka i innych kobyl, via sed:
sed -e 's/\r//' -i plik
sed -e 's/$/\r/ -i plik
13:16:55 18/09/2009
Czas myslec o przeniesieniu sie do stolicy, od kolejnego miesiaca swoja pseudo-edukacje bede kontynuowal na WAT.
Military University of Technology ;)
23:27:26 17/09/2009
Cala siec podnieca sie poszlakami na temat nktalk i przewidywaniem krucjaty #xmpp przeciwko #gg...
A myslalem ze bedzie spokoj, ale jak widac za stary jestem chyba na siec, bo mnie byle g*wno nie kreci :(
22:34:31 17/09/2009
Dzisiejszy wieczór sponsoruje metal łacinski w wydaniu niemiecki (In Extremo) i rosyjskim (koncertowo Наследие Вагантов), czyli kochane "Totus Floreo".
http://www.youtube.com/watch?v=_6SY_-ijgEI
http://www.youtube.com/watch?v=igTy288Ay9E
20:19:03 17/09/2009
Od wczoraj na devblogu nowy design ;)
Pozostalo jeszcze skrobnac te kilka linijek o antispam math captcha do wp.
22:53:04 15/09/2009
Dzisiejszy wieczor sponsoruje Škwor i Sraž nás na kolena
http://www.youtube.com/watch?v=C1JSL7jBPw0