Autor: Allen B. Downey

Tutuł oryginału - How to Think Like a Computer Scientist, Java Version, 4th Edition

Treść oryginału dostępna jest pod adresem http://www.greenteapress.com/thinkapjava/ .

Niniejszy tekst jest tłumaczeniem powyższej pozycji. Jeżeli chciałabyś (chciałbyś) wspomóc proces tłumaczenia, twój czas i zaangażowanie są bardzo mile widziane. Zapoznaj się z oryginalnym tekstem, skoncentruj się na którymś z rozdziałów i zacznij tłumaczyć. Wszelkie przetłumaczone akapity umieść tutaj w odpowiednim rozdziale, tak aby ktoś inny nie tłumaczył po raz drugi tego, co raz już zostało przez Ciebie przetłumaczone.

Przedmowa

Dlaczego napisałem tę książkę

To jest czwarta edycja książki, którą rozpocząłem pisać w 1999 roku, kiedy uczyłem w Colby College. Uczyłem początkującą klasę informatyczną języka programowania Java. Nie znalazłem jednak podręcznika, który by mnie uszczęśliwił. Z jednej strony, istniejące podręczniki były zbyt obszerne! Nie było możliwości, by moi studenci przeczytali 800 stron gęstego, technicznego materiału, nawet gdybym tego od nich oczekiwał. I nie oczekiwałem. Większość materiałów było zbyt szczegółowych - o języku Java i jego bibliotekach. Wszystko to mogłoby się okazać nieaktualne pod koniec semestru. Wszystko to przesłaniało także materiał, który faktycznie chciałem moim studentom przekazać.

Innym problemem, z którym się spotkałem, było to, że wstęp do programowania zorientowanego obiektowo był zbyt gwałtowny. Wielu studentów, którzy do tej pory radzili sobie bardzo dobrze, rozkładali ręce, gdy dochodzili do obiektów.

[...]

Droga do programowania

Podstawowym celem tej książki jest nauczenie ciebie myślenia jak programista. Osobiście lubię osoby, ktore myślą w taki sposob jak programiści, ponieważ łączą w sobie to co najlepsze w matematykach, inżynierach i naukowcach. Podobnie do matematyków programiści używają specyficznych języków w celu zapisania pomysłów (w szczególności dotyczących obliczeń). Podobnie do inżynierów, projektują układy łączące się w systemy, ewoluujące w kierunku doskonalszych rozwiązań. Podobnie do naukowców, obserwują zachowanie skomplikowanych systemów, formułują hipotezy, oraz testują je doświadczalnie.

Najważniejszą umiejętnością programisty jest rozwiązywanie problemów. Mówiąc to mam na myśli zdolność do formułowania problemów, kreatywnego myślenia na temat rozwiązania oraz zrozumiałego i właściwego wyrażania rozwiązania problemu. Dzięki temu nauka programowania jest wspaniałą okazją do ćwiczenia umiejętności rozwiązywania problemów. Dlatego właśnie nazwałem ten rozdział "Droga do programowania".

[...]

Czym jest język programowania?

Język programowania, którego będziesz się właśnie uczyć to Java. Jest to relatywnie nowy język (Sun wydał jego pierszą wersję w maju 1995 roku). Java jest przykładem języka programowania wysokiego poziomu. Inne języki wysokiego poziomu, o których mogłeś słyszeć to Pascal, C, C++ jak również FORTRAN.

Jak zapewne domyślasz się po nazwie "język wysokiego poziomu", istnieją również języki niskiego poziomu, czasami zwane językami maszynowymi lub asemblerami. Mówiąc najprościej, komputery potrafią bezpośrednio wykonywać wyłącznie programy napisane w języku niskiego poziomu. Dlatego programy napisane w języku wysokiego poziomu muszą zostać przetłumaczone na język niskiego poziomu zanim zostaną wykonane przez komputer. To tłumaczenie zajmuje nieco czasu, co jest pewną niedogodnością języków wysokiego poziomu.

Jednak ich zalet jest znacznie więcej. Po pierwsze, o wiele prościej jest pisać programy w języku wysokiego poziomu. Mówiąc "prościej" mam na myśli to, iż znacznie mniej czasu potrzeba, by program napisać. Jest on krótszy i bardziej czytelny, ponadto znacznie łatwiej wyszukiwać w nim błedy i wprowadzać poprawki. Po drugie, programy napisane w językach wysokiego poziomu są znacznie bardziej przenośne, tzn. można je uruchamiać na wielu rodzajach komputerów praktycznie bez potrzeby wprowadzania dodatkowych modyfikacji. Programy napisane w języku niskiego poziomu mogą być uruchamiane wyłącznie na platformie, na którą zostały napisane. W celu uruchomienia programu na innej platformie należałoby taki program przepisać od podstaw.

Ze względu na powyższe zalety, praktycznie wszystkie programy pisane są w językach wysokiego poziomu. Języki niskiego poziomu używane są w nielicznych specjalizowanych aplikacjach.

Istnieją dwie drogi przetłumaczenia programu napisanego w języku wysokiego poziomu do języka niskiego poziomu tak, by mógł być uruchomiony na komputerze: interpretacja oraz kompilacja. Interpreter to program odczytujący i jednocześnie wykonujący zawartość programu w języku wysokiego poziomu wiersz po wierszu.

Kompilator to program, który odczytuje i tłumaczy zawartość programu wysokiego poziomu w całości przed wykonaniem jakiejkolwiek komendy tego programu. Często kompilacja programu przebiega jako osobny krok. Skompilowany kod uruchamiany jest później. W tej sytuacji program napisany w języku wysokiego poziomu nazywamy kodem źródłowym, natomiast całkowicie przetłumaczony program - kodem obiektowym lub plikiem wykonywalnym.

Jako przykład proponuję ci napisać program w języku C. Być może użyjesz w tym celu edytora tekstu (edytor tekstu to uproszczony procesor tekstu). Kiedy program będzie skończony, zapiszesz go w pliku program.c, gdzie słowo program jest nazwą nadaną przez ciebie, natomiast końcówka .c jest, zgodnie z umową, rozszerzeniem nazwy pliku informującą, że plik zawiera kod źródłowy napisany w języku C.

Potem, w zależności od ulubionego środowiska programistycznego, opuścisz edytor tekstu i uruchomisz kompilator. Kompilator odczyta kod źródłowy twojego programu, przetłumaczy go i utworzy nowy plik o nazwie program.o (dla kodu obiektowego) lub program.exe (dla pliku wykonywalnego).

Język Java jest pod tym względem wyjątkowy, gdyż jest językiem zarówno kompilowanym jak i interpretowanym. Zamiast tłumaczyć programy w Javie do języka maszynowego, kompilator Javy generuje kod bajtowy Javy. Kod bajtowy jest prosty (i szybki) w interpretacji, zupełnie jak kod maszynowy. Jednocześnie jest równie przenośny jak języki wysokiego poziomu. Dzięki temu możliwa jest kompilacja programu w Javie na jednym komputerze, przesłanie kodu bajtowego do innego komputera przez sieć komputerową, oraz interpretacja kodu bajtowego przez inny komputer. Jest to zaletą języka Java, której nie posiadają inne języki wysokiego poziomu.

Choć powyższy proces może wydawać się skomplikowany, w większości środowisk programistycznych (czasem zwanych środowiskami rozwojowymi), te kroki zostały zautomatyzowane dla użytkownika. Zazwyczaj będziesz musiał tylko napisać program i nacisnąć przycisk (lub wydać pojedynczą komendę) by skompilować i uruchomić swój program. Z drugiej strony, dobrze jest znać wszystkie etapy zautomatyzowanego procesu, tak aby w sytuacji, gdy coś pójdzie nie po naszej myśli, móc zorientować się, gdzie leży przyczyna.

Czym jest program? Program jest ciągiem instrukcji, które określają, jak wykonać obliczenia. Obliczenia matematyczne mogą być czymś matematycznym, na przykład algorytm rozwiązania układu równań lub znalezienie pierwiastka wielomianu, ale mogą to być również obliczenia symboliczne, jak wyszukiwanie i zamiana tekstu w dokumencie lub (o dziwo) kompilacji programu .

Instrukcje, które nazywamy wyrażeniami, wyglądają inaczej w różnych językach programowania, ale istnieje kilka podstawowych operacji, które wykonuje większość języków:

wejście (input):

Pobierz dane z klawiatury lub pliku, lub z innego urządzenia. wyjście (output) :

Wyświetlanie danych na ekranie lub wysyłanie danych do pliku lub innego urządzenia. operacje matematyczne:

Wykonywanie podstawowych operacji matematycznych, takich jak dodawanie czy mnożenie. testowanie:

Testowanie na pewnych określonych warunkach i uruchamianie odpowiedniej sekwencji instrukcji. pętle:

Wykonywanie jakiejś akcji wielokrotnie, zwykle z pewnymi zmianami.

To prawie wszystko, co jest niezbędne. Każdy program, jaki kiedykolwiek był używany, bez względu na to, jak skomplikowany, składa się z instrukcji, które wykonują te przedstawione wyżej czynności. Zatem jednym ze sposobów, aby opisać programowanie to proces dzielenia dużego, skomplikowanego zadania na mniejsze podzadania (podproblemy), aż staną się one proste do wykonania z wykorzystaniem tych podstawowych operacji.

Co to jest debugowanie? Z dziwnego powodu błędy w programowaniu nazywane są bug'ami a proces ich odszukiwania i poprawiania - debugowaniem. Istnieją trzy rodzaje błędów, które mogą wystąpić w aplikacji, a ich rozpoznawanie pomaga w szybszym ich odnajdywaniu.

Błędy składniowe Kompilator potrafi przetłumaczyć program tylko jeżeli został on napisany poprawnie składniowo. W przeciwnym wypadku kompilacja zakończy się niepowodzeniem i nie będziesz mógł uruchomić swojego programu. Składnia to również struktura twojego kodu i zasady związane z tą strukturą. Dla przykładu w języku polskim zdanie musi się zaczynać wielką literą i kończyć kropką. to zdanie zawiera błąd składniowy. To również

Dla większości czytelników kilka błędów składniowych nie jest znaczącym problemem, dzięki czemu potrafimy czytać poezję bez wyrzucania błędów.

Kompilatory niestety nie są tak wyrozumiałe. Jeżeli gdziekolwiek w Twoim kodzie jest błąd składniowy kompilator wyświetli komunikat błędu i zakończy się - nie będziesz mógł uruchomić swojego programu.

Aby było jeszcze trudniej, więcej jest zasad składniowych w Java niż jest ich w języku angielskim, a komunikaty błędów kompilatora bywają mało pomocne. Podczas pierwszych tygodni swojej kariery jako programista spędzisz zapewne dużo czasu wyszukując błędy składniowe. Jednak wraz ze zdobywanym doświadczeniem będziesz popełniać ich coraz mniej i odszukiwać szybciej.

Błędy podczas działania

Drugim rodzajem błędów są błędy występujące podczas działania programu (ang. run-time error), nie pojawią się dopóki nie uruchomisz aplikacji. W Java błędy te występują gdy interpreter uruchamia kod bajtowy i coś idzie nie tak.

Java zmierza do bycia pewnym i bezpiecznym językiem, co oznacza że kompilator wyłapuje wiele błędów. Tak więc błędy podczas działania programu są rzadkie, zwłaszcza w skali drobnych aplikacji.

W Java błędy te nazywane są wyjątkami i w większości środowisk pojawiają się jako okienka zawierające informacje o tym co się wydarzyło i czym program się zajmował w momencie wystąpienia błędu - te informacje są przydatne przy debugowaniu.

Błędy logiczne i semantyczne Trzecim rodzajem błędów są błędy logiczne i semantyczne. Jeżeli w twoim kodzie występuje błąd logiczny skompiluje i uruchomi się on bez generowania błędów, ale nie zrobi tego co powinien. Zrobi coś innego. Uściślając, zrobi to co ty mu powiesz by zrobił.

Problem polega na tym, że program który napisałeś nie jest tym programem który chciałeś napisać. Semantyka lub znaczenie programu, są błędne. Zidentyfikowanie błędów logicznych może być trudne, ponieważ musisz pracować na odwrót - obserwując efekty działania programu próbować zrozumieć co zostało wykonane.

Debugowanie eksperymentalne Jedną z najważniejszych umiejętności, których nauczysz się na tych zajęciach jest debugowanie. Pomimo tego, że może ono być frustrujące, jest jednym z najbardziej interesujących, wymagających i wartościowych elementów programowania.

Debugowanie jest jak praca detektywa. Konfrontujesz się z podpowiedziami i musisz wydedukować proces i zdarzenia, które doprowadziły do rezultatu, który widzisz.

Debugowanie jest również jak nauka eksperymentalna. W momencie gdy masz pomysł co się dzieje źle zmodyfikuj swój program i spróbuj ponownie. Jeżeli twoja hipoteza była trafna możesz przewidzieć rezultat modyfikacji i robisz krok w kierunku działającego kodu. Jeżeli jednak hipoteza była błędna musisz wymyślić inną. Jak Sherlock Holmes zauważył, "Jeżeli wyeliminowałeś niemożliwe, cokolwiek pozostało, jakkolwiek nieprawdopodobne, musi być prawdą" (The Sign of Four, A. Conan Doyle).