Zrozumieć programowanie - ebook
Zrozumieć programowanie - ebook
Książka jest techniczno-popularyzacyjną pozycją traktującą o programowaniu oraz tematach pokrewnych i jest napisana z myślą o początkujących oraz średniozaawansowanych programistach.
Celem publikacji jest przedstawienie ciekawych elementów programowania oraz ekosystemu programistycznego, a także przedstawienie sposobów radzenia sobie z podstawowymi problemami, oraz wyjaśnienia w przystępny sposób pewnych elementów, z którymi często osoby początkujące oraz średniozaawansowane mają trudności.
Z książki dowiesz się:
- jak poradzić sobie z trudnościami napotykanymi podczas programowania,
- jak operować na danych tekstowych, binarnych, plikach, strumieniach, pakietach danych, oraz jakie są najczęściej popełniane błędy,
- jakie są różnice pomiędzy językami programowania w kwestiach, które na pierwszy rzut oka wydawały się identyczne,
- jak wybrane, często używane, mechanizmy, funkcje czy biblioteki działają "od kuchni",
- o wielu detalach, które normalnie pozostałyby niezauważone,
- zaprzyjaźnisz się z niskopoziomowymi aspektami informatyki.
Powinieneś:
- znać podstawy programowania (np. wiedzieć czym jest pętla),
- mieć w swoim dorobku przynajmniej 1 program dłuższy niż 50 linii.
Spis treści
Przedmowa
Wstęp
O autorze, o książce
Podziękowania
Zgłaszanie błędów i errata
Część I. Kilka codziennych czynności
1. Konsola i interpreter poleceń
1.1. Wykorzystanie interpretera
1.2. Przekierowania
1.3. Przykładowe polecenia wykorzystujące przekierowania
1.4. Bieżący katalog roboczy
1.5. Zmienne środowiskowe
1.6. Skrypt startowy
1.7. Konsola okiem programisty
Ćwiczenia
Bibliografia
2. Czytanie nieznanego języka
2.1. Podobieństwa i różnice
2.2. Studium przypadku
2.3. Uwagi na koniec
Ćwiczenia
Bibliografia
Część II. Podstawy
3. Podstawy architektury komputerów
3.1. Własny (wirtualny) komputer
3.2. Rejestry procesora
3.3. Kod maszynowy
3.4. Zestaw instrukcji
3.5. Pamięć operacyjna
3.6. Komunikacja z urządzeniami
3.7. Przerwania
3.8. Konsola znakowa
3.9. Programowalny timer
3.10. Przykładowy „kompilator”
3.11. Emulator
Ćwiczenia
Bibliografia
4. Typy liczb naturalnych i całkowitych
4.1. Zapis binarny i heksadecymalny
4.2. Typy liczb naturalnych
4.3. Liczby całkowite
4.4. Little i Big Endian
4.5. Przepełnienie zmiennych naturalnych i całkowitych
4.6. Przycięcie wyniku
4.7. Saturacja
4.8. Zasygnalizowane przepełnienie
4.9. Niezdefiniowane zachowanie
4.10. Awans zmiennej
4.11. Duże liczby
4.12. Obsługa przepełnienia w praktyce
Ćwiczenia
Bibliografia
5. Typy pseudorzeczywiste
5.1. Wstęp do liczb zmiennoprzecinkowych
5.2. Ułamki binarne
5.3. IEEE 754 i zmienne binarne
5.4. Kodowanie IEEE 754 Double Precision
5.5. Wartości specjalne i zdenormalizowane
5.6. Istotne wartości zmiennoprzecinkowe
5.7. Porównanie liczb zmiennoprzecinkowych
5.8. Dziesiętne typy zmiennoprzecinkowe
5.9. Typy stałoprzecinkowe
Ćwiczenia
Bibliografia
6. Znaki i łańcuchy znaków
6.1. ASCII i strony kodowe
6.2. Unicode
6.3. Łańcuchy znaków
6.4. Konwersja kodowań
Ćwiczenia
Bibliografia
Część III. Wykonywanie programu
Bibliografia
7. Procesy
7.1. Procesy w systemie operacyjnym GNU/Linux
7.2. Procesy w systemie operacyjnym Windows
7.3. Programowe tworzenie nowego procesu
7.4. Plik wykonywalny a nowy proces
7.5. API debuggera
7.6. Dziedziczenie po procesie rodzicu
7.7. Inne operacje na zewnętrznych procesach
Ćwiczenia
Bibliografia
8. Wątki
8.1. Tworzenie nowych wątków
8.2. Typy wątków i ich przełączanie
8.3. Kontekst wątku
8.4. Zmienne lokalne dla wątku
8.5. Pula wątków
Bibliografia
9. Synchronizacja
9.1. Blokujące atomowe bariery
9.2. Spinlocki – wirujące blokady
9.3. Muteksy i sekcje krytyczne
9.4. Zdarzenia i zmienne warunkowe
9.5. Problemy w synchronizacji
Ćwiczenia
Bibliografia
Część IV. Pliki i formaty danych
Bibliografia
10. System plików
10.1. Podstawowe operacje na systemie plików
10.2. Prawa dostępu
10.3. Operacje na plikach i danych
10.4. Ciekawe mechanizmy systemu plików
Ćwiczenia
Bibliografia
11. Pliki binarne i tekstowe
11.1. Pliki tekstowe
11.2. Pliki binarne
11.3. Wstęp do serializacji
11.4. Formaty plików
Ćwiczenia
Bibliografia
12. Format BMP i wstęp do bitmap
12.1. Grafika rastrowa
12.2. Canvas, surface, image, ...
12.3. Przegląd popularnych formatów pikseli
12.4. Wyświetlenie bitmapy
12.5. Ogólna struktura pliku BMP
12.6. Nagłówek BITMAPFILEHEADER
12.7. Nagłówek BITMAPINFOHEADER
12.8. Słowo o implementacji
12.9. Implementacja 24-bitowego BI_RGB
12.10. Paleta kolorów
12.11. Kompresja RLE w wydaniu BMP
12.12. Implementacja RLE8
12.13. Podsumowanie
Ćwiczenia
Bibliografia
13. Format PNG
13.1. Struktura PNG
13.2. Bloki IHDR oraz IEND
13.3. Blok IDAT, kompresja i filtry adaptacyjne
13.4. Prosty dekoder
Ćwiczenia
Bibliografia
Część V. Komunikacja
Bibliografia
14. Komunikacja międzyprocesowa
14.1. Potoki
14.2. Nazwane potoki
14.3. Gniazda domeny UNIX i socketpair
14.4. Pamięć współdzielona
14.5. Wiadomości w WinAPI
Ćwiczenia
Bibliografia
15. Komunikacja sieciowa
15.1. Wstęp do sieci TCP/IP
15.2. Gniazda TCP oraz DNS
15.3. Nasłuchujące gniazda TCP oraz HTTP
15.4. Gniazda UDP i peer-to-peer
Ćwiczenia
Bibliografia
Programowanie dla zabawy
Ćwiczenia
Bibliografia
Zakończenie
Indeks
Kategoria: | Programowanie |
Zabezpieczenie: |
Watermark
|
ISBN: | 978-83-01-18460-5 |
Rozmiar pliku: | 5,8 MB |
FRAGMENT KSIĄŻKI
Można śmiało powiedzieć, że na komputerach używanych w latach 70. i 80. ubiegłego wieku każdy dostępny fragment pamięci oraz cykl procesora był na wagę złota. W czasach, gdy masa megabajtu przestrzeni dyskowej była wyrażana w kilogramach, a programiści dysponowali niezwykle znikomą mocą obliczeniową, wyciskano siódme poty ze wszystkich instrukcji procesora, składających się na program, a o każdym bajcie było wiadomo, skąd się wziął i jaką rolę dokładnie odgrywa. Fakt ten był szczególnie widoczny na przykładzie starych gier wideo, które pomimo niewyobrażalnych dziś ograniczeń potrafiły zaskoczyć dopracowaniem oraz grywalnością na maszynach pokroju konsoli Atari 2600. Choć operowała ona na zaledwie 128 bajtach pamięci operacyjnej, to słynne produkcje, takie jak River Raid, Keystone Kapers czy Pitfall! na długo pozostały we wspomnieniach ówczesnych graczy. Z perspektywy lat trudno nie docenić kunsztu tych majstersztyków oraz umiejętności ich autorów.
Na skutek błyskawicznego rozwoju branży sprzętowej oraz powstawania coraz wygodniejszych systemów operacyjnych i środowisk programistycznych, szybszych i efektywniejszych kompilatorów czy w końcu samych języków programowania, lepiej skrojonych pod konkretne zastosowania i niezależnych od docelowej platformy, programowanie z biegiem czasu stało się w pewnym sensie łatwiejsze. Asembler został zamieniony na C, ten na C++, by następnie ustąpić w wielu przypadkach interpretowanym językom wysokiego poziomu, takim jak PHP, Java czy Python. Z drugiej strony postępujące oddalenie programisty od krzemu wykonującego tworzony kod utrudnia dostrzeżenie i zrozumienie pełnego obrazu tego, co dzieje się „pod maską” programu i całego środowiska uruchomieniowego. Na przykład wykonanie prostego skryptu „Hello, World!” napisanego w języku Python na systemie Windows składa się – w dużym uproszczeniu – z uruchomienia interpretera, przetłumaczenia kodu wysokiego poziomu na tzw. kod bajtowy (bytecode), obsłużenia każdej instrukcji tego kodu, przejścia do trybu jądra poprzez odpowiednie wywołanie systemowe, rasteryzacji tekstu do bitmapy i przesłania jej do sterownika graficznego, a w końcu na ekran. Ilu współczesnych programistów mogłoby opisać szczegółowo przebieg większości wymienionych etapów wykonania? Prawdopodobnie tylko nieznaczny procent – i choć nie jest to oczywiście problem sam w sobie, przykład ten ilustruje, jak długa jest lista zależności naszych aplikacji od elementów środowiska wykonawczego, z których istnienia możemy nawet nie zdawać sobie sprawy.
Mimo że zrozumienie wewnętrznych mechanizmów związanych z oprogramowaniem z całą pewnością przydaje się w pracy programisty, muszę przyznać, że główną motywacją wielu badań, które wspólnie z autorem tej książki przeprowadziliśmy podczas naszej 11-letniej znajomości, była zwyczajna ciekawość i rozrywka. Zagłębianie się w coraz to niższe partie środowiska wykonania aplikacji i skryptów, systemów operacyjnych czy w końcu samego procesora z czasem stało się swego rodzaju uzależnieniem pozwalającym na zaspokojenie głodu wiedzy. Szczególnie miło wspominam wczesne lata tego zauroczenia, gdy nierzadko w aktywnej jeszcze sieci IRC wystarczyło, by ktoś rzucił hasło: „Zróbmy konkurs na najmniejszy kompilator ezoterycznego języka Brainfuck!”, i już grupa ludzi rozmyślała przez tydzień nad ekstremalnymi optymalizacjami w asemblerze. Wkrótce potem zamiłowanie do niskopoziomowych aspektów informatyki i inżynierii wstecznej w naturalny sposób skierowała Gynvaela i mnie na tor bezpieczeństwa oprogramowania. Dalsze prace pozwoliły na odebranie prestiżowych nagród Pwnie Award (w tym wspólnej w 2013 r. w kategorii „Najbardziej Innowacyjne Badania Naukowe”), a stworzenie polskiej drużyny Dragon Sector na konkurowanie z najlepszymi zespołami Security CTF na świecie oraz zajęcie pierwszego miejsca w globalnym rankingu CTFtime.org w roku 2014.
Książka, którą trzymasz w ręku, jest wynikiem pasji, dociekliwości i wyjątkowego zacięcia dydaktycznego autora, które dotychczas ujawniało się w rozmaitych formach – od licznych, długich na kilka stron ekranowych postów na forach powiązanych z programowaniem i bezpieczeństwem, poprzez inicjatywę IRCowych wykładów (wyklady.net), posty na prywatnym blogu, wystąpienia na konferencjach i spotkaniach branżowych, aż po techniczne podcasty publikowane w serwisie YouTube. Dzieło to odbieram osobiście jako swoiste ukoronowanie edukacyjnej działalności autora. O prawdziwej wyjątkowości książki świadczy jednak przede wszystkim fakt, że podchodzi do tematyki inaczej niż podobne opracowania tego typu. Nie znajdziemy tutaj opisu składni lub wstępu do żadnego języka programowania, metodyk tworzenia oprogramowania czy wzorców architektonicznych – tematy te zostały już gruntownie opisane w innych publikacjach, a ich znalezienie nie stanowi problemu. W zamian autor, opierając się na swoim ponad 20-letnim doświadczeniu, skupił się na równie istotnych kwestiach, które bywają z reguły pomijane w innych źródłach, co skutkowało tym, że początkujący programiści byli zmuszeni dochodzić do nich sami na podstawie prób i błędów, tracąc przy tym energię i nabierając niekoniecznie prawidłowych nawyków lub przekonań.
Większość opisanych tutaj mechanizmów, technik i zachowań ma charakter ogólny i posiada zastosowanie niezależnie od użytego języka programowania, dotykając problemu tworzenia poprawnych i przemyślanych programów, a nie wyłącznie kompilującego się kodu. Część I porusza zagadnienia związane z codziennymi czynnościami programistycznymi, ze szczególnym uwzględnieniem konsoli i okna poleceń. Aspekt ten jest ważny głównie dla niedoświadczonych koderów, stawiających swoje pierwsze kroki w środowiskach konsolowych, choć często ignorowany lub traktowany po macoszemu. Część II opisuje najbardziej fundamentalne koncepty, kierujące współczesnym programowaniem, takie jak podstawy architektury komputerów, binarne kodowanie i operacje na typach liczb naturalnych, całkowitych i pseudorzeczywistych czy reprezentacja znaków i ich ciągów. Rozdziały te są jednymi z moich ulubionych, gdyż bardzo wyraźnie akcentują, jak pewne niskopoziomowe elementy środowiska wykonania przenikają i wpływają na kod wysokiego poziomu – za przykład mogą posłużyć niedokładne (wbrew intuicji) typy zmiennoprzecinkowe w językach takich jak Java czy Python, czy niekompatybilność reprezentacji ciągów tekstowych używanych wewnętrznie i przekazywanych do funkcji biblioteki standardowej, umożliwiająca atak typu poison null byte w starszych wersjach PHP. Części III, IV i V omawiają najważniejsze komponenty środowiska uruchomieniowego aplikacji, wprowadzając Czytelnika w świat procesów i wątków (jak również związanych z nimi problemów), interakcji z systemem plików oraz samymi plikami, a także komunikacji pomiędzy programami. Wszystkie rozdziały są okraszone olbrzymią dawką technicznych smaczków, studiów przypadku i przykładowych listingów kodu, tworząc lekturę wypełnioną po brzegi treścią.
Z pełnym przekonaniem polecam ten tytuł każdemu początkującemu i średnio zaawansowanemu programiście, a przede wszystkim tym, którzy zamiast pobieżnych wyjaśnień dostępnych w wielu opracowaniach (np. „zmienna typu short może przechowywać wartości z zakresu od –32768 do 32767”) wolą poznać pełną historię. Uważam, że jest to pozycja obowiązkowa na półce każdego zainteresowanego tą dziedziną informatyki, tuż obok książki do nauki konkretnego języka programowania oraz podręcznika do algorytmów i struktur danych; idealnie wypełni ona lukę dotyczącą podstaw środowiska wykonawczego oraz kluczowych mechanizmów używanych w oprogramowaniu w praktycznych zastosowaniach. Życzę Ci, Czytelniku, dobrej zabawy na kolejnych kartach tego tomu, gdyż to właśnie zabawa i fascynacja tematem pomagają z łatwością Zrozumieć programowanie.
Mateusz Jurczyk
Senior Software Engineer, Google
Kraków, wrzesień 2015 r.Wstęp
O autorze, o książce
Kiedy miałem siedem lat, zostałem dumnym posiadaczem swojego pierwszego, własnego komputera Atari 800XL wraz z magnetofonem oraz dwoma dżojstikami; do zestawu był również dołączony zestaw kaset z przeróżnymi grami, takimi jak River Ride, Bruce Lee czy Archon. Wczytanie gry trwało zazwyczaj od pięciu do dziesięciu minut, a więc całą wieczność dla niecierpliwego dziecka. Na szczęście jedna z gier nie wymagała kasety i była dostępna od razu po włączeniu komputera – nazywała się Atari BASIC i była grą w programowanie. Co więcej, była do niej dołączona instrukcja w formie zdobytej cudem kserokopii książki, która dla osoby rozpoznającej litery, ale niekoniecznie umiejącej złożyć je w wyrazy, stanowiła zagadkę, tak samo jak BASIC. Niemniej jednak umiejętność czytania nie jest potrzebna, by przepisywać kolejne znaki z przykładowych listingów, co też z upodobaniem czyniłem – najpierw z kserówek, a potem z kolejnych numerów czasopisma „Bajtek”, po które co miesiąc udawałem się wraz z którymś z rodziców do pobliskiego kiosku.
Na samym przepisywaniu listingów się nie kończyło – jeszcze większą radość przynosiło mi nanoszenie rozmaitych zmian we wprowadzonych programach i obserwowanie ich skutków. W efekcie okazało się, że parametry rozkazu REM były bez znaczenia (z czym wiązała się inna świetna wiadomość – nie trzeba było ich przepisywać!), parametry komendy PRINT były wypisywane na ekran, po instrukcji GOSUB musiało znaleźć się RETURN, a GRAPHICS na spółkę z PLOT i DRAWTO pozwalały rysować kolorowe linie. Z każdym przepisanym listingiem poznawałem coraz więcej wzorców, a z każdą wprowadzoną zmianą coraz lepiej rozumiałem to, co właściwie działo się w programie.
Bardzo szybko zacząłem również pisać własne, proste programiki, które z biegiem czasu stawały się coraz dłuższe i bardziej złożone. Wkrótce potem w domowym salonie stanął komputer kompatybilny z IBM PC, wyposażony w procesor 80286, 1 MB RAM, stację dyskietek 5,25" i kartę graficzną Hercules oferującą jedynie monochromatyczne tryby graficzne i tekstowe. Wraz z nim nadszedł czas nauki nowego wariantu znanego mi już języka – stworzonego przez Microsoft GW-BASIC. Wkrótce potem komputer został doposażony w dysk twardy o pojemności 50 MB, co umożliwiło zainstalowanie pełnego systemu MS-DOS 5 wraz z interpreterem języka QBasic, a później także Windows 3.1 i potężnym IDE języka Visual Basic 1.0. Czas leciał, leciwy 80286 został wymieniony na wielokrotnie szybszy 80486, a z języka Visual Basic przeniosłem się na Turbo Pascal. W kolejnych latach pojawiły się procesory z rodziny Pentium, pierwsze akceleratory 3D do kart graficznych (wtedy jeszcze jako osobne urządzenia), a także ogólnodostępny Internet za sprawą numeru 0–20 21 22. Wraz z nim uzyskałem dostęp do sieci IRC, grup dyskusyjnych i hobbystycznie prowadzonych stron internetowych poświęconych różnym językom programowania. Tymczasem trafiłem do liceum, komputer przeszedł kolejną metamorfozę i został wyposażony w procesor Intel Celeron taktowany z częstotliwością 333 MHz oraz kartę graficzną z wbudowaną akceleracją 3D, a ja za namową znajomego porzuciłem Turbo Pascal na rzecz C++ i OpenGL; moje zainteresowanie wzbudził też temat inżynierii wstecznej. Potem nadeszły studia na Politechnice Wrocławskiej, kolejne języki programowania w niemałej liczbie i coraz bardziej skomplikowane projekty. Na drugim roku rozpocząłem pierwszą pracę jako programista i reverse engineer dla jednej z polskich firm antywirusowych, coraz bardziej interesując się również zagadnieniami związanymi z bezpieczeństwem komputerowym. Wkrótce przeszedłem do hiszpańskiej firmy Hispasec, skończyłem studia inżynierskie, by ostatecznie trafić do firmy Google, w której pracuję do dzisiaj.
Spoglądając w przeszłość, mogę powiedzieć, że moja fascynacja wszystkim, co wiąże się z komputerami, a w szczególności programowaniem, nigdy nie minęła, mimo że zaczęła się ponad ćwierć wieku temu – jednym z jej efektów było napisanie książki, którą właśnie, Czytelniku, trzymasz w ręku. Podczas jej tworzenia starałem się uchwycić preferowane przeze mnie podejście do programowania, które jest zabarwione ciekawością, chęcią zrozumienia tego, jak każdy z używanych mechanizmów działa od środka, a także zamiłowaniem do niskopoziomowych zakątków informatyki. Co za tym idzie, książkę pisałem z myślą o pasjonatach, dla których programowanie jest jednocześnie wyzwaniem i świetną zabawą, bez względu na to, czy programują jedynie dla przyjemności, czy też pracują w zawodzie.
Dobierając zawartość książki, starałem się przede wszystkim wybrać tematy, o które często pytają początkujący i średnio zaawansowani programiści – stąd m.in. obecność rozdziałów o wątkach, gniazdach sieciowych czy plikach binarnych. Do spisu treści trafiły również tematy moim zdaniem istotne dla każdego programisty, takie jak niskopoziomowe kodowanie danych, synchronizacja procesów wielowątkowych czy choćby korzystanie z wiersza poleceń. Chciałem jednak również wskazać, że programowanie nie kończy się na aplikacjach narzędziowych lub „usługowych”, stąd obecność ostatniego rozdziału książki zatytułowanego „Programowanie dla zabawy”. Jednocześnie zdecydowałem się pominąć pewne, skądinąd bardzo istotne, zagadnienia, takie jak algorytmy, wzorce projektowe czy szczegółowe opisy konkretnych języków programowania – są one opisane w wielu innych, bardziej wyspecjalizowanych publikacjach.
Przykłady w książce zostały napisane w różnych językach programowania – są to przede wszystkim Python, C, C++ oraz Java. Ta nietypowa różnorodność brała się z chęci podkreślenia, że w większości środowisk występują te same podstawowe mechanizmy, których używa się w bardzo podobny sposób niezależnie od wybranego języka programowania, a różnice często sprowadzają się wyłącznie do nazw bibliotek, funkcji, klas itp. Jednocześnie z uwagi na specyfikę poszczególnych języków oraz ich umowną klasyfikację jako nisko- bądź wysokopoziomowe istnieją zadania łatwiejsze i trudniejsze do wykonania w każdym z nich – na przykład korzystanie z zaawansowanych funkcji oferowanych przez system operacyjny jest łatwiejsze w C i C++, ale już przetwarzanie danych tekstowych jest zdecydowanie prostsze w językach pokroju Python. Ostatecznie nie ma języka idealnego – warto więc, by programista znał ich kilka i zgodnie z zasadą use the right tool for the right job oraz własnymi preferencjami wybierał język adekwatny do danego zadania. Tak jak nie istnieje idealny język programowania, tak nie ma również idealnego systemu operacyjnego, stąd tematy poruszane w książce omawiam w kontekście dwóch popularnych rodzin systemów: Microsoft Windows oraz GNU/Linux (w szczególności Ubuntu).
Kontynuując temat przykładowych programów, starałem się również, by listingi miały wewnętrznie spójny styl, ale jednak zróżnicowany pomiędzy sobą – jednym z celów książki było zaprezentowanie fragmentów istniejącego ekosystemu programistycznego, w którym różni programiści stosują odmienne style tworzenia kodu. Warto więc jak najwcześniej nabrać pewnej elastyczności w tej kwestii – choć każdy projekt powinien konsekwentnie kierować się zasadami konkretnego stylu, jego wybór jest często kwestią osobistych preferencji programisty.
Nie w każdym przykładowym kodzie zawarłem pełne sprawdzanie błędów – wynikało to z chęci zwiększenia czytelności listingów i redukcji ich długości, która w przeciwnym razie mogłaby być przytłaczająca dla bardziej początkujących Czytelników. W przypadku rozwijania kodu produkcyjnego (tj. o wysokiej jakości) pełne sprawdzanie błędów jest w zasadzie obowiązkowe, choć oczywiście nie każdy tworzony kod musi przystawać do takich standardów. W trakcie pracy nad pomocniczymi narzędziami jednorazowego użytku czy rozwiązaniami zadań podczas konkursów trwających kilka lub kilkadziesiąt godzin obranie drogi „na skróty” może nierzadko zaoszczędzić sporo czasu i okazać się ostatecznie strategią najkorzystniejszą.
W książce oprócz przykładowych listingów kodu występuje również znaczna liczba ramek oznaczonych jako oraz . Celem tych pierwszych jest dokładniejsze przedyskutowanie zagadnień, które pojawiają się w tekście, i są skierowane przede wszystkim do bardziej początkujących Czytelników. Zawartość ramek natomiast znacznie rozwija tematykę i często wykracza poza średni poziom skomplikowania danego rozdziału – jestem przekonany, że nawet zaawansowani programiści mogą w nich znaleźć coś nowego i ciekawego.
Chciałbym również zachęcić do odwiedzenia oficjalnego serwisu „Zrozumieć Programowanie”, w którym można znaleźć przykładowe kody źródłowe, erratę, jak i niewielkie forum stworzone z myślą o dyskusji na tematy poruszane w książce, w tym również o ćwiczeniach i flagach. Znajduje się on pod adresem:
http://gynvael.coldwind.pl/book/
Podziękowania
W powstaniu i nadaniu ostatecznego kształtu tej książce swój udział miało wiele osób, którym chciałbym w tym miejscu podziękować. Mojej żonie Arashi Coldwind za wsparcie okazywane podczas całego czasu trwania tego, bądź co bądź, niemałego projektu, jakim jest napisanie książki. Autorowi przedmowy, a jednocześnie redaktorowi merytorycznemu i mojemu dobremu przyjacielowi Mateuszowi Jurczykowi, który na edycję i korektę tej książki poświęcił ogromną ilość własnego czasu. Tomaszowi Łopuszańskiemu, który wraz ze mną przesiadywał do późnych godzin nocnych, przeglądając i szlifując każdy kolejny nadesłany rozdział. Łukaszowi Łopuszańskiemu, który przekonał mnie do napisania tej książki i doprowadził do jej wydania. Sebastianowi Rosikowi za genialny projekt okładki. Recenzentom merytorycznym, którzy wychwycili znaczą liczbę niedociągnięć obecnych w pierwotnej wersji, a byli to: Paweł „KrzaQ” Zakrzewski, Robert „Jagger” Święcki, Mariusz Zaborski, Unavowed, Michał Leszczyński, Michał Melewski, Karol Kuczmarski, Adam „pi3” Zabrocki, Sergiusz „q3k” Bazański, Tomasz ‚KeiDii’ Bukowski. Testerom, którzy wskazali dodatkowe błędy i nieścisłości, w składzie: Łukasz „Stiltskin” Głowacki, Nism0, Łukasz „Lord Darkstorm”, Trzeciakiewicz, Alan Cesarski. A także Ange Albertiniemu, Mikołajowi Koprasowi, Mattowi Moore’owi, Ferminowi Sernie oraz Michałowi Zalewskiemu.
Mam nadzieję, Drogi Czytelniku, że książka ta będzie dla Ciebie ciekawą i inspirującą lekturą.
Gynvael Coldwind
Zurych, wrzesień 2015 r.
Zgłaszanie błędów i errata
W idealnym wszechświecie napisałbym książkę bez błędów, w której nie byłoby miejsca na literówki czy brakujące przecinki. Niestety, książka ta pochodzi z naszego wszechświata, więc wbrew wszelkim staraniom błędy na pewno się pojawią.
Z tego względu chciałbym zachęcić Czytelników do zaglądania od czasu do czasu na stronę z erratą, którą będę aktualizował przy okazji każdego znalezionego lub zgłoszonego błędu merytorycznego. Erratę można znaleźć pod adresem:
http://gynvael.coldwind.pl/book/errata
Chciałbym również zachęcić Czytelników do zgłaszania wszelkiego rodzaju błędów, zarówno merytorycznych, jak i językowych – wszystkie zauważone niedociągnięcia będą eliminowane w kolejnych wydaniach książki. Informacje na temat wykrytych błędów proszę zgłaszać pod poniższym adresem:
http://gynvael.coldwind.pl/book/bugbounty
Dodatkowo, naśladując niejako Donalda Knutha, postaram się wysłać pamiątkową pocztówkę każdemu Czytelnikowi, który jako pierwszy zgłosi dany błąd merytoryczny. Szczegóły tego swoistego bug bounty można również znaleźć na wspomnianej stronie internetowej.Część I Kilka codziennych czynności
Ryzykując otarcie się o banał, napiszę, że w skład umiejętności niezbędnych programiście wchodzą:
- Umiejętność projektowania architektury programów, funkcji, klas, protokołów itp.
- Znajomość algorytmów, struktur danych i wzorców projektowych.
- Znajomość przynajmniej jednego języka programowania i sprawność w posługiwaniu się nim.
- Umiejętność, którą osobiście określam mianem „tłumaczenia myśli na kod”.
Jak się często okazuje, umiejętności te są konieczne, ale nie zawsze wystarczające, aby biegle tworzyć i analizować oprogramowanie. Wynika to z dwóch faktów: programy ani nie działają w próżni, ani nie są tworzone w jednolity sposób przez niewielką grupę osób. Oznacza to, że programista musi zapoznać się również z ekosystemem, w którym są tworzone i wykonywane jego programy, oraz pogodzić się z myślą, że inni programiści tworzą kod w odmiennych językach bądź na podstawie innych zasad (lub ich braku).
W niniejszym rozdziale chciałbym wskazać i opisać kilka codziennych czynności, które „przytrafiają się” programistom. Dodam, że niektóre z nich mogą być konieczne do zrozumienia i prawidłowej interpretacji pewnych fragmentów książki; w szczególności chciałbym zachęcić do zapoznania się z rozdziałami: „Konsola i interpreter poleceń” – to właśnie konsolę wykorzystuję w zdecydowanej większości przykładów w niniejszej książce, oraz „Czytanie nieznanego języka”, ponieważ przykładowe listingi zostały sporządzone w różnych językach, a często również w odmiennych stylach tworzenia kodu.