Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00363 005518 13259048 na godz. na dobę w sumie
Debugowanie. Jak wyszukiwać i naprawiać błędy w kodzie oraz im zapobiegać - książka
Debugowanie. Jak wyszukiwać i naprawiać błędy w kodzie oraz im zapobiegać - książka
Autor: Liczba stron: 240
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-2760-8 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> techniki programowania
Porównaj ceny (książka, ebook, audiobook).

Mistrz debugowania w akcji!

Zapewne niejednokrotnie podczas pracy przy komputerze musiałeś użerać się z wadliwymi aplikacjami. Doskonale wiesz, jak to jest, kiedy kolejne łatki usuwają stare błędy, równocześnie generując nowe, programiści zaś nie kwapią się do zmiany niewłaściwych założeń. A przecież jednym z najbardziej niedocenianych aspektów profesjonalnego programowania jest zdolność do rozpoznawania i usuwania błędów kryjących się w każdej większej partii stworzonego kodu. Jeśli tworzysz niebanalne aplikacje, najprawdopodobniej zajmiesz się ich debugowaniem chwilę po zakończeniu ich pisania. To zajęcie w zdecydowanie większym stopniu niż inne aspekty tworzenia oprogramowania jest działalnością intelektualną - ponieważ jego areną jest umysł programisty. Znajdowanie i wyjaśnianie przyczyn problemów powinno być pierwszą czynnością na drodze do ich zwalczania.

Ta książka poświęcona jest właśnie arkanom sztuki debugowania. Jej lektura pozwoli Ci znacznie ograniczyć liczbę popełnianych błędów, a te, które się pojawią, będą łatwiejsze do wykrycia i usunięcia. Podręcznik wyjaśni Ci, jak pisać kod, który łatwo debugować, przeprowadzi Cię przez proces wykrywania błędów, ich reprodukcji, diagnozowania, aż do wprowadzania i wycofywania poprawek w oprogramowaniu. Poznaj empiryczną metodę wykrywania błędów. Dowiedz się, jak ważne jest zapewnienie sobie pewnych sposobów reprodukowania błędnych zachowań. Naucz się unikać pułapek czyhających zarówno na programistów, jak i testerów. Stosuj powszechnie używane narzędzia i metody zapewniające automatyczne wykrywanie potencjalnych przyczyn problemów, zanim jeszcze się one pojawią! Naucz się tworzyć samodebugujące oprogramowanie, które automatycznie informuje o swoim stanie, a także sprawdź, co możesz zrobić, aby szybko wykrywać sytuacje będące potencjalną przyczyną problemów.

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Idź do • Spis treści • Przykładowy rozdział Katalog książek • Katalog online • Zamów drukowany katalog Twój koszyk • Dodaj do koszyka Cennik i informacje • Zamów informacje o nowościach • Zamów cennik Czytelnia • Fragmenty książek online Debugowanie. Jak wyszukiwaæ i naprawiaæ b³êdy w kodzie oraz im zapobiegaæ Autor: Paul Butcher T³umaczenie: Andrzej Gra¿yñski ISBN: 978-83-246-2760-8 Tytu³ orygina³u: Debug It!: Find, Repair, and Prevent Bugs in Your Code Format: 158235, stron: 240 Mistrz debugowania w akcji! • Jak tworzyæ oprogramowanie, które ³atwo siê debuguje? • Jak wykrywaæ potencjalne przyczyny problemów? • Jak omin¹æ pu³apki czyhaj¹ce na programistów? Zapewne niejednokrotnie podczas pracy przy komputerze musia³eœ u¿eraæ siê z wadliwymi aplikacjami. Doskonale wiesz, jak to jest, kiedy kolejne ³atki usuwaj¹ stare b³êdy, równoczeœnie generuj¹c nowe, programiœci zaœ nie kwapi¹ siê do zmiany niew³aœciwych za³o¿eñ. A przecie¿ jednym z najbardziej niedocenianych aspektów profesjonalnego programowania jest zdolnoœæ do rozpoznawania i usuwania b³êdów kryj¹cych siê w ka¿dej wiêkszej partii stworzonego kodu. Jeœli tworzysz niebanalne aplikacje, najprawdopodobniej zajmiesz siê ich debugowaniem chwilê po zakoñczeniu ich pisania. To zajêcie w zdecydowanie wiêkszym stopniu ni¿ inne aspekty tworzenia oprogramowania jest dzia³alnoœci¹ intelektualn¹ – poniewa¿ jego aren¹ jest umys³ programisty. Znajdowanie i wyjaœnianie przyczyn problemów powinno byæ pierwsz¹ czynnoœci¹ na drodze do ich zwalczania. Ta ksi¹¿ka poœwiêcona jest w³aœnie arkanom sztuki debugowania. Jej lektura pozwoli Ci znacznie ograniczyæ liczbê pope³nianych b³êdów, a te, które siê pojawi¹, bêd¹ ³atwiejsze do wykrycia i usuniêcia. Podrêcznik wyjaœni Ci, jak pisaæ kod, który ³atwo debugowaæ, przeprowadzi Ciê przez proces wykrywania b³êdów, ich reprodukcji, diagnozowania, a¿ do wprowadzania i wycofywania poprawek w oprogramowaniu. Poznaj empiryczn¹ metodê wykrywania b³êdów. Dowiedz siê, jak wa¿ne jest zapewnienie sobie pewnych sposobów reprodukowania b³êdnych zachowañ. Naucz siê unikaæ pu³apek czyhaj¹cych zarówno na programistów, jak i testerów. Stosuj powszechnie u¿ywane narzêdzia i metody zapewniaj¹ce automatyczne wykrywanie potencjalnych przyczyn problemów, zanim jeszcze siê one pojawi¹! Naucz siê tworzyæ samodebuguj¹ce oprogramowanie, które automatycznie informuje o swoim stanie, a tak¿e sprawdŸ, co mo¿esz zrobiæ, aby szybko wykrywaæ sytuacje bêd¹ce potencjaln¹ przyczyn¹ problemów. Kontakt Helion SA ul. Kościuszki 1c 44-100 Gliwice tel. 32 230 98 63 e-mail: helion@helion.pl © Helion 1991–2010 • Metoda empiryczna • Reprodukcja b³êdów • Diagnozowanie • Wyszukiwanie b³êdów • Wprowadzanie i wycofywanie poprawek • Testowanie • Przyczyny b³êdów • Oprogramowanie samodebuguj¹ce • Narzêdzia wspomagaj¹ce Spis treĂci Od tïumacza sïów kilka .................................................................................... 9 Przedmowa ...................................................................................................... 13 CzÚĂÊ I. Istota problemu Rozdziaï 1. W tym szaleñstwie jest metoda ................................................ 19 1.1. Debugowanie to coĂ wiÚcej niĝ eksterminacja bïÚdów ................................................ 20 1.2. Metoda empiryczna ................................................................................................ 22 1.3. Struktura procesu debugowania .............................................................................. 23 1.4. Przede wszystkim rzeczy najwaĝniejsze .................................................................... 24 1.5. Do dzieïa! ............................................................................................................. 28 Rozdziaï 2. Reprodukcja ................................................................................. 29 2.1. Najpierw reprodukcja, potem pytania ...................................................................... 29 2.2. Kontrolowane zachowanie aplikacji ......................................................................... 32 2.3. Kontrolowane Ărodowisko ....................................................................................... 32 2.4. Kontrolowane dane wejĂciowe ................................................................................. 34 2.5. Ulepszanie reprodukcji ........................................................................................... 43 2.6. Gdy bïÈd nie chce siÚ ujawniÊ ................................................................................. 52 2.7. Podsumowanie ...................................................................................................... 55 Rozdziaï 3. Diagnoza ....................................................................................... 57 3.1. Gdy debugowanie staje siÚ naukÈ ............................................................................ 57 3.2. Sztuczki i chwyty .................................................................................................... 63 3.3. Debuggery ............................................................................................................. 70 6  Debugowanie 3.4. Puïapki ................................................................................................................. 71 3.5. Gry umysïowe ........................................................................................................ 76 3.6. Zweryfikuj swojÈ diagnozÚ ...................................................................................... 80 3.7. Podsumowanie ...................................................................................................... 81 Rozdziaï 4. Poprawki ...................................................................................... 83 4.1. Czysta tablica ........................................................................................................ 84 4.2. Testowanie ............................................................................................................ 85 4.3. Eliminowanie przyczyn, nie objawów ....................................................................... 87 4.4. Refaktoryzacja ....................................................................................................... 89 4.5. Kontrola wersji ...................................................................................................... 91 4.6. Inspekcja kodu ....................................................................................................... 92 4.7. Podsumowanie ...................................................................................................... 93 Rozdziaï 5. Refleksja ....................................................................................... 95 5.1. Jak to w ogóle mogïo dziaïaÊ? ................................................................................. 95 5.2. Co poszïo nie tak? .................................................................................................. 97 5.3. Nigdy wiÚcej tego samego bïÚdu .............................................................................. 99 5.4. Zamykanie pÚtli ................................................................................................... 102 5.5. Podsumowanie .................................................................................................... 102 CzÚĂÊ II. Szersza perspektywa Rozdziaï 6. Chyba mamy problem… ........................................................... 105 6.1. Tropienie bïÚdów ................................................................................................. 106 6.2. Wspóïpraca z uĝytkownikami ................................................................................ 109 6.3. Wspóïdziaïanie z innymi zespoïami ....................................................................... 116 6.4. Podsumowanie .................................................................................................... 117 Rozdziaï 7. Pragmatyczna nietolerancja .................................................... 119 7.1. BïÚdy majÈ pierwszeñstwo .................................................................................... 119 7.2. Debugowanie a psychologia .................................................................................. 122 7.3. Zasypywanie przepaĂci jakoĂciowej ....................................................................... 125 7.4. Podsumowanie .................................................................................................... 129 CzÚĂÊ III. Debug-Fu Rozdziaï 8. Przypadki szczególne ................................................................ 133 8.1. ’atanie istniejÈcego oprogramowania .................................................................... 133 8.2. KompatybilnoĂÊ wersji .......................................................................................... 134 8.3. WspóïbieĝnoĂÊ ..................................................................................................... 139 Spis treĂci  7 8.4. BïÚdy heisenbergowskie ........................................................................................ 142 8.5. Problemy z wydajnoĂciÈ ....................................................................................... 144 8.6. Systemy osadzone ................................................................................................ 147 8.7. BïÚdy w obcym oprogramowaniu ........................................................................... 150 8.8. Podsumowanie .................................................................................................... 154 Rozdziaï 9. Idealne Ărodowisko debugowania .......................................... 155 9.1. Automatyczne testowanie ..................................................................................... 155 9.2. Kontrola wersji .................................................................................................... 158 9.3. Automatyczne budowanie binariów ....................................................................... 163 9.4. Podsumowanie .................................................................................................... 171 Rozdziaï 10. Naucz swe oprogramowanie samodebugowania ................ 173 10.1. Zaïoĝenia i asercje ............................................................................................. 174 10.2. Binaria debugowalne .......................................................................................... 184 10.3. Wycieki zasobów i bïÚdna obsïuga wyjÈtków ........................................................ 189 10.4. Podsumowanie .................................................................................................. 195 Rozdziaï 11. Antywzorce .............................................................................. 197 11.1. Inflacja priorytetów ............................................................................................. 197 11.2. Primadonna ....................................................................................................... 198 11.3. Zespóï serwisowy ............................................................................................... 200 11.4. Gaszenie poĝaru ................................................................................................ 202 11.5. Pisanie od nowa ................................................................................................. 203 11.6. Bezpañski kod ................................................................................................... 205 11.7. Czarna magia .................................................................................................... 206 11.8. Podsumowanie .................................................................................................. 207 Dodatki Dodatek A Materiaïy .................................................................................... 211 A.1. Systemy kontroli wersji i Ăledzenia problemów ....................................................... 211 A.2. NarzÚdzia zarzÈdzania generowaniem binariów i integracjÈ ciÈgïÈ .......................... 215 A.3. Przydatne biblioteki ............................................................................................ 216 A.4. Inne narzÚdzia .................................................................................................... 218 Skorowidz ...................................................................................................... 223 Rozdziaï 1. • W tym szaleñstwie jest metoda  19 Rozdziaï 1. W tym szaleñstwie jest metoda T ego moĝna siÚ byïo spodziewaÊ: stworzony program nie chce dziaïaÊ, a jeĝeli juĝ dziaïa, to w sposób dziwaczny. I co teraz?! NiewÈtpliwie poĝyteczny okazuje siÚ wówczas nawyk systematycznoĂci, czyli dÈĝenie do znalezienia prawdziwej przyczyny (przyczyn) tak dziwacznego zachowania (starannie przecieĝ napisanego) programu, wielu programistów jednak zdaje siÚ wykazywaÊ objawy chaotycznego — by nie rzec rozpaczliwego — miotania siÚ po kodzie programu, bez wyraěnego celu i (co zrozumiaïe) bez widocznych rezultatów. Cóĝ jednak odróĝnia obie te grupy od siebie? W tym rozdziale przyjrzymy siÚ dokïadnie metodom debugowania kodu, sprawdzo- nym w warunkach profesjonalnego wytwarzania oprogramowania. Nie da siÚ ich, co prawda, porównaÊ do kamienia filozoficznego, zamieniajÈcego powszedniÈ materiÚ — czyli owoc niedoskonaïych dziaïañ omylnych programistów — w zïoto, czyli kod dziaïajÈcy niezawodnie i bezbïÚdnie; w dalszym ciÈgu nieocenione okazujÈ siÚ okre- Ălone kwalifikacje programisty czy testera — wiedza, doĂwiadczenie, intuicja, zdolno- Ăci detektywistyczne, no i — oczywiĂcie — odrobina szczÚĂcia. Metody te umoĝliwiajÈ odpowiednie ukierunkowanie zainwestowanego wysiïku, pozwalajÈ uniknÈÊ bezsen- sownego drÈĝenia rozmaitych hipotez, a w konsekwencji otwierajÈ drogÚ — moĝliwie krótkÈ — dotarcia do prawdziwej przyczyny problemu. Poznamy kilka konkretnych koncepcji, skïadajÈcych siÚ na wspomnianÈ metodologiÚ, m.in.:  róĝnicÚ miÚdzy „debugowaniem” a „usuwaniem bïÚdów”,  podejĂcie empiryczne, czyli niech oprogramowanie samo zademonstruje, co siÚ z nim dzieje, 20  CzÚĂÊ I • Istota problemu  podstawowe elementy procesu debugowania — reprodukowanie bïÚdów, diagnozowanie ich przyczyny, poprawianie kodu i wyciÈganie wniosków na przyszïoĂÊ,  koniecznoĂÊ dokïadnego rozumienia sensu podejmowanych dziaïañ. 1.1. Debugowanie to coĂ wiÚcej niĝ eksterminacja bïÚdów Spytajcie niedoĂwiadczonego programistÚ, co oznacza termin „debugowanie”, a usïy- szycie, ĝe jest to „znajdowanie bïÚdów” czy innÈ podobnÈ odpowiedě. OczywiĂcie, eliminowanie bïÚdów jest jednym z elementów debugowania, nie jest to jednak element jedyny ani nawet najwaĝniejszy. Efektywne debugowanie ukierunkowane jest pod kÈtem istotnych celów. Oto one. 1. Znalezienie przyczyny nieoczekiwanego zachowania programu. 2. Wyeliminowanie tej przyczyny. 3. Zapobieganie sytuacjom, w których wyeliminowanie jednej przyczyny jednej grupy bïÚdów staje siÚ kolejnÈ przyczynÈ innych bïÚdów. 4. Utrzymanie (a nawet ulepszenie) ogólnej jakoĂci kodu — jego czytelnoĂci, przejrzystoĂci, stopnia pokrycia przypadkami testowymi, wydajnoĂci, ïatwoĂci konserwacji i rozbudowy itp. 5. Upewnienie siÚ, ĝe okreĂlony problem zostaï caïkowicie wyeliminowany z kodu programu i nie da znaÊ o sobie nigdy wiÚcej. Nieprzypadkowo najwaĝniejszy okazuje siÚ pierwszy z wymienionych celów — od prawidïowego rozpoznania rzeczywistej przyczyny problemu uzaleĝnione jest po- wodzenie pozostaïych dziaïañ. Przede wszystkim — zrozumieÊ PoczÈtkujÈcy, niedoĂwiadczeni programiĂci (i, niestety, wielu uwaĝajÈcych siÚ za doĂwiadczonych) czÚsto zaniedbujÈ rozpoznanie problemu „u ěródïa”, ograniczajÈc siÚ do dokonywania doraěnych poprawek, które powinny przywróciÊ1 poprawne 1 Nie moĝna, oczywiĂcie, przywróciÊ czegoĂ, czego nigdy nie byïo, szczególnie nie moĝna przywróciÊ poprawnego dziaïania programu, który nigdy poprawnie nie dziaïaï. To prawda, nie zapominajmy jednak, ĝe kaĝdy tworzony przez nas program funkcjonuje poprawnie w naszych oczekiwaniach, w naszej wyobraěni (a bywa i tak, ĝe faktycznie okazuje siÚ od razu bezbïÚdny — najbardziej odpowiednim pytaniem pod adresem programisty moĝe byÊ wówczas: „Co zamierzasz zrobiÊ na bis?”). Umówmy siÚ wiÚc, iĝ owo „przywrócenie” oznacza przywrócenie adekwatnoĂci naszych oczekiwañ po poczÈtkowo frustrujÈcej konfrontacji z rzeczywistoĂciÈ — przyp. tïum. Rozdziaï 1. • W tym szaleñstwie jest metoda  21 funkcjonowanie programu. Gdy programista ma trochÚ szczÚĂcia, owe doraěne zabiegi okazujÈ siÚ od razu chybione, co umoĝliwia unikniÚcie marnotrawstwa czasu i wysiïku, niekiedy jednak, niestety, faktycznie eliminujÈ konkretny bïÈd lub stwarzajÈ pozory jego wyeliminowania. „Niestety”, poniewaĝ w ostatecznym rozrachunku okazuje siÚ, ĝe owe nieprzemyĂlane i nie do koñca zrozumiane zabiegi jedynie maskujÈ prawdziwe przyczyny bïÚdów, które niespodziewanie mogÈ siÚ ujawniÊ, gdy bÚdziemy tego naj- mniej oczekiwaÊ. Co gorsza, nieprzemyĂlane ïatanie kodu moĝe mieÊ zgubne konse- kwencje w postaci destrukcji regresywnej, czyli ponownego wprowadzenia do kodu bïÚdów, których przyczyny zostaïy wczeĂniej wyeliminowane. Zmarnowany czas i wysiïek Kilka lat temu przyszïo mi wspóïpracowaÊ z zespoïem bardzo doĂwiadczonych i utalentowanych programistów. Swe zawodowe umiejÚtnoĂci zdobywali oni na bazie systemów klasy UNIX, jednak gdy do nich doïÈczyïem, dokonywali migracji uniksowego oprogramowania na platformÚ Windows; migracja ta znajdowaïa siÚ juĝ w doĂÊ zaawansowanym stadium. Jeden z „bïÚdów” wynikajÈcych z migracji ujawniaï siÚ w warunkach rów- nolegïej pracy wielu wÈtków. Niektóre wÈtki funkcjonowaïy bez zarzutu, inne jednak zdawaïy siÚ pozostawaÊ w stanie zagïodzenia2. Poniewaĝ w Ărodowisku UNIX-a wszystko funkcjonowaïo bezbïÚdnie, przyczyna problemu zdawaïa siÚ ewidentnie tkwiÊ w specyfice mechanizmu zarzÈdzania wÈtkami przez Windows. PodjÚto wiÚc decyzjÚ o stworzeniu wïasnego pod- systemu zarzÈdzania wÈtkami, zastÚpujÈcego oferowany standardowo przez Windows — przedsiÚwziÚcie, owszem, bardzo ambitne i pracochïonne, nie- mniej jednak mieszczÈce siÚ w granicach moĝliwoĂci wspomnianego zespoïu. I rzeczywiĂcie, gdy doïÈczyïem do zespoïu, wydawaïo siÚ, ĝe wspomniany podsystem speïnia pokïadane w nim nadzieje — nie zdarzaïy siÚ juĝ przypadki zagïodzenia wÈtków. Jednak tak gïÚboka ingerencja w system operacyjny rzadko obywa siÚ bez skutków ubocznych i nie inaczej byïo tym razem: cenÈ zapïaconÈ za ulepszone zarzÈdzanie wÈtkami okazaïo siÚ ogólne, zauwaĝalne spowolnienie pracy caïego systemu Windows. Dla mnie caïa ta sytuacja byïa o tyle intrygujÈca, ĝe sam w przeszïoĂci musiaïem zmagaÊ siÚ z rozmaitymi problemami wynikajÈcymi z wielowÈtkowej architektury tworzonych przeze mnie aplikacji dla Windows. Pobieĝna analiza problemu, którego konsekwencjÈ byïa gïÚboka ingerencja w system operacyjny, wykazaïa, ĝe jego rzeczywistÈ przyczynÈ jest dynamiczne zwiÚkszanie priorytetu wÈtków (dynamic thread priority boost), które wyïÈczyÊ moĝna w sposób 2 Zagïodzeniem (starvation) wÈtku lub procesu nazywamy sytuacjÚ, w której mechanizmy szere- gowania systemu operacyjnego konsekwentnie ignorujÈ ów wÈtek lub proces w rywalizacji o dostÚp do zasobów, w tym przypadku w rywalizacji o czas procesora — przyp. tïum. 22  CzÚĂÊ I • Istota problemu elementarny, wywoïujÈc funkcjÚ API SetThreadPriorityBoost(). Zamiast pracochïonnego — i podatnego na bïÚdy — tworzenia wïasnego systemu szeregowania wÈtków, wystarczyïoby dodanie jednego wiersza kodu. Moraï? ObserwujÈc niepoĝÈdane zachowanie aplikacji, zespóï programistów dopatrzyï siÚ jego przyczyny w ogólnej architekturze Windows, bez gïÚbszej analizy uwikïanego w to zachowanie podsystemu. Na pewno nie bez znaczenia byïy uwarunkowania kulturowe, czyli mówiÈc po prostu, acz delikatnie, nie najlepsza reputacja systemu Windows w Ărodowisku „hakerów uniksowych”. Tak czy inaczej, gdyby programiĂci z zespoïu poĂwiÚcili nieco czasu na wnikliwÈ analizÚ zjawiska i tkwiÈcych u jego przyczyny mechanizmów oraz dostÚpnych ustawieñ, zaoszczÚdziliby znacznie wiÚcej czasu, jaki stracony zostaï na — niepotrzebnÈ w gruncie rzeczy — konstrukcjÚ wïasnego podsystemu. UniknÚliby ponadto degradacji wydajnoĂci systemu Windows i (bez wÈtpienia) wprowadzenia doñ nowych bïÚdów. MówiÈc dosadnie: gdy rezygnujemy z poszukiwañ prawdziwych przyczyn ujawniajÈ- cych siÚ bïÚdów, sami wystawiamy siÚ poza nawias inĝynierii programowania, za- puszczamy siÚ w zdradliwy gÈszcz „programowania voodoo”3 lub „lub programowania przez przypadek”4. 1.2. Metoda empiryczna Do zrozumienia przyczyny zaistniaïych bïÚdów, manifestujÈcych siÚ niezgodnym z oczekiwaniami dziaïaniem aplikacji, moĝna dochodziÊ róĝnymi drogami. Generalnie kaĝda metoda, która przybliĝa do tego celu, moĝe byÊ uznana za wïaĂciwÈ. A skoro tak, to w wiÚkszoĂci przypadków debugowania najbardziej celowe — bo wysoce produktywne —okazuje siÚ podejĂcie empiryczne. Eksperymentuj i obserwuj wyniki. PodejĂcie to zasadza siÚ na obserwacjach i doĂwiad- czeniu, a nie na teorii czy teĝ czysto logicznych spe- kulacjach. Owszem, moĝna studiowaÊ kod programu i wyciÈgaÊ z niego wnioski na temat skutków wykonania poszczególnych jego fragmentów (i czasem zdarza siÚ, ĝe nie ma innego wyboru), 3 ¿argonowe okreĂlenie naĂladujÈce powiedzenie prezydenta George’a Busha seniora, który mia- nem „voodoo economics” okreĂlaï niektóre gospodarcze posuniÚcia Ronalda Reagana. Oznacza uĝywanie w programowaniu funkcji lub algorytmów, których dziaïania nie rozumie siÚ w peïni, wskutek czego program nie dziaïa albo jeĂli przypadkiem dziaïa, programista i tak nie rozumie, dla- czego tak siÚ dzieje, cytat z pl.wikipedia.org — przyp. tïum. 4 Andrew Hunt, David Thomas, The Pragmatic Programmer: From Journeyman to Master, Addi- son-Wesley, Reading, MA, 2000. Rozdziaï 1. • W tym szaleñstwie jest metoda  23 A propos natury oprogramowania… „Oprogramowanie” to kategoria zasïugujÈca na szczególnÈ uwagÚ — co dla nas, majÈcych z niÈ do czynienia na bieĝÈco, nie zawsze jest oczywiste. Niewiele jest w ludzkiej dziaïalnoĂci innych obszarów dajÈcych tak wielkÈ oka- zjÚ do nieograniczonej niemal realizacji wïasnej pomysïowoĂci, wynalazczoĂci; niewiele jest przykïadów tworzywa intelektualnego dajÈcego siÚ ksztaïtowaÊ w tak plastyczny sposób. Oprogramowanie ma tÚ cennÈ zaletÚ, ĝe jest noĂni- kiem determinizmu — poza nielicznymi wyjÈtkami, które opiszemy w dalszej czÚĂci ksiÈĝki, kolejny stan jego realizacji wyznaczony jest jednoznacznie przez stany poprzednie, a my uzyskujemy powtarzalny dostÚp do kaĝdego ze stanów na kaĝde ĝÈdanie. Nie majÈ tego szczÚĂcia przedstawiciele wiÚkszoĂci dziedzin tradycyjnej inĝynierii. Bo czyĝ moĝna wyobraziÊ sobie mechanika Formuïy 1, przyglÈdajÈcego siÚ sil- nikowi obracajÈcemu siÚ z prÚdkoĂciÈ 19000 obrotów na minutÚ i momentalnie — jakby w rezultacie mentalnego zatrzymania tych obrotów — zgïÚbiajÈcego wszelkie detale rozmaitych konsekwencji tej dynamiki? Albo szczegóïowo ana- lizujÈcego przebieg zapïonu w komorze spalania? W konfrontacji z szybkoĂciÈ dziaïania ludzkich zmysïów wydaje siÚ to absolutnie niewykonalne i faktycznie takie jest. W naszym oprogramowaniu krÚcÈca siÚ z szybkoĂciÈ milionów (czy nawet mi- liardów) na sekundÚ pÚtla wolna jest od owego piÚtna ulotnoĂci. Gdy na ĝÈdanie zostaje zatrzymana — w precyzyjnie okreĂlonym miejscu — moĝemy drobiazgo- wo, bez presji wynikajÈcej z szalonego tempa, analizowaÊ wszelkie (dostÚpne) aspekty jej realizacji — przypomnijmy: aspekty deterministyczne, a wiÚc powta- rzalne. I ten wïaĂnie istotny fakt predestynuje metodÚ empirycznÈ jako szczególnie cennÈ i produktywnÈ w procesie debugowania. lecz jest to metoda po pierwsze, maïo efektywna, po drugie, zawodna. Znacznie efektywniej moĝna dojĂÊ sedna problemu, konstruujÈc odpowiedni eksperyment i ob- serwujÈc faktyczne zachowanie siÚ aplikacji. Jest to nie tylko efektywne, lecz daje takĝe okazjÚ do zweryfikowania przyjÚtych zaïoĝeñ dotyczÈcych oczekiwanego jej zachowania. Tak oto skutecznym narzÚdziem w walce z tkwiÈcymi w oprogramo- waniu bïÚdami okazuje siÚ… samo oprogramowanie. W kolejnym punkcie zobaczymy, jak wykorzystaÊ tÚ empirycznÈ filozofiÚ do utwo- rzenia strukturalnego modelu walki z bïÚdami w oprogramowaniu. 1.3. Struktura procesu debugowania Pod wzglÚdem strukturalnym w procesie debugowania wyróĝniÊ moĝna nastÚpu- jÈce kluczowe elementy: 24  CzÚĂÊ I • Istota problemu  reprodukcjÚ — czyli wypracowanie sposobów na niezawodnÈ i wygodnÈ powtarzalnoĂÊ poszczególnych aspektów bïÚdnego zachowania aplikacji;  diagnozÚ — formuïowanie i eksperymentalne weryfikowanie hipotez, zmierzajÈce do ostatecznego ustalenia rzeczywistej przyczyny zaistniaïych bïÚdów;  naprawÚ — projektujÈc i urzeczywistniajÈc zmiany w kodzie ěródïowym w celu wyeliminowania konkretnego bïÚdu, naleĝy upewniÊ siÚ, ĝe nie spowodujÈ one zniwelowania poprawek wprowadzonych wczeĂniej (a w kon- sekwencji ponownego zaistnienia bïÚdów juĝ wyeliminowanych — powszech- nie okreĂla siÚ to zjawisko mianem destrukcji regresywnej); wprowadzane poprawki nie powinny teĝ pogarszaÊ wydajnoĂci kodu, jego czytelnoĂci i ïatwoĂci konserwacji;  refleksjÚ — skuteczne poprawienie bïÚdu staje siÚ swoistÈ lekcjÈ, z której warto zawsze wyciÈgnÈÊ stosowne wnioski. Co zrobiliĂmy nie tak w tym fragmencie programu? Czy istniejÈ inne jeszcze fragmenty noszÈce zna- miÚ analogicznej pomyïki? Co moĝemy zrobiÊ w celu upewnienia siÚ, ĝe tego bïÚdu juĝ nie powtórzymy? Debugowanie jest procesem iteracyjnym. Jak pokazano na rysunku 1.1, etapy te zasadniczo ukïadajÈ siÚ w prostÈ sekwencjÚ; nie powinno to jednak sugerowaÊ, iĝ powiÈzane sÈ ze sobÈ na zasadzie wo- dospadu. Co prawda, trudno przystÚpowaÊ do formu- ïowania hipotez bez uprzedniego zapewnienia Ărodków do reprodukowania bïÚdu na ĝÈdanie, nie ma teĝ wiÚkszego sensu poprawianie kodu bez uprzedniego dogïÚbnego zrozumienia przyczyny wykrytego bïÚdu, niemniej jednak miÚdzy wymienionymi czterema etapami istniejÈ silne sprzÚĝenia zwrotne powodujÈce, ĝe debugowanie, zamiast sekwencjÈ etapów, staje siÚ procesem iteracyjnym. I tak np. na etapie formu- ïowania hipotez moĝemy krytycznie oceniÊ skutecznoĂÊ metod reprodukowania bïÚ- dów (i skutecznoĂÊ tÚ poprawiÊ), zaĂ nanoszenie poprawek w kodzie moĝe staÊ siÚ okazjÈ do zrewidowania przyjÚtych hipotez. W nastÚpnych rozdziaïach zatrzymamy siÚ szczegóïowo na kaĝdym z wymienio- nych etapów; dalsza czÚĂÊ tego rozdziaïu niech natomiast posïuĝy jako niezbÚdne do tego przygotowanie. 1.4. Przede wszystkim rzeczy najwaĝniejsze Mimo silnej pokusy, by jak najszybciej „zaczÈÊ debugowanie”, warto jednak za- stanowiÊ siÚ, czy jesteĂmy do tego naleĝycie przygotowani. Rozdziaï 1. • W tym szaleñstwie jest metoda  25 Rysunek 1.1. Struktura procesu debugowania Co powinno siÚ wydarzyÊ, a co wydarzyïo siÚ naprawdÚ? Czy naprawdÚ wiesz, czego szukasz? Zanim przystÈpimy do reprodukowania problemu i sta- wiania hipotez na temat jego przyczyny, powinniĂmy dokïadnie zdawaÊ sobie sprawÚ z tego, cóĝ w zacho- waniu aplikacji wydarzyïo siÚ takiego, co skïonni jeste- Ămy uwaĝaÊ za ów „problem”, oraz — co niemniej waĝne — co powinno siÚ wydarzyÊ, zgodnie z naszymi oczekiwaniami. JeĂli dys- ponujemy formalnym raportem na temat bïÚdów, raport ten powinien zawieraÊ niezbÚdne informacje w tym zakresie (raportami takimi zajmiemy siÚ dokïadniej w roz- dziale 6.), na przeanalizowanie i zrozumienie których warto poĂwiÚciÊ trochÚ czasu. JeĂli nie ma raportu, bo bïÈd sami wykryliĂmy lub dowiedzieliĂmy siÚ o nim z niefor- malnej rozmowy, tym waĝniejsze jest stworzenie adekwatnego obrazu caïej sytuacji. Nie zapominajmy jednak, ĝe formalne raporty o bïÚdach bywajÈ nie mniej mylÈce niĝ wszelkie inne dokumenty. Jeĝeli mianowicie stwierdzono w raporcie, ĝe „wydarzyïo siÚ to, a powinno siÚ wydarzyÊ tamto”, czy zawsze stwierdzenie takie zgodne jest ze specyfikacjÈ aplikacji? Jeĝeli mamy w tym wzglÚdzie wÈtpliwoĂci, nie rozpoczynajmy konkretnych dziaïañ przed ich wyjaĂnieniem, przed upewnieniem siÚ, ĝe wszystko naleĝycie zrozumieliĂmy. Nie warto ryzykowaÊ „psucia” aplikacji, czyli zmiany poĝÈdanego jej zachowania na bïÚdnÈ, tylko dlatego, ĝe tak sugerowaÊ moĝe treĂÊ wspomnianego raportu. 26  CzÚĂÊ I • Istota problemu Walka z niespójnymi danymi Przyszïo mi kiedyĂ zmagaÊ siÚ z doĂÊ prostym (wydawaïoby siÚ) bïÚdem: raport transakcji, generowany przez system ewidencji sprzedaĝy, nie uwzglÚd- niaï czasu letniego i okazywaï siÚ nieadekwatny do rzeczywistoĂci w dniach, na przeïomie których nastÚpowaïa zmiana czasu. Szybko wprowadziïem niezbÚdnÈ poprawkÚ i zajÈïem siÚ nastÚpnym problemem. Niedïugo potem poinformowano mnie o kolejnym bïÚdzie: wykazana w rapor- cie liczba transakcji nie zgadzaïa siÚ z liczbÈ transakcji faktycznie zreali- zowanych, wskutek czego dziaï ksiÚgowoĂci nie mógï sporzÈdziÊ bilansu. ½ródïo owej rozbieĝnoĂci od razu staïo siÚ dla mnie oczywiste: proces reje- strowania transakcji nie uwzglÚdniaï zmiany czasu, w przeciwieñstwie do ge- nerowanego raportu. Po krótkich konsultacjach dowiedziaïem siÚ, ĝe opisany problem daï o sobie znaÊ juĝ rok temu i wïaĂnie dla unikniÚcia opisanej rozbieĝnoĂci postanowiono istnienie czasu letniego po prostu ignorowaÊ5. Tak oto „bïÚdne” dziaïanie aplikacji, czyli rozbieĝnoĂÊ jej zachowania z ocze- kiwaniami, nie byïo wcale winÈ aplikacji, a wynikaïo po prostu z nieadekwat- noĂci wspomnianych oczekiwañ. Poniewaĝ raporty sprzedaĝy generowane byïy w róĝnych kontekstach, niektóre powinny uwzglÚdniaÊ zmianÚ czasu, inne raczej celowo jÈ ignorowaÊ. Rzetelnym rozwiÈzaniem problemu mogïoby byÊ wprowadzenie do programu stosownej opcji rozróĝniajÈcej te dwa przypadki. Jeden problem na raz Poniewaĝ problemy czÚsto pojawiajÈ siÚ w grupach, istnienie pokusa zajmowania siÚ równolegle wieloma z nich. Pokusa taka okazuje siÚ jeszcze silniejsza, gdy wiele bïÚdów wydaje siÚ byÊ zwiÈzanych z tym samym obszarem kodu. Takim pokusom naleĝy siÚ zdecydowanie opieraÊ. Debugowanie jest procesem wy- starczajÈco zïoĝonym, by powstrzymaÊ siÚ od dalszej jego komplikacji. Jakkolwiek nie bylibyĂmy ostroĝni, zawsze istnieje moĝliwoĂÊ, iĝ eksperyment zmierzajÈcy do wykrycia przyczyny jednego bïÚdu interferowaÊ moĝe z eksperymentami zaprojekto- wanymi w celu wykrycia innych. To w duĝym stopniu utrudniaÊ moĝe rozumienie, co naprawdÚ dzieje siÚ z aplikacjÈ. Ponadto wprowadzanie do kodu kaĝdej poprawki powinno byÊ logicznie uzasadnione, a to staje siÚ znacznie utrudnione, gdy próbujemy poprawiaÊ kilka bïÚdów na raz (wrócimy do tej kwestii w punkcie 4.5). 5 PrawdÚ mówiÈc, programista dokonujÈcy poprawek mógï zaoszczÚdziÊ nam fatygi i umieĂciÊ w kodzie komentarz wyjaĂniajÈcy przyczynÚ ignorowania czasu letniego i tym samym upewniajÈcy czytelnika kodu, ĝe jest to dziaïanie zamierzone. Rozdziaï 1. • W tym szaleñstwie jest metoda  27 Czasami moĝe siÚ okazaÊ, ĝe to, co skïonni byliĂmy uwaĝaÊ za pojedynczy bïÈd, spowodowane jest wieloma przyczynami. UĂwiadamiamy sobie wówczas, ĝe znaleěli- Ămy siÚ w przysïowiowej „strefie mroku” — z aplikacjÈ dziejÈ siÚ róĝne kuriozalne rzeczy, niedajÈce siÚ wyjaĂniÊ w wiarygodny sposób. Obszernie problem ten omówiono w punkcie 3.4. Zaczynaj od rzeczy prostych Wiele bïÚdów programistycznych ma swe ěródïo w zwykïym przeoczeniu tych czy innych rzeczy. Mimo iĝ czÚsto przychodzi nam zmagaÊ siÚ z bïÚdami bardziej subtelnej natury, nie moĝna o takich prozaicznych przyczynach zapominaÊ. Tak siÚ juĝ staïo, ĝe my, programiĂci, przekonani jesteĂmy co do tego, ĝe wszystko powinniĂmy robiÊ we wïasnym zakresie. Przekonanie to czÚsto ujawnia siÚ w postaci syndromu „co nie moje, to niedobre” (Not Invented Here), polegajÈcego na ponow- nym wynajdywaniu koïa, czyli (uïomnego nieraz) implementowania rzeczy, dla których gotowe, czÚsto perfekcyjne implementacje, dostÚpne sÈ na wyciÈgniÚcie rÚki. W odnie- sieniu do debugowania syndrom ten przyjmuje postaÊ dÈĝenia do osobistego wyja- Ănienia kaĝdego aspektu nieoczekiwanego zachowania aplikacji. A wystarczy po prostu spytaÊ kolegów, czy w przeszïoĂci zetknÚli siÚ z takim, czy innym problemem. To niewiele kosztuje, a moĝe przyczyniÊ siÚ do unikniÚcia znacz- nego marnotrawstwa czasu i wysiïku. Szczególnie w sytuacji, gdy nie jesteĂmy eks- pertami w dziedzinie, którÈ przyszïo siÚ nam zajmowaÊ. NiespójnoĂÊ treĂci Subversion (Sean Ellis) Nie dalej jak kilka dni temu nasz nowy kolega zetknÈï siÚ z problemem dziw- nego dziaïania polecenia svn export. Dziwnego, bo mimo identycznych numerów wersji, postaÊ kodu aplikacji na serwerze Subversion róĝniïa siÚ od kopii roboczej w jego komputerze. Nic, tylko rwaÊ wïosy z gïowy. Po bezskutecznych próbach samodzielnego uporania siÚ z problemem kolega poddaï siÚ i zapytaï mnie, czy widzÚ jakieĂ wyjaĂnienie rozbieĝnoĂci, którÈ on jest mi w stanie natychmiast zaprezentowaÊ. Odpowiedziaïem twierdzÈco, wyjaĂniajÈc, iĝ przyczynÈ problemu jest bïÈd w jednej z bibliotek runtime serwera Apache, manifestujÈcy siÚ pod posta- ciÈ nieprawidïowej interpretacji Ăcieĝek zawierajÈcych sekwencje ../../... Po ostatecznym upewnieniu siÚ, iĝ to wïaĂnie jest istotÈ problemu, wystar- czyïo nam kilka minut, by zainstalowaÊ nowszÈ, poprawnÈ wersjÚ biblioteki. Ostatecznie okazaïo siÚ, iĝ bïÈd ten odkryty zostaï juĝ wiele miesiÚcy wczeĂniej, jednak odkrywca widocznie zapomniaï podzieliÊ siÚ swÈ wiedzÈ z kolegami. 28  CzÚĂÊ I • Istota problemu Jak widaÊ, komunikacja jest zawsze istotna — nie tylko w kwestiach subtel- nych, trudnych do pisania zwykïymi sïowami, lecz takĝe wówczas, gdy wystar- czy po prostu zapytaÊ: „Czy widzieliĂcie juĝ wczeĂniej coĂ podobnego?”. W nastÚpnych rozdziale zajmiemy siÚ pierwszym z etapów iteracyjnego debugowania — reprodukowaniem bïÚdnego zachowania aplikacji. 1.5. Do dzieïa! Dla przypomnienia...  Upewnij siÚ, ĝe:  dÈĝysz do poznania prawdziwej przyczyny, powodujÈcej nieoczekiwane zachowanie aplikacji,  rzeczywiĂcie eliminujesz okreĂlony bïÈd,  nie stwarzasz zagroĝenia destrukcji „dobrego” kodu,  nie pogarszasz jakoĂci kodu,  bïÈd, który wïaĂnie poprawiasz, nie pozostanie w innym miejscu kodu,  nie popeïnisz w przyszïoĂci tego samego bïÚdu.  Wykorzystuj moĝliwoĂci oprogramowania w zakresie demonstracji jego zachowania.  Nie zajmuj siÚ wieloma problemami jednoczeĂnie.  Upewnij siÚ, ĝe doskonale wiesz:  jak powinna zachowywaÊ siÚ aplikacja?  jak zachowuje siÚ faktycznie?  PoszukujÈc przyczyn bïÚdów, zaczynaj od rzeczy oczywistych.
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Debugowanie. Jak wyszukiwać i naprawiać błędy w kodzie oraz im zapobiegać
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: