POLITECHNIKA KRAKOWSKA - WIEiK - KATEDRA AUTOMATYKI

Technologie Informacyjne www.pk.edu.pl/~zk/TI_HP.html

Wykładowca: dr inż. Zbigniew Kokosiński [email protected]

Wykład 6: P r o g r a m o w a n i e • • • • • • •

Definicja programowania Języki, środowiska programowania Hipoteza Sapira-Whorfa Programowanie – klasyfikacje Kompilacja kodu źródłowego Wymagania jakościowe Metody programowania

Definicja programowania Programowanie (kodowanie) jest procesem obejmującym tworzenie, testowanie, usuwanie błędów oraz bieżące utrzymywanie kodu źródłowego programów komputerowych.



Kod źródłowy jest zapisem wybranego algorytmu, przetwarzającego w pożądany sposób dane wejściowe w dane wyjściowe, w pewnym języku programowania. Algorytm to metoda rozwiązania problemu algorytmicznego (istnieją także problemy niealgorytmiczne i prawdopodobnie niealgorytmiczne).

Dane przechowywane są zwykle w postaci struktur. Wybór struktur danych zależy od problemu, własności języka programowania oraz samego programisty. Programy = algorytmy + struktury danych (Niklaus Wirth)

Programowanie – rzemiosło czy sztuka ? Przykładowe nazwy podręczników dla programistów:

The art of computer programming (Donald Knuth)



Algorithmics. The spirit of computing (David Harel) Programming perls (Jon Bentley) Algorithms + Data Structures = programs (Niklaus Wirth) The practice of programming (Brian Kernighan, Robert Pike) Podstawy i praktyka programowania mikroprocesorów (Jerzy Grabowski, Stanisław Koślacz) The pragmatic programmer. From Journeyman to Master (Andrew Hunt, David Thomas)

Języki proceduralne Język proceduralny pozwala na tworzenie oprogramowania w postaci programu głównego oraz wielu procedur (lub podprogramów), z których każda realizuje określoną funkcję i może być wywoływana wielokrotnie przez program główny. Każda z procedur pobiera określoną liczbę parametrów oraz opcjonalnie zwraca wartość wynikową w jednej lub wielu zmiennych (procedura), albo jako wartość zwracaną (funkcja). Istnienie mechanizmu zmiennych lokalnych oraz parametrów wywołania umożliwia zagnieżdżanie odwołań do procedury, co w efekcie pozwala na stosowanie technik rekurencyjnych.

Języki proceduralne wspomagają proces przygotowywania uniwersalnych bibliotek procedur i funkcji, dołączanych do nowo tworzonych programów, co przyspiesza proces tworzenia nowego programu oraz poprawia jakość tworzonych aplikacji.

Języki nieproceduralne Język nieproceduralny umożliwia pisanie programów jedynie w postaci ciągłej sekwencji instrukcji (niepodzielonej na procedury). Możliwe jest wykonywanie skoków warunkowych i bezwarunkowych oraz wykonywanie podprogramów, nie istnieje jednak pojęcie parametrów wywołania procedury, wartości zwracanej przez funkcję oraz zmiennych lokalnych i globalnych.

Tworzenie współdzielonych przez wiele programów bibliotek funkcji (do powtórnego wykorzystania) oraz stosowanie takich technik programistycznych jak rekurencja jest znacznie utrudnione lub niemożliwe. Przykładem języka nieproceduralnego jest BASIC.

Języki i środowiska programowania Języki niskiego poziomu – asemblery procesorów

Języki wysokiego poziomu – Fortran, Prolog, LISP, Pascal, Delphi, C, C++, C#, Java, UML itp. Języki opisu sprzętu – Abel, VHDL, Verilog

Środowiska obliczeń matematycznych i inżynierskich – Mathematica, Statistica , Maple, Matlab Środowiska projektowania układów programowalnych – Foundation ISE, Webpack ISE (Xilinx), Max+Plus II (Altera)

Hipoteza Sapira-Whorfa 1 Edward Sapir i Benjamin Lee Whorf badali języki Indian. W swoich badaniach zaobserwowali, że różnice występujące pomiędzy prymitywnymi językami naturalnymi a jezykami europejskimi, dotyczące słownictwa oraz takich kategorii gramatycznych jak czas czy liczba powodują w konsekwencji różnice w sposobie myślenia. Przykład: w jezyku Hopi zorientowanych na stawanie się (proces) brak jest czasowników odnoszących się do statycznych relacji przestrzennoczasowych (przeszłości, teraźniejszości i przyszłości) – są natomiast czasowniki odnoszące się do zdarzeń, przewidywania i uogólniania. Wg teorii lingwistycznej Sapira-Whorfa, używany jezyk (wzory językowe) wpływa w mniejszym lub większym stopniu na sposób (wzory) myślenia. Za hipotezą o znacznym udziale języka w myśleniu oraz procesach społecznych przemawiają zmiany językowe i znaczeniowe w praktycznie wszystkich grupach związanych wspólną ideologią. Zmiany te – spontaniczne czy zaprogramowane – wywierają wpływ na sposób myślenia członków grupy.

Hipoteza Sapira-Whorfa 2 W kontekście programowania komputerów ciekawym zagadnieniem są znaczne różnice w sposobie widzenia problemów przez programistów używających różnych języków programowania.

Może to mieć pewien związek z hipotezą Sapira–Whorfa i relatywizmem językowym jej autorów. Używanie jednego paradygmatu czy języka programowania może pociągać za sobą pewną jednostronność myślenia i tendencję do posługiwania się tymi samymi schematami bez względu na to jakie zadanie należy rozwiązać. Pewnym remedium na to zjawisko jest nauka – przynajmniej podstaw – kilku różnych języków programowania, dzięki czemu można patrzeć na to samo zadanie z różnych stron. Wśród języków szczególnie zalecanych programistom do nauki nieschematycznego myślenia są m.in.: LISP, Haskell, Prolog, czy Oz.

Programowanie – klasyfikacje 1 Ze względu na rozmiar projektu i charakter pracy programowanie dzielimy na: indywidualne, zespołowe, interaktywne W systemach równoległych i rozproszonych, w których występuje wiele komputerów/procesorów/wątków biorących udział w obliczeniach, wyróżniamy rodzaje programowania:

równoległe, współbieżne, wielowątkowe, rozproszone Ze względu sposób podejścia do hierarchii projektu programistycznego wyróżniamy programowanie :

modularne, zstępujące=analityczne (top-down) i wstępujące=syntetyczne (down-top)

Programowanie – klasyfikacje 2 Ze względu na dominujący paradygmat programowania wyróżniamy programowanie: proceduralne – kod programu dzielony jest na procedury, czyli fragmenty wykonujące ściśle określone operacje; procedury nie powinny korzystać ze zmiennych globalnych, lecz lokalnych oraz pobierać i przekazywać wszystkie dane (czy też wskaźniki do nich) jako parametry wywołania. strukturalne – programowanie oparte o tzw. instrukcje strukturalne, takie jak sekwencje, instrukcje warunkowe (if, if ... else), instrukcje wyboru (case), pętle (while, repeat ); ograniczone lub wyeliminowane jest używanie instrukcji skoku (go to); strukturalność zakłócają instrukcje typu break, continue, switch – stosowane czasem dla zwiększenia czytelności kodu.

Programowanie – klasyfikacje 3 obiektowe – programy definiuje się za pomocą obiektów – elementów wiążących ze sobą stan (dane, nazywane polami) i zachowanie (procedury, czyli metody); program obiektowy stanowi zbiór takich obiektów, komunikujących się pomiędzy sobą w celu wykonywania zadań. (programowanie obiektowe ma ułatwić pisanie, konserwację i wielokrotne użycie programów lub ich fragmentów) uogólnione – pozwala na pisanie kodu programu bez wcześniejszej znajomości typów danych, na których ten kod będzie pracował; przykładowe języki: C++, Java, Haskell

metaprogramowanie – technika pozwalająca programom na tworzenie lub modyfikację własnego kodu (lub kodu innych programów) w trakcie jego kompilacji lub wykonywania; przykładowe języki: Lisp, Smalltalk, PHP, Python, Tcl, Perl.

Programowanie – klasyfikacje 3 W przypadku jezyków opisu sprzętu (HDL) mamy dwa paradygmaty programowania : strukturalne – opisywane są komponenty składowe i sposób ich połączenia, a nie zachowanie układu. behawioralne – w przypadku języków opisu sprzętu opisywane jest zachowanie układu, a nie jego struktura.

Jeżeli występuje programowanie w wielu językach lub paradygmatach równocześnie mamy do czynienia z programowaniem mieszanym, np. : język wysokiego poziomu + asembler paradygmat strukturalny + behawioralny

Programowanie – klasyfikacje 4 Programowanie wizualne (visual programming )– technika tworzenia programów przy pomocy narzędzi umozliwiających wybór standardowych elementów z menu i automatyczna generacja powiadającego im kodu źródłowego. Zastosowanie – tworzenie interfejsu użytkownika aplikacji, wspomaganie tworzenia klas obiektów, podział na funkcje I procedury, generowanie dokumentacji. Przykłady jezyków: Borland Delphi, Symentec C++, Visual C++ Programowanie szablonowe (template programming) – szablony umożliwiają tworzenie kodu bez uwzględniania typów. Szablonów używa się tworząc instancje (konkretyzacja). W C++ popularne są szablony funkcji i klasy. Java, C#, Haskell mają podobne rozwiązanie – typy generyczne. W VHDL istnieje biblioteka szablonów typowych układów cyfrowych – potrzebna jest konkretyzacja (uwzględnienie rozmiaru układu, nazw).

Kompilacja kodu źródłowego Kompilacja : kod źródłowy jest zwykle kompilowany do kodu maszynowego, wykonywalnego na danej maszynie. • Kompilacja składa się z kilku faz: analizy leksykalnej, analizy syntaktycznej i semantycznej, generacji kodu pośredniego, optymalizacji tego kodu oraz generacji kodu wynikowego. Procesem odwrotnym do kompilacji jest dekompilacja. W wyniku dekompilacji z kodu wynikowego odtwarzany jest kod źródłowy. Praktykę taką nazywa się reverse enginnering. Oprócz kompilacji programowej wyróżnia się ponadto kompilację sprzętową, np. w celu skonfigurowania układu FPGA.

Wymagania jakościowe 1 Programy, jako wynik działalności programistycznej, powinny spełniać następujące wymagania o charakterze jakościowym: Efektywność – wydajność : ilość zasobów systemu komputerowego wymagana przez program (czas pracy procesora, zajmowany obszar pamięci, przepustowość sieci oraz w pewnym zakresie również intensywność komunikacji z użytkownikiem) – powinna być jak najmniejsza.

Niezawodność : jak często wyniki generowane przez program są poprawne; zależy od zapobiegania propagacji błędów pochodzących z konwersji danych, oraz zapobierania błądom pochodzacym z przepełnionych buforów, dzielenia przez zero itp. Odporność : jak dobrze program jest w stanie przewidzieć sytuacje konfliktu typu danych i inne rodzaje niekompatybilności, które skutkują błędami wykonania programu lub jego zawieszeniem. Program powinien zapewniać w takich sytuacjach właściwy kontakt z użytkownikiem i obsługę wyjątków.

Wymagania jakościowe 2 Użyteczność : czytelność i intuicyjność programów decyduje o ich akceptacji przez docelowego użytkownika i sukcesie rynkowym. Interfejs użytkownika obejmuje zarówno ogólną koncepcję jak i szeroką paletę elementów tekstowych i graficznych, które powodują, że program jest łatwy i wygodny w użytkowaniu. Przenośność : zakres platform sprzętowych i systemów operacyjnych, na których może być kompilowany, interpretowany i wykonywany kod źródłowy programu. Przenośność zależy przede wszystkim od dostępnych na danej platformie kompilatorów, a nie od samego programu. Inne związane z tymi wymaganiami cechy programów są następujące: paradygmat programowania, styl programowania, niska złożoność obliczeniowa implementowanego algorytmu, testowalność programu, potencjalna wielokrotna używalność (re-usability), zwięzłość i dokumentacja.

Metody programowania Rekursja Metoda dziel i zwyciężaj (divide and conquer) Równoważenie (balancing) Programowanie z nawrotami (backtracking) Wyszukiwanie wyczerpujące (exhaustive search)

Wyszukiwanie lokalne (local search) Programowanie dynamiczne Programowanie liniowe (optymalizacja)

Programowanie zachłanne (greedy) Metaheurystyki (algorytmy iteracyjne) Programowanie równoległe (parallel programming)

Literatura

1. Cormen T.H., Leiserson C.E., Rievest R.L., : Wprowadzenie do algorytmów, WNT, Warszawa 2002 2. Kernighan B.W., Pike R. : Lekcja programowania, WNT, Warszawa 2002