Instalacja, użytkowanie i pielęgnacja Hitachi Rak 18nh6 jest łatwa, dzięki łatwej instalacji i intuicyjnemu sterowaniu. Hitachi Rak 18nh6 jest łatwy w montażu i obsłudze, dzięki czemu można go łatwo skonfigurować i uruchomić. Wystarczy podłączyć wszystkie niezbędne przewody i włączyć przełącznik zasilania, aby uruchomić system. Użytkowanie Hitachi Rak 18nh6 jest proste i intuicyjne, dzięki czemu można szybko i łatwo skonfigurować ustawienia i uzyskać optymalne wyniki. Ponadto, system jest łatwy w pielęgnacji i konserwacji - wystarczy regularnie czyścić i usuwać kurz z obudowy, aby zapewnić długotrwałe działanie urządzenia.
Ostatnia aktualizacja: Instalacja, użytkowanie i pielęgnacja Hitachi Rak 18nh6
Na zakończenie rozważań o paradygmatach programowania chcemy przedstawić krótkie zestawienie ich charakterystycznych cech. Korzystając z tej sposobności, chcemy również wspomnieć o kilku paradygmatach, których nie omawialiśmy. Powiemy m. in. o programowaniu współbieżnym i o programowaniu sterowanym zdarzeniami.
Wstęp
Przypomnijmy, jak zdefiniowaliśmy paradygmat programowania w pierwszym wykładzie. Otóż jest to zbiór mechanizmów, jakich programista używa, pisząc program oraz jak ów program jest następnie wykonywany przez komputer. Można zatem powiedzieć, że paradygmat programowania to ogół oczekiwań programisty wobec języka programowania i komputera, na którym będzie działał program.
Wykład skupił się na czterech głównych paradygmatach: imperatywnym, obiektowym, funkcyjnym i logicznym. Te cztery wybraliśmy jako „sztandarowe”, ukazujące główne nurty myślenia o programowaniu — choć niekoniecznie najbardziej rozpowszechnione. O ile rozpowszechnienie programowania imperatywnego i obiektowego jest ogromne, to czyste programowanie funkcyjne, a tym bardziej logiczne, jest już rzadsze. Teraz, przy okazji podsumowania, warto więc powiedzieć kilka słów o kilku innych paradygmatach.
Podsumowanie sztandarowej czwórki
Programowanie imperatywne
Chcąc najkrócej scharakteryzować programowanie imperatywne, moglibyśmy napisać „zrób najpierw to, a potem tamto”. Mamy zatem sekwencję poleceń zmieniających krok po kroku stan maszyny, aż do uzyskania oczekiwanego wyniku — czyli mamy stan będący funkcją czasu. Ten sposób patrzenia na programy związany jest ściśle z budową sprzętu komputerowego o architekturze von Neumanna, w którym poszczególne instrukcje to właśnie polecenia zmieniające ów globalny stan.
Imperatywne języki programowania posługują się abstrakcjami bliskimi architekturze von Neumanna, np. zmienne są abstrakcją komórek pamięci. Naturalną abstrakcją są tu też procedury (będące, notabene, zasadniczym elementem „podparadygmatu” proceduralnego). Najważniejsze — w swoim czasie — języki imperatywne to Fortran, Cobol, Pascal i C.
Programowanie obiektowe
W programowaniu obiektowym program to zbiór porozumiewających się ze sobą obiektów, czyli jednostek zawierających określone dane i umiejących wykonywać na nich określone operacje. Najważniejsze są tu dwie cechy: po pierwsze, powiązanie danych (czyli stanu) z operacjami na nich (czyli poleceniami) w całość, stanowiącą odrębną jednostkę — obiekt; po drugie, mechanizm dziedziczenia, czyli możliwość definiowania nowych, bardziej złożonych obiektów, na bazie obiektów już istniejących.
Z tych dwóch cech bierze się zapewne wielki sukces paradygmatu obiektowego. Umożliwia on bowiem modelowanie zjawisk rzeczywistego świata w uporządkowany, hierarchiczny sposób — od idei do szczegółów technicznych. Wśród najważniejszych języków należy wymienić C++ (chociaż nie jest to język czysto obiektowy) i Javę; ze względów historycznych i poznawczych należałoby dodać Simulę 67 i Smalltalk.
Programowanie funkcyjne
Tu po prostu składamy i obliczamy funkcje, w sensie podobnym do funkcji znanych z matematyki. Nie ma stanu maszyny — nie ma zmiennych mogących zmieniać wartość. Nie ma zatem „samodzielnie biegnącego” czasu, a jedynie zależności między danymi. Nie ma efektów ubocznych. Można by wręcz sądzić, że programowanie funkcyjne zdefiniowane zostało jako poważne ograniczenie paradygmatu imperatywnego... Rzeczywiście, do pewnego stopnia zwykłe języki imperatywne zawierają w sobie „podjęzyk” funkcyjny (można przecież tworzyć, składać i wywoływać funkcje). Prawdziwe języki funkcyjne oferują jednak znacznie więcej, m. rekurencyjne struktury danych i możliwość operowania funkcjami wyższego rzędu.
Programowanie funkcyjne nie doczekało się takiej popularności jak dwa poprzednie paradygmaty, choć są dziedziny, gdzie jego pozycja jest przyzwoita (np. język Erlang używany w telekomunikacji oraz język K używany do obliczeń finansowych). Najsłynniejsze języki funkcyjne żyły lub żyją przede wszystkim w środowiskach akademickich: Lisp, Scheme (potomek Lispu), ML, Ocaml (potomek ML-a), Miranda, Haskell.
Programowanie w logice
Podobnie jak w programowaniu funkcyjnym, nie „wydajemy rozkazów”, a jedynie opisujemy, co wiemy i co chcemy uzyskać (z tego powodu języki funkcyjne i logiczne nazywa się łącznie językami deklaratywnymi). Na program składa się zbiór zależności (przesłanki) i pewne stwierdzenie (cel). Wykonanie programu to próba udowodnienia celu w oparciu o podane przesłanki, a więc pewien rodzaj automatycznego wnioskowania; obliczenia wykonywane są niejako „przy okazji” dowodzenia celu.
Język programowania w logice (a ściślej — jego interpreter) to właściwie system automatycznego dowodzenia twierdzeń, działający w oparciu o nieco uproszczony rachunek predykatów. Kluczowym pojęciem jest tu rezolucja, realizowana m. przy pomocy unifikacji i nawrotów. Zastosowania programowania w logice obejmują przede wszystkim sztuczną inteligencję (np. systemy ekspertowe, rozpoznawanie obrazów) i przetwarzanie języka naturalnego. Językiem, który uzyskał największą popularność, jest Prolog. Historycznie ważny jest również Planner — wcześniejszy i bardziej złożony od Prologu.
Inne paradygmaty
Oczywiście „wielka czwórka” to nie wszystko. Warto wspomnieć jeszcze o kilku paradygmatach, które można by określić mianem niszowych bądź cząstkowych. Chodzi nam o to, że dotyczą one albo dość szczególnych rodzajów programowania (np. programowanie sterowane przepływem danych), albo odnoszą się tylko do niektórych cech programowania (np. programowanie strukturalne).
Programowanie strukturalne
O programowaniu strukturalnym wspominamy z kronikarskiego obowiązku, jest to bowiem bardzo dobrze znany i powszechnie stosowany „podparadygmat” programowania imperatywnego, czy ściślej — proceduralnego. Chodzi w nim o tworzenie programów z kilku dobrze zdefiniowanych konstrukcji takich jak instrukcja warunkowa if-then-else i pętla while, za to bez skoków (go to). Powinno to sprzyjać pisaniu programów przejrzystych, łatwych w rozumieniu i utrzymaniu.
Ściślej, Dijkstra proponował użycie tylko trzech rodzajów struktur sterujących:
- Sekwencja (lub konkatenacja) — czyli po prostu wykonanie instrukcji w określonej kolejności. W wielu językach rolę „operatora konkatenacji instrukcji” spełnia niepozorny średnik...
- Wybór — czyli wykonanie jednej z kilku instrukcji zależnie od stanu programu. Przykładem jest if-then-else i switch/case.
- Iteracja, czyli powtarzanie instrukcji tak długo, jak długo spełniony (lub niespełniony) jest dany warunek. Chodzi oczywiście o pętle, np. while, repeat-until, for itp.
Programowanie strukturalne | Programowanie niestrukturalne |
Powyższe struktury stosuje się do „małych” jednostek programu, złożonych z elementarnych instrukcji, czyli np. podstawień, wywołań procedur lub instrukcji wejścia-wyjścia. „Duże” jednostki powinny być — wedle zasad programowania strukturalnego — rozbite na mniejsze (funkcje, procedury, bloki itp. ), tak by można było zrozumieć poszczególne fragmenty bez rozumienia całości.
Z programowaniem strukturalnym powszechnie kojarzy się też niechęć do instrukcji skoku. Rzeczywiście Dijkstra był bardzo przeciwny instrukcji skoku, uważając, że zaciemnia ona strukturę programu i w rezultacie pogarsza jego jakość. Oponenci Dijkstry twierdzili natomiast, że w pewnych sytuacjach użycie skoku jest naturalne i bardziej czytelne, niż usilne unikanie go za pomocą dodatkowych zmiennych, warunków i testów. Na dwóch biegunach znalazły się w swoim czasie języki Basic (tylko skoki, żadnych „przyzwoitych” struktur) i Pascal (modelowy język strukturalny, choć i w nim skoki są dopuszczalne... ).
Do dzisiaj dyskusja nad skokami zdążyła już gruntownie ostygnąć. Na ogół wszyscy się zgadzają, że programowanie strukturalne jest pożyteczne, choć w pewnych sytuacjach użycie skoku wcale nie zasługuje na potępienie. Rozpowszechniły się konstrukcje językowe, nieco bardziej liberalne niż pierwotne idee Dijkstry, zapewniające programiście wygodę bez poświęcania przejrzystości programu. Przykładowo:
- Instrukcja return pozwala pisać funkcje z wieloma punktami wyjścia.
- Instrukcja break pozwala opuścić pętlę w dowolnym miejscu.
- Obsługa wyjątków daje nam możliwość zajęcia się sytuacjami wyjątkowymi bez mnożenia zbędnych bytów (zmiennych, warunków itp. ).
Praktycznie wszystkie języki programowania — nawet te pierwotnie niestrukturalne, np. Fortran i Basic — pozwalają dzisiaj pisać programy strukturalne, choć tylko nieliczne zabraniają stosowania skoków. Idea programowania strukturalnego odniosła więc sukces dydaktyczny (wielki) i komercyjny (nieco mniejszy).
Programowanie sterowane przepływem danych
Jest to w praktyce paradygmat „niszowy”, odnoszący się raczej do szczególnych sytuacji, a nie do programowania w ogóle — mimo iż jego pomysłodawcy uważali, że to właśnie programowanie sterowane przepływem danych powinno być jak najbardziej naturalne i powszechne. Chodzi o to, by program postrzegać jako graf operacji, między którymi przepływają dane. Moment wykonania danej operacji nie jest więc zależny od liniowej sekwencji instrukcji, lecz od dostępności danych — a przecież w końcu to dane są najważniejsze... Ten pomysł można w pewnym uproszczeniu zobrazować przez analogię do linii produkcyjnej. Przy linii znajdują się stanowiska, gdzie wykonywane są pewne operacje. Operacja jest wykonywana, gdy tylko przy stanowisku pojawi się przetwarzany przedmiot (czyli dane).
Zauważmy, że taki model bardzo dobrze nadaje się do równoległego wykonywania programu na wielu procesorach. Rozkład zadań na procesory uzyskujemy tu automatycznie, bez konieczności pisania dodatkowego, uciążliwego kodu rozdzielającego zadania. Z myślą o programowaniu równoległym powstały zresztą niektóre ważne języki, np. Sisal wykorzystywany do programowania superkomputerów Cray i język G, będący częścią środowiska LabView i służący do programowania aparatury pomiarowej.
Najbardziej rozpowszechnionym jednak przykładem programowania sterowanego przepływem danych jest arkusz kalkulacyjny. Zmiana wartości w komórce arkusza powoduje automatyczne przeliczenie zawartości innych komórek, zgodnie z grafem zależności pomiędzy nimi. W szczególności, zmiana jednej komórki może spowodować kaskadę zmian w komórkach powiązanych łańcuchem zależności.
Drugi przykład to rozwiązania stosowane we współczesnych procesorach. Procesor posiada kilka jednostek arytmetyczno-logicznych i stara się je wykorzystywać, gdy tylko są dostępne odpowiednie dane, niekoniecznie zgodnie z oryginalną kolejnością instrukcji w programie. Wymaga to skomplikowanego śledzenia i oznaczania danych pomiędzy operacjami. Proces ten można sobie wyobrazić jako „okienko” podążające za instrukcjami programu; instrukcje mieszczące się wewnątrz okienka są wykonywane w sposób sterowany przepływem danych, choć samo okienko przesuwa się zgodnie z przepływem sterowania w programie. Ze względu na złożoność tego procesu, w praktyce możliwe jest obsłużenie jedynie niewielkiej liczby jednostek arytmetyczno-logicznych (np. sześć jednostek w procesorach Pentium), a w okienku mieści się ograniczona liczba instrukcji (nieco ponad sto). Komputery stosujące tę technikę budowano już w latach 60-tych XX wieku; „pod strzechy”, czyli do mikroprocesorów, trafiła ona jednak dopiero w połowie lat 90-tych.
Trzeci przykład, bardzo skromny, to znane z systemu Unix potoki. Graf zależności między operacjami jest tu bardzo prosty (kreska, i to zazwyczaj niedługa), ale idea wykonywania operacji w miarę dostępności danych jest zachowana.
Programowanie sterowane zdarzeniami
Chodzi o programowanie, w którym zamiast zasadniczego nurtu sterowania mamy wiele drobnych programów obsługi zdarzeń, uruchamianych w chwili wystąpienia odpowiedniego zdarzenia. Zdarzenia mogą być wywoływane przez urządzenia wejścia-wyjścia (np. naciśnięcie klawisza, ruch myszką) lub przez same programy obsługi zdarzeń. Oprócz zbioru programów obsługi zdarzeń potrzebny jest też zarządca, który będzie je uruchamiał.
Przykłady programowania sterowanego zdarzeniami są znacznie częstsze niż można by sądzić. Każdy system operacyjny jest — do pewnego stopnia — sterowany zdarzeniami: reaguje na przerwania. Rolę zarządcy spełnia tu procesor komputera. Z kolei sam system operacyjny jest zarządcą w stosunku do uruchomionych pod jego kontrolą procesów.
Inny typowy przykład to serwery bazodanowe, w których procedury mogą być uruchamiane w odpowiedzi na ustalone zdarzenia.
Programowanie współbieżne
Tym razem mówimy o „nadparadygmacie”, gdyż chodzi o wykonywanie wielu zadań obliczeniowych w tym samym czasie. Istotą problemu jest koordynacja zadań, które komunikują się ze sobą i korzystają ze wspólnych zasobów, a tym samym są od siebie zależne. Pojęcie programowania współbieżnego jest ogólniejsze od programowania równoległego i od programowania rozproszonego. Równoległość oznacza równoczesne wykonywanie zadań przez wiele procesorów; współbieżność obejmuje ponadto podział czasu jednego procesora między wiele zadań — czyli to, z czym mamy do czynienia w praktycznie każdym systemie operacyjnym. O programowaniu rozproszonym mówimy, gdy mamy wiele procesorów połączonych siecią (ale nie wieloprocesorowy komputer).
Komunikacja między współbieżnymi zadaniami może być niejawna, ale najczęściej mamy do czynienia z jawną komunikacją przy użyciu jednego z dwóch podstawowych mechanizmów:
- Wspólna pamięć: porozumiewanie się następuje przez zmianę wartości umówionych komórek pamięci. Zwróćmy uwagę na związek tego mechanizmu z paradygmatem imperatywnym.
- Przekazywanie komunikatów: ta metoda wymaga w praktyce bardziej rozbudowanego wsparcia ze strony systemu operacyjnego, ale jest łatwiejsza do matematycznego okiełznania — co powinno sprzyjać poprawności programów.
Mimo że programowanie współbieżne liczy już praktycznie kilkadziesiąt lat (pierwsze współbieżne systemy operacyjne powstały na początku lat 60-tych XX wieku), znajduje ono słabe odbicie w językach programowania. Przez długie lata było ono głównie domeną twórców systemów operacyjnych, później pojawiło się w innych dziedzinach, np. w oprogramowaniu dla telekomunikacji, na potrzeby którego powstał wspominany już język Erlang, obejmujący obsługę współbieżnych procesów. Innym przykładem języka z wbudowaną mechanizmami obsługi współbieżności jest Ada. W dzisiejszych czasach duża część programowania współbieżnego „dzieje się” w Javie, choć wsparcie dla współbieżności w samym języku jest raczej elementarne. Tym niemniej to właśnie Java przyczyniła się wydatnie do rozpowszechnienia programowania współbieżnego.
Programowanie strukturalne – paradygmat programowania opierający się na podziale kodu źródłowego programu na procedury i hierarchicznie ułożone bloki z wykorzystaniem struktur kontrolnych w postaci instrukcji wyboru i pętli. Rozwijał się w opozycji do programowania wykorzystującego proste instrukcje warunkowe i skoki. Programowanie strukturalne zwiększa czytelność i ułatwia analizę programów, co stanowi znaczącą poprawę w stosunku do trudnego w utrzymaniu „spaghetti code” często wynikającego z użycia instrukcji goto.
Początki programowania strukturalnego przypadają na Lata 60. XX wieku, a ważnym głosem w dyskusji o programowaniu strukturalnym był list Edsgera Dijkstry Goto Statement considered harmful.
Język programowania zgodny z paradygmatem programowania strukturalnego nazywa się językiem strukturalnym.
Cechy charakterystyczne[edytuj | edytuj kod]
Struktury kontrolne[edytuj | edytuj kod]
Podstawowe struktury kontrolne jakie wymienia twierdzenie o programowaniu strukturalnym, z których możliwe jest zbudowanie dowolnego programu to:
- Sekwencja – wykonanie ciągu kolejnych instrukcji
- Wybór – w zależności od wartości predykatu wykonywana jest odpowiednia instrukcja. W językach programowania zazwyczaj reprezentowana przez słowa kluczowe
if.. then.. else
. - Iteracja – wykonywanie instrukcji póki spełniony jest jakiś warunek. Reprezentowana w różnych wariantach jako pętle oznaczane między innymi przez:
while
,repeat
,for
lubdo.. until
.
Każda ze struktur kontrolnych może być też rozumiana jako pojedyncza instrukcja. Według pierwotnych założeń struktury kontrolne powinny posiadać jedno wejście i jedno wyjście.
Podprogramy[edytuj | edytuj kod]
Podprogramy pozwalają na wydzielenie pewnej grupy instrukcji i traktowania ich jako pojedynczej operacji, są dodatkowo mechanizmem abstrakcji.
Bloki[edytuj | edytuj kod]
W językach programowania bloki odpowiadają sekwencjom instrukcji, umożliwiając budowanie programu przez komponowanie struktur kontrolnych – w miejscu, w którym umieścimy blok z instrukcjami jest on traktowany jak pojedyncza instrukcja.
W kodzie źródłowym programów bloki są wyróżniane na różne sposoby, przykładowo ograniczone przez if.. fi
jako blok dla instrukcji if
w ALGOLU 68, czy dowolne bloki instrukcji obejmowanie poprzez BEGIN.. END
w Pascalu, PL/I, przy pomocy wcięć w Pythonie czy Haskellu lub poprzez nawiasy klamrowe w języku C i pochodnych.
Historia[edytuj | edytuj kod]
Przed programowaniem strukturalnym[edytuj | edytuj kod]
Pierwsze komputery były programowane wprost z użyciem kodu maszynowego[1] lub z wykorzystaniem asemblera. Pierwsze asemblery przypadają na połowę lat 50. W 1954 roku Nathaniel Rochester napisał asembler dla IBM 701, natomiast w 1955 Stan Poley stworzył SOAP – asembler dla komputera IBM 650, początkowo programowanego wyłącznie przy pomocy kodu maszynowego[2]. Kontrola przepływu w programie odbywała się głównie przy pomocy warunkowych i bezwarunkowych instrukcji skoku, w ówczesnych komputerach IBM określanych jako branch
lub instrukcje transferu[3][4].
Wprowadzony w roku 1957 FORTRAN, pierwszy poważny język programowania wysokiego poziomu, główny nacisk kładł na formuły arytmetyczne. Występujące w nim struktury (a raczej instrukcje) kontrolne nie wykraczały daleko poza możliwości instrukcji skoku w asemblerach[4] – język, poza skokiem bezwarunkowym, udostępniał przypisywalne (assigned goto
) i obliczalne (computed goto
) instrukcje skoku, oraz zbliżone do obliczalnego goto wyrażenie arytmetycznego (nie logicznego) if
. Skoki były wykonywane do etykiet reprezentowanych przez wartości liczbowe. Dodatkowo występowała też prosta pętla.
ALGOL[edytuj | edytuj kod]
Opublikowany w roku 1958 ALGOL 58 oraz jego dwa lata późniejsza, mocno rozwinięta wersja ALGOL 60, wprowadziły wiele kluczowych konstrukcji programistycznych, istotnych nie tylko z punktu widzenia programowania strukturalnego. Był to pierwszy język, w którym pojawił się koncept instrukcji złożonych – bloków – służących do grupowania instrukcji. Blok jest traktowany jako pojedyncza instrukcja i możliwe jest użycie go w miejscu dla niej przeznaczonym.
Język ALGOL wprowadził również fundamentalne dla programowania strukturalnego konstrukcje: logiczne instrukcje warunkowe z opcjonalnym else
, pętle for
oraz instrukcję wyboru switch
. Pozwolił też na deklarowanie procedur, w tym zagnieżdżonych w sobie, wraz z odpowiednim zasięgiem identyfikatorów. Instrukcja goto dalej pozostawała jednak ważnym elementem składniowym języka.
Podstawa teoretyczna[edytuj | edytuj kod]
Jako fundament teorii programowania strukturalnego określa się twierdzenie o programowaniu strukturalnym. Jego autorstwo przypisuje się najczęściej ’Böhmowi i Giuseppe Jacopiniemu, wskazując jako źródło ich pracę Flow Diagrams, Turing Machines And Languages With Only Two Formation Rules z maja 1966 roku[5]. W swojej pracy pokazali oni, że dowolny program zawierający skoki (czyli dowolny graf przepływu), może zostać znormalizowany do odpowiadającego mu ustrukturyzowanego grafu – zbudowanego z trzech podstawowych struktur: oraz wyrażającym odpowiednio: sekwencję, wybór oraz iterację. Ponieważ grafy przepływu mogą wyrażać dowolne funkcje obliczalne, to oznacza, że możemy też takie wyrazić przy pomocy tych podstawowych konstrukcji. W dalszej części pracy opisany jest język P′′ – pierwszy strukturalny język, dla którego udowodniono zupełność w sensie Turinga.
Twierdzenie Böhma i Jacopiniego nie mówi o tym w jaki sposób tworzyć dobre programy strukturalne lub je analizować. Prace nad tymi zagadnieniami odbywały się głównie na przełomie lat 60 i 70, z istotnym wkładem dokonamy przez Edsgera Dijkstrę, Roberta W. Floyda, Tonyego Hoarea, Ole-Johana Dahla, oraz Davida Griesa.
Dyskusja[edytuj | edytuj kod]
Już na etapie projektowania języka ALGOL, w roku 1959, Heinz Zemanek rozważał ograniczenie użycia instrukcji goto, jednak jego uwagi zostały wtedy zignorowane[6]. Niedługo później Hoare proponował ograniczenie użycia skoków tylko do wyjść alarmowych, natomiast w roku 1966 razem z Wirthem proponowali ograniczenia w postaci instrukcji wyboru case
[6][7].
W debacie pomiędzy programistami dotyczącej popularyzacji programowania strukturalnego i ograniczeniu programowania opartego na goto najistotniejszym punktem jest praca Edsgera Dijkstry z 1974 roku A Case against GO TO Statemant opublikowana pod tytułem Goto Statement considered Harmful. Autor w sposób zdecydowany wyraża się przeciwko użyciu tej instrukcji:
Instrukcja go to powinna zostać usunięta z wszystkich „wysokopoziomowych” języków programowania (to znaczy z wszystkich poza – prawdopodobnie - czystym kodem maszynowym)[6].
Odwołuje się też do twierdzenia Böhma i Jacopiniego, które umożliwia pokazanie, że goto jest instrukcją zbędną. Podaje przyczyny, przez które programy używające skoków są trudne w analizie. Dijkstra proponuje też odpowiednie ograniczenia na struktury kontrolne, jak na przykład Instrukcja opuszczenia, tak by dalej pozwalały na odpowiednią analizę, jeśli zestaw podstawowych instrukcji okazałby się zbyt ograniczający.
Jednym z pierwszych dużych komercyjnych projektów wykorzystujących programowanie strukturalne, który odniósł duży sukces było wykonane przez Harlana Millsa z IBM systemu indeksującego zbierane informacje dla New York Times.
Mimo kolejnych sukcesów związanych z aplikacją technik programowania strukturalnego, jak i rozwojowi teorii jej poświęconej, spora liczba programistów wciąż opierała się ograniczeniu lub wyeliminowaniu instrukcji goto z użycia[8]. Donald Knuth w 1974 roku opublikował pracę Structured Programming with GoTo Statements[9], w której opisywał sytuacje gdzie użycie skoku upraszcza rozwiązanie bez wpływu na trudność w jego analizie.
W roku 1987 na łamach Communications of the ACM po liście Franka Rubina „GOTO Considered Harmful” Considered Harmful[10] na nowo rozgorzała dyskusja dotycząca słuszności użycia goto, zarówno z głosami poparcia dla Rubina i użycia skoków, jak i mocnymi głosami przeciwko (razem z tytułami, stopniowo zawierającymi w coraz większej liczbie frazę „Considered Harmful”)[11][12]. Rubin twierdził:
Wiara, że GOTO są złe, stała się doktryną religijną, niepodważalną żadnymi dowodami[10]
Zdaniem edytora była to największa wymiana listów w historii forum[12]. Dyskusję uciął ostry list Dijkstry, poniekąd zawiedzionego poziomem dyskusji, jak i samymi próbami ponownej popularyzacji instrukcji goto[13][14].
Wpływ na języki programowania[edytuj | edytuj kod]
Popularyzacja programowania strukturalnego zaowocowała wprowadzeniem konstrukcji programowania strukturalnego, często inspirowanych ALGOLEM, do języków programowania, które wcześniej ich nie posiadały, takich jak FORTRAN, COBOL czy BASIC.
Częste odstępstwa[edytuj | edytuj kod]
O ile można obserwować zanik użycia goto, to istnieje niewiele czysto strukturalnych języków programowania. Najczęściej poza podstawowymi strukturami kontrolnymi pojawia się możliwość wczesnego wyjścia, łamiąc tym samym zasadę pojedynczego wyjścia z każdej struktury. Obsługa wyjątków również wykracza poza założenia programowania strukturalnego.
Wczesne wyjście[edytuj | edytuj kod]
Najczęściej spotykana jest możliwość wyjścia z danej pętli lub podprogramu. Na poziomie podprogramu jest to zwykle instrukcja return
. W przypadku pętli są to instrukcje break
(przerwij daną pętlę) lub continue
(przerwij daną iterację i przejdź do następnej). W czystym kodzie strukturalnym można napisać równoważne programy z wykorzystaniem dodatkowych instrukcji warunkowych, jednak może istotnie zwiększyć złożoność programów. Język C jest jednym z wczesnych przykładów wprowadzenia tego typu konstrukcji. Niektóre nowe języki programowania wprowadzają instrukcje „etykietowanego break”, które pozwalają opuścić więcej niż jeden poziom zagnieżdżonych pętli w pojedynczym kroku.
Wczesne wyjścia mogą powodować pewne trudności przy tworzeniu programów, związane na przykład z koniecznością zwalniania zaalokowanych zasobów przy każdym miejscu, w którym może być wykonany powrót z danego podprogramu. Występują różne podejścia: Pascal unika tych problemów nie dopuszczając tego typu konstrukcji, natomiast języki obiektowe wysokiego poziomu, takie jak C++ czy Java zawierają odpowiednie mechanizmy (RAII lub odśmiecanie pamięci) mające na celu ułatwienie pracy programiście.
Kent Beck, Martin Fowler wraz ze współautorami swoich książek na temat refaktoryzacji stwierdzają, że mocno zagnieżdżone bloki instrukcji warunkowych mogą być trudniejsze w zrozumieniu niż bardziej spłaszczona struktura z wieloma punktami wyjścia.
Pojedynczy punkt wyjścia nie jest tak naprawdę użyteczną regułą. Kluczem jest przejrzystość: Jeśli metoda jest prostsza z jednym punktem wyjścia, użyj jednego, w przeciwnym przypadku, użyj wielu[15]
Herb Sutter i Andrei Alexandrescu również stwierdzają, że zasada pojedynczego wyjścia nie ma zastosowania w C++, jest tak za sprawą obsługi wyjątków i destruktorów, przez co każda funkcja może mieć wiele niejawnych punktów wyjścia[16].
Odmienne zdanie wyraża natomiast Bertrand Meyer, który w 2009 opisał break
i continue
jako „stare goto
w owczej skórze” i mocno odradzał ich użycie[17].
Obsługa wyjątków[edytuj | edytuj kod]
Badacze spierają się co do użycia wyjątków w kontekście programowania strukturalnego, jako że łamią one zasadę pojedynczego wyjścia. Cytując wcześniejsze badania (1999-2004) i podając własne, Westley Weimer i George Necula stwierdzają, że problem z wyjątkami polega na tym, że „tworzą ukryte ścieżki przepływu sterowania, o których programistom ciężko wnioskować”[18].Pojawiają się propozycje by sprowadzić wyjątki do pojedynczego wyjścia, jak i opinie, by pozostawić pełną dowolność w ich użyciu, jako że reguła pojedynczego wyjścia powstała przed pojawieniem się i popularyzacją wyjątków, a opakowywanie wyjątków by uczynić zgodnymi z regułą jednego wyjścia dodaje zbędne poziomy zagnieżdżenia utrudniając zrozumienie programów[19][20].
Zobacz też[edytuj | edytuj kod]
- Paradygmat programowania
- Programowanie obiektowe
- Graf przepływu sterowania
Przypisy[edytuj | edytuj kod]
- ↑ John von Neumann: First Draft of a Report on the EDVAC. [dostęp 2015-02-05]. [zarchiwizowane z tego adresu (2015-04-06)].
- ↑ The IBM 650 Magnetic Drum Calculator.
- ↑ IBM: SOAP II.
- ↑ a b Coding for the MIT-IBM 704 Computer.
- ↑ David Harel. On Folk Theorems. „Communications of the ACM”. 23 (7), s. 379–389, lipiec 1980. org/wiki/DOI_(identyfikator_cyfrowy)" title="DOI (identyfikator cyfrowy)">DOI: 10. 358892.
- ↑ a b c Edsger Dijkstra. Go to statement considered harmful. 11 (3), s. 147–148, marzec 1968. 1145/362929. 362947">10. 362947. atitle=Go+to+statement+considered+harmful&rft. date=marzec+1968&rft. volume=11&rft. aulast=Dijkstra&rft. aufirst=Edsger&rft. pages=147%E2%80%93148&rft_id=info:doi/10. 1145%2F362929. 362947&rft_id=https%3A%2F%2Fwww. edu%2Fusers%2FEWD%2Fewd02xx%2FEWD215. PDF">
- ↑ C. Hoare, Wirth. A contribution to the development of ALGOL. „Communications of ACM”. 9, s. 413–432, czerwiec 1966. atitle=A+contribution+to+the+development+of+ALGOL&rft. jtitle=Communications+of+ACM&rft. date=czerwiec+1966&rft. volume=9&rft. aulast=Hoare&rft. aufirst=C. &rft. pages=413%E2%80%93432">Sprawdź autora:2.
- ↑ P. J. Plauger: Programming on Purpose, Essays on Software Design. Prentice-Hall, 1993, s. 25. org/wiki/Specjalna:Ksi%C4%85%C5%BCki/9780137213740" title="Specjalna:Książki/9780137213740">ISBN 978-0-13-721374-0.
- ↑ Donald Knuth: Structured Programming with GoTo Statements. [dostęp 2015-02-08]. [zarchiwizowane z tego adresu (2013-10-23)].
- ↑ a b Frank Rubin. „GOTO Considered Harmful” Considered Harmful. 30 (3), s. 195–196, marzec 1987. atitle=%E2%80%9EGOTO+Considered+Harmful%E2%80%9D+Considered+Harmful&rft. date=marzec+1987&rft. volume=30&rft. aulast=Rubin&rft. aufirst=Frank&rft. pages=195%E2%80%93196">
- ↑ „'GOTO Considered Harmful’ Considered Harmful” Considered Harmful? . 30 (5), s. 351–355, maj 1987. atitle=%E2%80%9E%27GOTO+Considered+Harmful%E2%80%99+Considered+Harmful%E2%80%9D+Considered+Harmful%3F&rft. date=maj+1987&rft. pages=351%E2%80%93355">
- ↑ a b „'GOTO Considered Harmful’ Considered Harmful” Considered Further. 30 (6), s. 475–478, czerwiec 1987. atitle=%E2%80%9E%27GOTO+Considered+Harmful%E2%80%99+Considered+Harmful%E2%80%9D+Considered+Further&rft. date=czerwiec+1987&rft. pages=475%E2%80%93478">
- ↑ GOTO, One More Time. 30 (8), s. 659–662, sierpień 1987. atitle=GOTO%2C+One+More+Time&rft. date=sierpie%C5%84+1987&rft. pages=659%E2%80%93662">
- ↑ Edsger Dijkstra: On a somewhat disappointing correspondence. [dostęp 1987-05-25]. zły zapis daty dostępu
- ↑ Jay Fields, Shane Harvie, Martin Fowler, Kent Beck: Refactoring: Ruby Edition. Pearson Education, 2009, s. 274–279. org/wiki/Specjalna:Ksi%C4%85%C5%BCki/9780321603500" title="Specjalna:Książki/9780321603500">ISBN 978-0-321-60350-0. btitle=Refactoring%3A+Ruby+Edition&rft. au=Jay+Fields&rft. date=2009&rft. pub=Pearson+Education&rft. pages=274%E2%80%93279&rft. isbn=978-0-321-60350-0">
- ↑ Herb Sutter, Andrei Alexandrescu: C++ Coding Standards: 101 Rules, Guidelines, and Best Practices. Pearson Education, 2004. org/wiki/Specjalna:Ksi%C4%85%C5%BCki/9780132654425" title="Specjalna:Książki/9780132654425">ISBN 978-0-13-265442-5. btitle=C%2B%2B+Coding+Standards%3A+101+Rules%2C+Guidelines%2C+and+Best+Practices&rft. aulast=Sutter&rft. aufirst=Herb&rft. date=2004&rft. isbn=978-0-13-265442-5">
- ↑ Bertrand Meyer: Touch of Class: Learning to Program Well with Objects and Contracts. Springer Science & Business Media, 2009, s. 189. org/wiki/Specjalna:Ksi%C4%85%C5%BCki/9783540921448" title="Specjalna:Książki/9783540921448">ISBN 978-3-540-92144-8. btitle=Touch+of+Class%3A+Learning+to+Program+Well+with+Objects+and+Contracts&rft. au=Bertrand+Meyer&rft. pub=Springer+Science+%26+Business+Media&rft. pages=189&rft. isbn=978-3-540-92144-8">
- ↑ Westley Weimer, Necula George. „ACM Transactions on Programming Languages and Systems”. 30 (2). jtitle=ACM+Transactions+on+Programming+Languages+and+Systems&rft. au=Exceptional+Situations+and+Program+Reliability&rft. aulast=Weimer&rft. aufirst=Westley">Sprawdź autora:1.
- ↑ Jim Bonang: The Pragmatic Defense: Making Defects Easier to Find. kwiecień 2012. [zarchiwizowane z tego adresu (2017-07-10)].
- ↑ Peter Ritchie: Single-Entry, Single-Exit, Should It Still Be Applicable In Object-oriented Languages? . 2008-03-07.
Bibliografia[edytuj | edytuj kod]
- Corrado Böhm, Giuseppe Jacopini. Flow diagrams, Turing machines and languages with only two formation rules. 9 (5), s. 366–371, maj 1966. 1145/355592. 365646">10. 365646. atitle=Flow+diagrams%2C+Turing+machines+and+languages+with+only+two+formation+rules&rft. date=maj+1966&rft. aulast=B%C3%B6hm&rft. aufirst=Corrado&rft. pages=366%E2%80%93371&rft_id=info:doi/10. 1145%2F355592. 365646">
- Edsger Dijkstra. PDF">
Technik informatyk nie jest zwykłym użytkownikiem komputerów. Jeśli uczeń wybiera szkołę o takim profilu, z czasem staje się prawdziwym komputerowym ekspertem.
Programowanie komputerów osobistych stanowi esencję informatyki. Jest twórcze i wymiernie wpływa na działanie sprzętu, na którym pracujemy - w tym na jego użyteczność oraz efektywność. Bez odpowiedniego oprogramowania niemożliwe jest funkcjonowanie stron internetowych, programów biurowych i bankowych czy nawet sprzętu AGD. Umiejętność programowania w dzisiejszym świecie jest wręcz nieodzowna w zawodzie inżyniera, technika, webmastera czy naukowca.
"Programowanie strukturalne i obiektowe. Podręcznik do nauki zawodu technik informatyk. Wydanie II" w przystępny sposób wyjaśnia wszystkie niezbędne terminy, tak aby nawet osoba, która nigdy nie miała styczności z programowaniem, mogła je bez przeszkód zrozumieć. Podręcznik został podzielony na części stanowiące trzy oddzielne kursy programowania: w językach Pascal, C++ oraz Java. W czasie realizacji materiału uczniowie poznają najważniejsze elementy tych języków. Każdą część zamyka rozbudowany i ciekawy przykład podsumowujący.
Do książki została dołączona płyta CD zawierająca ważne i interesujące informacje dodatkowe, które ze względów praktycznych nie mogły ukazać się w wersji drukowanej. Znajduje się tam kurs wprowadzający do programowania w Windows za pomocą WinAPI, omówienie zagadnień pracy grupowej, projektowania oprogramowania i optymalizacji kodu, a także wybrane tematy uzupełniające, m. in. wiadomości dotyczące reprezentacji pozycyjnej liczb.
Materiały dostępne tylko dla zalogowanych użytkowników z wypełnioną deklaracją.