Professional Documents
Culture Documents
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Spis treci
Wstp.........................................................................................................................7
Rozdzia 1. Kwestie organizacyjne ..............................................................................13
Wytyczna 0. Nie bd maostkowy (czyli czego nie standaryzowa) .......................................... 14
Wytyczna 1. Dbaj o bezbdn kompilacj przy najwyszym poziomie ostrzee kompilatora.. 17
Wytyczna 2. Korzystaj z automatycznych systemw kompilacji ................................................ 20
Wytyczna 3. Korzystaj z systemu kontroli wersji ........................................................................ 22
Wytyczna 4. Nie oszczdzaj na wzajemnej rewizji kodu............................................................. 24
Rozdzia 2. Styl projektowy ........................................................................................27
Wytyczna 5. Jednej jednostce jedno zadanie ............................................................................... 29
Wytyczna 6. Przede wszystkim poprawno, prostota i przejrzysto......................................... 31
Wytyczna 7. Jak i kiedy kodowa z uwzgldnieniem skalowalnoci........................................... 33
Wytyczna 8. Wystrzegaj si przedwczesnej optymalizacji .......................................................... 36
Wytyczna 9. Wystrzegaj si przedwczesnej pesymizacji............................................................. 39
Wytyczna 10. Minimalizuj ilo danych globalnych i wspuytkowanych................................ 41
Wytyczna 11. Ukrywaj informacje .............................................................................................. 43
Wytyczna 12. Niepotrzebna rywalizacja to niezdrowa rywalizacja ............................................. 45
Wytyczna 13. Zagwarantuj opiek nad zasobami przez obiekty.
Stosuj RAII i inteligentne wskaniki .................................................................... 49
Rozdzia 3. Styl kodowania.........................................................................................53
Wytyczna 14. Lepsze bdy kompilacji i konsolidacji od bdw czasu wykonania ................... 54
Wytyczna 15. Nie bj si stosowania const ................................................................................. 57
Wytyczna 16. Unikaj makrodefinicji ........................................................................................... 59
Wytyczna 17. Unikaj magicznych numerkw .......................................................................... 62
Wytyczna 18. Zmienne deklaruj najbardziej lokalnie, jak to moliwe......................................... 64
Wytyczna 19. Kada zmienna powinna zosta zainicjalizowana................................................. 66
Wytyczna 20. Unikaj rozwlekych funkcji, wystrzegaj si gbokich zagniede ..................... 69
Wytyczna 21. Unikaj zalenoci inicjalizacji w rnych jednostkach kompilacji ....................... 71
Spis treci
Wytyczna 22. Redukuj zalenoci definicyjne i unikaj zalenoci cyklicznych .......................... 73
Wytyczna 23. Niech pliki nagwkowe bd samowystarczalne ................................................. 75
Wytyczna 24. Pamitaj o wewntrznych barierach plikw nagwkowych,
unikaj barier zewntrznych ................................................................................... 77
Rozdzia 4. Funkcje i operatory...................................................................................79
Wytyczna 25. Parametry przyjmowa odpowiednio przez warto,
(inteligentne) wskaniki albo referencje ............................................................... 80
Wytyczna 26. Zachowuj naturaln semantyk przecianych operatorw .................................. 82
Wytyczna 27. Preferuj kanoniczne postaci operatorw arytmetycznych i przypisania................ 84
Wytyczna 28. Preferuj kanoniczne postaci operatorw ++ i -- oraz ich wersje przedrostkowe ... 86
Wytyczna 29. Przecianie w miejsce niejawnej konwersji typw.............................................. 88
Wytyczna 30. Unikaj przeciania operatorw &&, || i operatora , (przecinka) .......................... 90
Wytyczna 31. Nie uzaleniaj poprawnoci kodu od kolejnoci ewaluacji
argumentw wywoania funkcji............................................................................ 93
Rozdzia 5. Projektowanie klas i dziedziczenie .............................................................95
Wytyczna 32. Ustal rodzaj definiowanej klasy ............................................................................ 96
Wytyczna 33. Lepsze klasy minimalistyczne ni monolityczne .................................................. 98
Wytyczna 34. Lepsza kompozycja od dziedziczenia ................................................................. 100
Wytyczna 35. Nie dziedzicz po klasach, ktre nie zostay przewidziane jako bazowe.............. 103
Wytyczna 36. O wyszoci interfejsw abstrakcyjnych ............................................................ 106
Wytyczna 37. Dziedziczenie publiczne daje wymienialno ..................................................... 109
Wytyczna 38. Uprawiaj bezpieczne przesanianie ..................................................................... 111
Wytyczna 39. Niech metody wirtualne bd niepublicznymi, a publiczne niewirtualnymi.. 114
Wytyczna 40. Unikaj udostpniania konwersji niejawnych....................................................... 117
Wytyczna 41. Skadowe klas, z wyjtkiem klas prostych agregatw, powinny by prywatne .. 120
Wytyczna 42. Nie trwoni tego, co wasne................................................................................ 123
Wytyczna 43. Zachowaj umiar w implementacjach prywatnych ............................................... 126
Wytyczna 44. Warto polubi zwyke funkcje nieskadowe i niezaprzyjanione................... 129
Wytyczna 45. Zawsze udostpniaj komplet: new razem z delete............................................... 131
Wytyczna 46. Jeli przecia new dla klasy, to porzdnie z wszystkimi standardowymi
formami operatora............................................................................................... 133
Rozdzia 6. Konstrukcja, destrukcja i kopiowanie....................................................... 135
Wytyczna 47. Porzdek inicjalizacji skadowych danych powinien by zgodny
z porzdkiem ich deklaracji ................................................................................ 136
Wytyczna 48. W konstruktorze lepsza inicjalizacja od przypisania........................................... 138
Wytyczna 49. Unikaj wywoa metod wirtualnych w konstruktorach i destruktorach .............. 140
Wytyczna 50. Destruktory klasy powinny by albo publiczne i wirtualne,
albo niewirtualne i zabezpieczone ...................................................................... 143
Wytyczna 51. Operacje destrukcji, dealokacji i podmiany nigdy nie zawodz.......................... 146
Wytyczna 52. Usuwaj, co skopiujesz......................................................................................... 149
Wytyczna 53. Jawnie udostpniaj i blokuj kopiowanie ............................................................. 151
Spis treci
Spis treci
Rozdzia 11. Algorytmy STL ...................................................................................... 241
Wytyczna 83. Korzystaj z udogodnie kontrolnych implementacji STL................................... 242
Wytyczna 84. Algorytmy s lepsze od ptli............................................................................... 245
Wytyczna 85. Wybieraj z STL waciwe algorytmy wyszukiwania .......................................... 249
Wytyczna 86. Wybieraj z STL odpowiednie algorytmy sortowania.......................................... 251
Wytyczna 87. Predykaty powinny by funkcjami czystymi ...................................................... 254
Wytyczna 88. W wywoaniach algorytmw miejsce funkcji powinny zajmowa
obiekty funkcyjne ............................................................................................... 256
Wytyczna 89. Zadbaj o poprawno obiektw funkcyjnych...................................................... 258
Rozdzia 12. Bezpieczestwo typw .......................................................................... 261
Wytyczna 90. Zamiast przeczania pomidzy typami stosuj polimorfizm ............................... 262
Wytyczna 91. Polegaj na typach, nie na reprezentacjach........................................................... 265
Wytyczna 92. Unikaj rzutowania reinterpret_cast ..................................................................... 267
Wytyczna 93. Unikaj rzutowania static_cast na wskanikach ................................................... 269
Wytyczna 94. Zachowuj const przy rzutowaniu ........................................................................ 271
Wytyczna 95. Nie korzystaj z rzutowania znanego z C ............................................................. 273
Wytyczna 96. Nie wolno brutalnie kopiowa obiektw typw innych ni proste POD............. 276
Wytyczna 97. Unie nie su do reinterpretacji reprezentacji .................................................... 278
Wytyczna 98. Nie stosuj zmiennych list argumentw (trzykropkw)........................................ 280
Wytyczna 99. Nie korzystaj z niepoprawnych obiektw i niebezpiecznych funkcji.................. 282
Wytyczna 100. Nie wykorzystuj tablic polimorficznie .............................................................. 284
Dodatek A Bibliografia ............................................................................................. 287
Dodatek B Podsumowanie ....................................................................................... 295
Skorowidz ............................................................................................................... 313
Rozdzia 2.
Styl projektowy
Gupcy ignoruj zoono. Pragmatycy od niej cierpi. Niektrzy potrafi jej
unika. Geniusze za j eliminuj
Alan Perlis
Trudno w peni rozdzieli styl kodowania od stylu projektowania. Dlatego w tym rozdziale postaralimy si uwzgldni te wytyczne, ktre umykaj uwadze, kiedy mowa
o waciwym kodowaniu.
Niniejszy rozdzia powicony jest zasadom i praktykom dajcym si zastosowa szerzej
ni do pojedynczej klasy czy funkcji. Klasycznym przykadem jest zachowanie rwnowagi pomidzy prostot a przejrzystoci kodu (patrz wytyczna 6.) czy unikanie przedwczesnej optymalizacji (wytyczna 8.), a take przedwczesnej pesymizacji (wytyczna
9.). Owe trzy wytyczne mona stosowa nie tylko na poziomie kodowania funkcji, ale
rwnie na poziomie wyszym, obejmujcym kwestie projektowania klas i moduw
oraz decyzje co do architektury aplikacji (owe wytyczne obowizuj wszystkich programistw uwaajcy inaczej powinni zerkn raz jeszcze na stwierdzenie Donalda
Knutha i sprawdzi, kog on z kolei cytowa).
Wiele wytycznych z tego i nastpnych rozdziaw odnosi si do aspektw zarzdzania zalenociami kamienia wgielnego inynierii oprogramowania i rwnoczenie
zagadnienia powracajcego w tej ksice wielokrotnie. Pomyl przez chwil nad dowoln
dobr technik inynierii oprogramowania dowoln dobr technik. Jakakolwiek
by ona bya, w ten czy inny sposb polega na redukcji zalenoci. Dziedziczenie?
Zmniejsza zaleno kodu pisanego pod ktem klasy bazowej od klas pochodnych.
Redukcja liczby zmiennych globalnych? To jawna redukcja rozcigych zalenoci
w stosunku do widocznych rozlegle danych. Abstrakcja? To eliminacja zalenoci
pomidzy kodem manipulujcym pojciami a kodem implementujcym te pojcia.
28
29
Wytyczna 5.
Jednej jednostce jedno zadanie
Wytyczna 5. Jednej jednostce jedno zadanie
Streszczenie
Lepiej robi jedn rzecz, a dobrze. Wedle tej zasady naleaoby nadawa poszczeglnym
jednostkom programu (zmiennym, klasom, funkcjom, przestrzeniom nazw, moduom,
bibliotekom) jasno okrelone i rwnoczenie ograniczone zadania. W miar rozrostu
jednostki zakres jej zada w sposb naturalny si zwiksza, nie powinien jednak obejmowa coraz to nowych obszarw.
Uzasadnienie
Powiada si, e dobry pomys na biznes to taki, ktry mona uj w jednym zdaniu.
Podobna regua tyczy si jednostek programu, ktre powinny mie konkretne i jasno
okrelone zadania.
Jednostka odpowiadajca za wicej ni jedno zadanie jest zwykle nieproporcjonalnie
trudniejsza w uyciu ni zestaw jednostek prostszych o mniejszej odpowiedzialnoci,
poniewa jej implementacja obejmuje wicej ni tylko sum intelektualnego wysiki,
zoonoci i bdw w stosunku do jej poszczeglnych skadowych funkcjonalnych.
Taka jednostka jest wiksza (zwykle niepotrzebnie) i trudniejsza do stosowania i ponownego wykorzystania. Zwykle te jednostka taka udostpnia okrojone interfejsy
kadego z zada okrojone z racji czciowego pokrywania si rnych obszarw
zadaniowych i rozmycia wizji implementacji kadego z nich.
Jednostki o czonych zadaniach s zwykle trudniejsze z punktu widzenia projektowego i implementacyjnego. Mnoga odpowiedzialno oznacza wtedy zazwyczaj
mnog osobowo kombinacyjn liczb rnych moliwych stanw i zachowa.
Dlatego zalecamy stosowanie prostych i jasnych, jednozadaniowych funkcji (patrz te
wytyczna 39.), prostych klas oraz moduw o cile ograniczonym zakresie zada.
Abstrakcje wyszego poziomu naley konstruowa z prostszych abstrakcji niszego
poziomu. Nie warto w adnym razie grupowa wielu abstrakcji niskiego poziomu
w wikszym i bardziej zoonym konglomeracie niskiego poziomu. Implementacja
zoonego zachowania na bazie szeregu prostszych jest bowiem atwiejsza ni implementacja odwrotna.
Przykady
Przykad 1. wywoanie . W standardowym jzyku C to jeden
z typowych przykadw uomnego projektu. Funkcja ma zdecydowanie za
duo zada: dla wskanika pustego przydziela pami, dla zerowego argumentu rozmiaru zwalnia wskazywan pami, za dla pozostaych wartoci argumentw zmienia
30
rozmiar przydzielonej pamici, przy czym nowy przydzia w czci pokrywa si w przestrzeni adresowej z poprzednim, a jeli jest to niemoliwe, wykonywany jest zupenie
nowy przydzia. Trudno o lepszy przykad wadliwego projektu funkcji.
Przykad 2.
. Klasa
to w standardzie jzyka C++
rwnie niesawny przykad monolitycznego projektu klasy. Klasa ta zostaa rozepchana
zbyt wielk liczb (nawet uytecznych i przyjemnych) dodatkw przez to, cho
aspiruje do miana kontenera, nie jest nim do koca, nie moe bowiem wybra pomidzy
indeksowaniem a iteracj i rwnoczenie powiela wiele standardowych algorytmw, nie
zostawiajc za to za wiele miejsca na rozszerzenia (patrz przykad do wytycznej 44.).
rda
[Henney02a] [Henney02b] [McConnell93] 10.5 [Stroustrup00] 3.8, 4.9.4,
23.4.3.1 [Sutter00] 10, 12, 19, 23 [Sutter02] 1 [Sutter04] 3740
31
Wytyczna 6.
Przede wszystkim poprawno,
prostota i przejrzysto
Wytyczna 6. Przede wszyst kim poprawno, pros tota i przejrzysto
Streszczenie
Wedle zasady KISS (Keep It Simple Software parafraza Keep It Simple, Stupid, czyli
jak najprociej, gupku) im prociej, tym lepiej. Proste jest niemal zawsze lepsze od
zoonego. Przejrzyste za jest lepsze od niejasnego. No i bezpieczne jest lepsze od
niebezpiecznego (patrz wytyczne 83. i 99.).
Uzasadnienie
Trudno przeceni znaczenie prostoty projektu i przejrzystoci kodu. Programista tworzcy kod czytelny i zrozumiay bdzie cieszy si wdzicznoci ze strony przyszego
opiekuna tego kodu. Powiniene przy tym pamita, e opiek nad kodem czsto sprawuj jego twrcy i, majc to na uwadze, dba o swoje samopoczucie w przyszoci.
Std klasyczne prawdy w rodzaju:
Programy musz by pisane tak, aby day si czyta przez ludzi, ewentualnie
od czasu do czasu wykonywa przez maszyny
Harold Abelson i Gerald Jay Sussman
32
Unikaj wic zaukw jzyka programowania i stosuj zawsze najprostsze z efektywnych technik.
Przykady
Przykad 1. unikaj zbdnego (cho efektownego) przeciania operatorw. Jedna
z (niepotrzebnie) udziwnionych bibliotek graficznego interfejsu uytkownika wymagaa, celem dodania do widgetu elementu sterujcego , napisania wyraenia
(zobacz wytyczn 26.).
Przykad 2. w roli parametrw konstruktorw stosuj zmienne nazwane, nie tymczasowe. Pozwala to na uniknicie niejednoznacznoci deklaracji. Pozwala te na lepsz
prezentacj zadania realizowanego przez kod i tym samym uproszczenie konserwacji
programu. Jest te niejednokrotnie bezpieczniejsze (zobacz wytyczne 13. i 31.).
rda
[Abelson96] [Bentley00] 4 [Cargill92] pp.9193 [Cline99] 3.0506 [Constantine95] 29 [Keffer95] p. 17 [Lakos96] 9.1, 10.2.4 [McConnell93] [Meyers01] 47 [Stroustrup00] 1.7, 2.1, 6.2.3, 23.4.2, 23.4.3.2 [Sutter00] 4041,
46 [Sutter04] 29
33
Wytyczna 7.
Jak i kiedy kodowa
z uwzgldnieniem skalowalnoci
Wytyczna 7. Jak i kiedy kodowa z uw zg ldnieniem s kalowalno ci
Streszczenie
Wystrzegaj si wybuchowego rozrostu kodu unikajc przedwczesnej optymalizacji,
kontroluj rwnoczenie zoono asymptotyczn kodu. Algorytmy dziaajce na danych
uytkownika powinny cechowa si liniow zoonoci, czyli liniowym przyrostem
czasu wykonania przy przyrocie iloci przetwarzanych danych. Tam, gdzie optymalizacja okae si niezbdna, i zwaszcza gdy zostanie wymuszona zwikszeniem iloci
danych, skupiaj si raczej na uzyskaniu sensownej zoonoci obliczeniowej algorytmu
ni na urywaniu tu i wdzie po jednej instrukcji maszynowej.
Uzasadnienie
Niniejsza wytyczna ilustruje punkt rwnowagi pomidzy wytycznymi 8. i 9. (unikaj
przedwczesnej optymalizacji i unikaj przedwczesnej pesymizacji). Z tego wzgldu t
wytyczn do ciko sformuowa tak, aby nie myli jej sensu z sensem wytycznej 8.
Ale do rzeczy.
Oto to zagadnienia: pojemnoci pamici ulotnych i dyskw twardych rosn wykadniczo; w latach od 1988 do 2004 pojemno dyskw rosa o 112 procent rocznie (co
daje w cigu dekady wzrost blisko 1900-krotny), podczas gdy prawo Moorea zakada
przyrost zaledwie 59-procentowy (100-krotny w cigu dekady). Jedn z konsekwencji
tej dynamiki jest to, e czynnoci realizowane dzi przez kod mog jutro obejmowa
znacznie wiksze iloci danych znacznie wiksze. Jeli stosowane do ich przetwarzania algorytmy bd cechowa si kiepsk asymptotyczn zoonoci obliczeniow,
wczeniej czy pniej przestan si nadawa do wykorzystywania nawet na najwydajniejszych systemach komputerowych to tylko kwestia iloci danych, ktrymi te
algorytmy bd karmione.
Obrona przed t wtpliw karier algorytmu polega na unikaniu wbudowywania
w projekt takich elementw, ktre w obliczu koniecznoci przetwarzania plikw
wikszych ni dzi przewidywane (wikszych baz danych, wikszej liczby pikseli,
wikszej liczby okien, wikszych szybkoci transmisji) oka si jego wskimi gardami.
W przypadku biblioteki standardowej jzyka C++ elementami zabezpieczajcymi
przyszo s choby gwarancje co do zoonoci obliczeniowej algorytmw i operacji na kontenerach.
Oto wniosek: nie powinnimy przedwczenie optymalizowa programu przez zastosowanie w nim mniej przejrzystego algorytmu, jeli spodziewany przyrost iloci przetwarzanych danych nie jest pewny. Ale rwnie niewskazana jest przedwczesna pesymizacja
34
35
rda
[Bentley00] 6, 8, dod. A [Cormen01] [Kernighan99] 7 [Knuth97a] [Knuth97b]
[Knuth98] [McConnell93] 5.14, 10.6 [Murray93] 9.11 [Sedgewick98]
[Stroustrup00] 17.1.2
36
Wytyczna 8.
Wystrzegaj si
przedwczesnej optymalizacji
Wytyczna 8. Wystrzegaj si przedwczesnej optymalizacji
Streszczenie
Nie bodzie si chtnego wierzchowca. Przedwczesna optymalizacja jest rwnie uzaleniajca, jak bezproduktywna, pierwsza regua optymalizacji mwi bowiem: zaniechaj
jej. Druga regua (dla ekspertw) mwi za: powstrzymaj si jeszcze. Jedn optymalizacj trzeba poprzedzi dwoma pomiarami dowodzcymi jej koniecznoci.
Uzasadnienie
We wstpie do [Stroustrup00] 6 znajdziemy wietne cytaty:
Przedwczesna optymalizacja to rdo wszelkiego za
Donald Knuth (cytujcy z kolei z Hoarea)
Hoare i Knuth maj (jak zwykle) racj (patrz wytyczna 6. i niniejsza). Tak jak i Bentley
(wytyczna 9.).
Przedwczesn optymalizacj zdefiniowalibymy jako zwikszanie zoonoci projektu
albo kodu, a przez to zmniejszenie ich czytelnoci, w imi wydajnoci, ktrej potrzeba
zwikszenia nie zostaa jeszcze dowiedziona (na przykad pomiarami i porwnaniem
ich wynikw z zaoonymi celami) jako taka optymalizacja ta nie wnosi do projektu
adnych korzyci. Czsto przedwczesna i niepoparta pomiarami optymalizacja, mimo
woonego w ni wysiku, nie daje dosownie adnego efektu wydajnociowego.
Warto wic zapamita, e:
Znacznie atwiej przyspieszy poprawny program, ni poprawi szybki!
Nie naley wic od pocztku skupia si na szybkoci kodu w pierwszej kolejnoci
powinna nas interesowa raczej jego przejrzysto i czytelno (zgodnie z wytyczn 6.).
W kodzie czytelnym atwiej o poprawno, zrozumienie jego dziaania, wprowadzanie
poprawek i zmian, i wreszcie optymalizacj. Komplikacje, nieodzowne dla optymalizacji,
zawsze mona wprowadzi pniej i tylko wtedy, gdy s niezbdne.
Przedwczesna optymalizacja czsto nie daje spodziewanych efektw z dwch gwnych
powodw. Po pierwsze, programici stale myl si w swoich szacunkach co do szybkoci
danego kodu i typowania jego wskich garde. Dotyczy to nas, autorw tej ksiki,
i dotyczy najprawdopodobniej rwnie Ciebie. Wspczesne komputery realizuj
37
Przykady
Przykad ironia . Oto ilustracja ukrytego kosztu przedwczesnej mikrooptymalizacji. Ot narzdzia profilujce su do tego, aby na podstawie licznika wywoa
funkcji informowa programist o tym, ktre z funkcji nadaj si do rozwijania w miejscu
38
wywoania, a nie zostay jako takie oznaczone. Niestety, nawet najlepsze takie narzdzie
nie bdzie w stanie wskaza takich funkcji, ktre zostay oznaczone jako rozwijane
w miejscu wywoania (), cho nie powinny nie bdzie bowiem adnej moliwoci okrelenia liczby wywoa teje funkcji w kodzie wynikowym. Zbyt czsto
programici w imi optymalizacji decyduj si na rozwijanie wielu funkcji w miejscu
wywoania, co mao kiedy przynosi rzeczywiste korzyci (zakadajc, e kompilator
nie ignoruje zupenie sowa patrz [Sutter00], [Sutter02] czy [Sutter04]).
Wyjtki
Twrca kodu biblioteki ma zadanie utrudnione o tyle, e nie bardzo moe przewidzie, ktre z jej elementw bd w przyszoci wykorzystywane w kodzie czuym na
wydajno wykonania. Ale nawet twrcy bibliotek powinni poprzedzi optymalizacj
testami na szerokiej bazie klientw-uytkownikw biblioteki.
rda
[Bentley00] 6 [Cline99] 13.0109 [Kernighan99] 7 [Lakos96] 9.1.14
[Meyers97] 33 [Murray93] 9.910, 9.3 [Stroustrup00] 6 (wprowadzenie)
[Sutter00] 30, 46 [Sutter02] 12 [Sutter04] 25
39
Wytyczna 9.
Wystrzegaj si
przedwczesnej pesymizacji
Wytyczna 9. Wystrzegaj si przedwczesnej pesymizacji
Streszczenie
Jeli pozostae czynniki (jak choby czytelno kodu czy jego zoono) nie ucierpi
na tym, to pewne wzorce projektowe, praktyki programistyczne i tym podobne idiomy programistyczne naley uzna za o tyle naturalne, e ich wprowadzenie nie wie
si dla programisty ze zwikszonym wysikiem i niejako same wychodz spod jego
palcw. Nie uznajemy ich za przedwczesn optymalizacj, a raczej za unikanie niepotrzebnej pesymizacji.
Uzasadnienie
Unikanie przedwczesnej pesymizacji nie moe oznacza wzrostu efektywnoci, jeli
osiga si go znacznym kosztem. Przedwczesn pesymizacj bdziemy rozumie jako
niepotrzebne potencjalne ograniczenia efektywnoci, takie jak:
definiowanie parametrw jako przekazywanych przez warto tam,
40
rda
[Keffer95] pp. 1213 [Stroustrup00] 6 (wprowadzenie) [Sutter00] 6
41
Wytyczna 10.
Minimalizuj ilo danych globalnych
i wspuytkowanych
Wytyczna 10. Min imalizuj ilo danych globalnych i wspu yt kowanych
Streszczenie
Wspuytkowanie oznacza rywalizacj naley wic unika danych wsplnych,
zwaszcza globalnych. Zwikszaj one powizanie kodu kosztem atwoci konserwacji,
a niejednokrotnie i wydajnoci.
Uzasadnienie
Niniejsza wytyczna jest pewnym uoglnieniem wytycznej 18.
Chodzi o unikanie stosowania danych (wizanych zewntrznie) o zasigu pokrywajcym si z zasigiem przestrzeni nazw albo wystpujcych w postaci statycznych skadowych klas. Komplikuj one logik programu i ucilaj zwizki pomidzy rnymi
(i, co gorsza, odlegymi) elementami programu. Wspuytkowanie danych zmniejsza
moliwoci testowania jednostki programu, poniewa poprawno kodu odwoujcego
si do takich danych jest mocno uzaleniona od historii zmian tych danych i warunkw
wykonania dalszego, nieznanego bliej kodu, ktry si pniej do tych danych odwouje.
Nazwy obiektw w globalnej przestrzeni nazw zamiecaj t przestrze, zwikszajc
ryzyko kolizji nazw.
Jeli ju trzeba zastosowa obiekt globalny, obiekt o zasigu pokrywajcym si z zasigiem przestrzeni nazw albo statyczny obiekt klasy, naley starannie go zainicjalizowa. Porzdek inicjalizacji tego rodzaju obiektw w rnych jednostkach kompilacji
jest niezdefiniowany i aby zapewni jego poprawno, trzeba wdroy specjalne techniki
(odsyamy do rde). Reguy kolejnoci inicjalizacji s subtelne lepiej unika koniecznoci zagbiania si w te subtelnoci, a jeli jest to niemoliwe, warto je przynajmniej
dobrze pozna i starannie stosowa.
Obiekty o zasigu przestrzeni nazw, skadowe statyczne oraz obiekty dzielone przez
wiele wtkw albo procesw redukuj zrwnoleglenie w rodowiskach wielowtkowych
i wieloprocesorowych i s czstymi wskimi gardami wydajnoci i skalowalnoci
(patrz wytyczna 7.). Optuj za zasad jak najmniej wsplnego zamiast danych
wsplnych (wspuytkowanych) stosuj komunikacj pomidzy uytkownikami danych
(np. kolejki komunikatw).
Cao sprowadza si za do unikania cisych zalenoci i do minimalizacji interakcji
pomidzy klasami (patrz [Cargill92]).
42
Wyjtki
Za wyjtki mona uzna takie mechanizmy, jak obiekty ,
i , implementowane celowo jako obiekty globalne. Dalej, np. fabryka (generator obiektw wedug
wzorca projektowego Factory) musi utrzymywa rejestr funkcji do wywoania celem
utworzenia obiektu danego typu i zwykle w programie znajduje si jeden taki rejestr
(powinien by on jednak obiektem wewntrznym fabryki, a nie wspuytkowanym
obiektem globalnym; patrz wytyczna 11.).
Kod zakadajcy wspuytkowanie obiektw przez wiele wtkw powinien zawsze szeregowa wszelkie odwoania do owych obiektw (patrz wytyczna 12. oraz [Sutter04c]).
rda
[Cargill92] pp.126136, 169173 [Dewhurst03] 3 [Lakos96] 2.3.1 [McConnell93] 5.14 [Stroustrup00] C.10.1 [Sutter00] 47 [Sutter02] 16, dod. A
[Sutter04c] [SuttHysl03]
43
Wytyczna 11.
Ukrywaj informacje
Wytyczna 11. U krywaj informacje
Streszczenie
Nie eksponuj wewntrznych informacji jednostki stanowicej abstrakcj.
Uzasadnienie
Minimalizacja zalenoci pomidzy wywoujcym, manipulujcym pewn abstrakcj,
a wywoywanym, czyli implementacj tej abstrakcji, wymaga ukrywania danych wewntrznych tej implementacji. W przeciwnym razie wywoujcy moe si do owych
informacji odwoywa (albo, co gorsza, manipulowa nimi) z pominiciem implementacji abstrakcji. Eksponowa naley raczej sam abstrakcj (nawet, jeli ma ona jedynie
posta akcesorw
-
), a nie jej dane.
Ukrywanie informacji zmniejsza koszt projektu, skraca harmonogram realizacji lub
(i) ryzyko jego przekroczenia, dziki:
ograniczaniu zasigu zmian ukrywanie informacji redukuje efekt domina
44
Wyjtki
Wyjtkiem moe by kod testujcy, niejednokrotnie wymagajcy swobodnego dostpu
do danych testowanych klas i moduw.
Regule ukrywania danych nie podlegaj rwnie agregaty wartoci (np. znane z jzyka C
struktury), stanowice jedynie zlepek danych, dla ktrych nie przewidziano abstrakcji
behawioralnej dane te stanowi wtedy rwnoczenie swj wasny (jedyny) interfejs
(zobacz wytyczna 41.).
rda
[Brooks95] 19 [McConnel] 6.2 [Parnas02] [Stroustrup00] 24.4 [SuttHysl04a]
45
Wytyczna 12.
Niepotrzebna rywalizacja
to niezdrowa rywalizacja
Wytyczna 12. Niepotr zebna rywalizacja to niezdrowa rywalizacja
Streszczenie
Bezpieczestwo wtkowe to podstawa jeli aplikacja wykorzystuje wiele wtkw
czy procesw, programista musi wiedzie, jak ma minimalizowa wspuytkowanie
obiektw (zobacz wytyczna 10.) i jak bezpiecznie uytkowa te, ktre musz pozosta
wsplne.
Uzasadnienie
Wtki to obszerne zagadnienie. Jego waga wymaga potwierdzenia w wydzieleniu dla
niego osobnej wytycznej. W ramach jednej takiej wytycznej nie sposb jednak uj
wszystkiego, co zwizane z programowaniem wtkw, ograniczymy si wic do podsumowania kilku kwestii zasadniczych po szczegy odsyamy za do rde. Za
kwestie najwaniejsze uwaamy za unikanie zakleszcze, unikanie zawaszczania
zasobw i unikanie szkodliwej rywalizacji w dostpie do zasobw (i ich uszkodzenia
w wyniku niewystarczajcego blokowania).
Standard jzyka C++ nie powica wtkom ani sowa. Mimo tego jzyk ten jest rutynowo i powszechnie wykorzystywany do pisania solidnych, wielowtkowych aplikacji.
Jeli wic Twj program dzieli dane pomidzy wtki, niech robi to bezpiecznie:
Sprawd w dokumentacji platformy docelowej dostpno elementarnych
46
47
48
Twrca biblioteki przeznaczonej do powszechnego uytku powinien szczeglnie rozway zabezpieczenie obiektw biblioteki przed interakcjami w rodowisku wielowtkowym. Powinien do tego podej w sposb opisany powyej, ale tak, aby zabezpieczenia
te nie powodoway znacznych narzutw w rodowiskach wielowtkowych. Jeli na
przykad piszesz bibliotek zawierajc typ stosujcy kopiowanie przy zapisie i z tego
wzgldu wykorzystujcy rwnie jakie wewntrzne blokady, blokady te naley tak
zaaranowa, aby w kompilacjach dla rodowisk jednowtkowych byy niewidoczne
(mona uciec si wtedy do dyrektyw i pustych implementacji).
Zakadajc wiele blokad, powiniene unika zakleszcze i ukada kod tak, aby we
wszystkich miejscach pozyskiwania tego kompletu blokad kolejno ich zakadania
bya zawsze taka sama (zwalnianie blokad moe by wtedy realizowane w dowolnym
porzdku). Rozwizaniem problemu staej kolejnoci zakadania blokad moe by ich
zakadanie wedug rosncych adresw w pamici bazujc na adresach, moesz atwo
ustali porzdek blokowania wsplny dla caej aplikacji.
rda
[Alexandrescu02a] [Alexandrescu04] [Butenhof97] [Henney00] [Henney01]
[Meyers04] [Shmidt01] [Stroustrup] 14.9 [Sutter02] 16 [Sutter04c]
Wytyczna 13. Zagwarantuj opiek nad zasobami przez obiekty. Stosuj RAII
49
Wytyczna 13.
Zagwarantuj opiek nad zasobami
przez obiekty. Stosuj RAII
i inteligentne wskaniki
Wytyczna 13. Zagwarantuj opiek nad za sobami przez obie kty. S tosuj RAII
Streszczenie
Nie walaj rk, jeli masz narzdzia idiom pozyskanie zasobu to jego inicjalizacja
(RAII, od resource acquisition is initialization) to wietne narzdzie poprawnej obsugi
zasobw. RAII pozwala kompilatorowi na udostpnianie silnych i automatycznych
gwarancji, ktre w innych jzykach wymagaj karkoomnych sztuczek programistycznych. Przydzielajc surowy zasb, bezzwocznie przeka go do obiektu, ktry ma by
jego dysponentem. I nigdy nie przydzielaj wicej ni jednego zasobu w pojedynczej
instrukcji.
Uzasadnienie
Jzyk C++, wymuszajcy symetri wywoa konstruktorw i destruktorw, odwzorowuje w niej symetri charakterystyczn dla par funkcji pozyskujcych i zwalniajcych
obiekty, takich jak i
, i czy operatorw i .
Dziki temu przydzielany w pamici stosu (albo implementowany ze zliczaniem odwoa) obiekt z pozyskujcym zasoby konstruktorem i zwalniajcym je destruktorem
jest znakomitym narzdziem automatyzacji zarzdzania zasobami.
Automatyzacja ta jest prosta w implementacji, elegancka, mao kosztowna i w swej
istocie odporna na bdy. Jej odrzucenie oznacza obcienie samego siebie niebanalnym
i angaujcym zadaniem rcznego parowania wywoa pozyskujcych i zwalniajcych
zasoby, z uwzgldnieniem wyjtkw i wynikajcych z logiki programu rozgazie
przepywu sterowania. Tego rodzaju przywizanie do jzyka C i charakterystycznego
dla niego mikrozarzdzania operacjami zwalniania zasobw jest nie do zaakceptowania
w jzyku C++, w ktrym owe czynnoci s automatyzowane za porednictwem RAII.
Gdy mamy do czynienia z zasobem wymagajcym parowania wywoa funkcji pozyskujcych i zwalniajcych, powinnimy w zasb hermetyzowa w obiekcie, skadajc
zadanie zwalniania zasobu na barki jego destruktora. Na przykad w miejsce wywoa
pary funkcji !"
i #
"
wypadaoby rozway takie rozwizanie:
!
"
50
&!
'
%!
!"#$(()%
!
%!
* '
+
Powyszy kod nie jest bezpieczny. Standard jzyka C++ daje twrcom kompilatorw
znaczn swobod w zakresie porzdkowania wyrae reprezentujcych argumenty
wywoania funkcji. W szczeglnoci kompilator moe przeplata obliczanie obu wyrae i najpierw wykona przydzia pamici dla obu obiektw (operatorem ), a potem
dopiero wywoa (w dowolnej kolejnoci) konstruktory obiektw klasy $
. W takim
ukadzie bardzo atwo o wyciek pamici, poniewa jeli jeden z konstruktorw zgosi
wyjtek, to pami drugiego z obiektw nie zostanie nigdy zwolniona (po szczegy
odsyamy do [Sutter02])!
Ten subtelny problem ma proste rozwizanie: wystarczy pilnowa, aby w pojedynczej
instrukcji nie przydziela wicej ni jednego zasobu, a kady przydzia realizowa
jawnie, z natychmiastowym przekazaniem zasobu do obiektu-dysponenta (np. wskanika
). Jak tutaj:
Wytyczna 13. Zagwarantuj opiek nad zasobami przez obiekty. Stosuj RAII
51
'
(
'
%&(
Wyjtki
atwo o naduycie inteligentnych wskanikw. Zwyke wskaniki wietnie sprawdzaj
si w kodzie, w ktrym wskazywane zasoby s widoczne jedynie w ograniczonym fragmencie kodu (np. wycznie wewntrz klasy, jak w przypadku wewntrznych wskanikw nawigacji wrd wzw w klasie %).
rda
[Alexandrescu00c] [Cline99] 31.0305 [Dewhurst03] 24, 67 [Meyers96]
910 [Milewski01] [Stroustrup00] 14.34, 25.7, E.3, E.6 [Sutter00] 16
[Sutter02] 2021 [Vandervoorde03] 20.1.4