Programowanie Komputerów
Prof. Dr hab. Jerzy Gołuchowski
( Notatki: created by Matek & Psychol )
Programowanie (w szerszym znaczeniu ):
Jest to jednoznaczne formułowanie zdań oraz sposobu ich rozwiązywania za pomocą komputera prowadzące do wykonania szeregu czynności.
Czynności składające się na proces programowania:
Sformułowanie problemu
Określenie metody rozwiązania
Dyskusja warunków istnienia rozwiązania
Tworzenie sieci działań
Kodowanie algorytmu w wybranym języku programowania
Uruchomienie testowe
Opracowanie dokumentacji
Programowanie ( w węższym znaczeniu ):
To kodowanie algorytmu w wybranym języku programowania.
Algorytm - zbiór reguł postępowania (przepis) mający na celu w skończonej liczbie kroków przetworzenie informacji wejściowych (danych) w informacje wynikowe (wyniki).
Problemy związane z opracowywaniem algorytmów:
Przed opracowywaniem algorytmu powinniśmy stwierdzić, czy zdanie posiada rozwiązanie i czy rozwiązanie jest jednoznaczne.
Raz opracowany algorytm dla danego problemu może służyć do rozwiązania wszystkich problemów tej samej klasy, dla której został opracowany, różniących się jedynie doborem konkretnych danych wejściowych.
Zawsze przy opracowywaniu algorytmu zakłada się pewien poziom szczegółowości, na którym formułuje się algorytm.
Algorytm powinien uwzględniać wszystkie teoretyczne warianty przebiegu obliczeń zaistniałe z powodu różnego doboru danych wejściowych.
Algorytm musi by kompletny.
Etapy opracowywania programu:
Analiza problemu i sformułowanie algorytmu.
Zakodowanie algorytmu w języku programowania.
Wprowadzenie tekstu programu źródłowego do komputera.
Tłumaczenie programu.
Testowanie i ewentualne poprawienie błędów formalnych ( składniowych ) wykrytych w kroku 4 i ponowne tłumaczenie programu.
Uruchomienie programu i poprawienie błędów logicznych.
Opracowanie dokumentacji.
Kodowanie algorytmu w języku programowania:
Jako ograniczenia zawężające możliwości wyboru języka przyjmuje się m.in.:
Klasę problemu.
Kwalifikacje programisty.
Struktury danych.
Dostępność translatora języka.
Cechy dobrego programu:
Poprawny - „ testowanie może wykazać obecność pomyłki, nigdy nie może zaś wykazać nieobecności błędu”.
Przystosowywalny - modularna budowa.
Odporny - na błędy użytkownika.
Stabilny - nie „załamuje się” w przypadku prostego błędu danych wejściowych.
Optymalny - minimalizujący zajętość pamięci i czasu pracy procesora.
System programowania ( środowisko programistyczne - zawierające co najmniej translator języka ):
Język programowania.
Translator.
Systemy programowania obejmują:
Translator.
Edytory do zapisu programu źródłowego.
Narzędzia do testowania i uruchamiania programów ( debugger ) pozwalające wykrywa i usuwa błędy zawarte w programach.
Biblioteki specjalizowanych procedur, które można włączyć do pisanych programów narzędzia wspomagające użytkownika ( nauka języka, podpowiedzi kontekstowe ).
Rodzaje środowisk programistycznych:
Testowe.
Graficzne.
Język programowania:
Zbiór symboli oraz reguł syntaktycznych i normatycznych stosowanych w trakcie definiowania sposobu przetwarzania określonego zadania.
Elementy języka programowania:
Alfabet - czyli zbiór określonych symboli, z których będą tworzone słowa i zdania w tym języku.
Składnia ( syntaktyczna ) - czyli reguły tworzenia poprawnych zdań ( instrukcji ) tego języka.
Reguły znaczeniowe ( semantyka ) - interpretujących znaczenie poszczególnych zdań i konstrukcji języka.
Translacja programu:
Programy z reguły są pisane w językach programowania łatwo zrozumiałych przez człowieka, natomiast niezrozumiałych dla komputera. Dlatego konieczny jest proces tłumaczenia języka źródłowego w jakim napisany jest program na język docelowy zrozumiały przez maszynę.
Translacja - proces tłumaczenia programu źródłowego na wynikowy. Translacji dokonuje się przeważnie przez:
Interpretację - przez interpretery.
Kompilację - przez kompilatory.
Translator - program tłumaczący pozwalający „przetłumaczyć” przekształcić kod programu napisany w języku zrozumiałym dla programisty ( tzw. Program źródłowy ) w kod maszynowy czyli postać programu wykonalną na dowolnym sprzęcie.
Kompilacja
Kompilator analizuje program napisany w określonym języku programowania( program źródłowy ) i tłumaczy go na równoważnie funkcjonalnie program w języku wewnętrznym ( program wynikowy ).
Jeśli proces tłumaczenia zakończy się poprawnie to w dalszej pracy nad programem, czyli w trakcie jego testowania pracuje się z wersją wynikową, program wynikowy może być uruchomiony na każde żądanie bez konieczności ponownego tłumaczenia.
Kompilacja - proces automatycznego tłumaczenia kodu napisanego w języku programowania na drugi. Kod źródłowy - dane wejściowe. Tłumaczenie języka z wyższego poziomu na język niższego poziomu. Odwrotny proces to dekompilacja.
Polega na przekształceniu programu źródłowego na równoważny program wyrażony w języku maszynowym przed jego uruchomieniem. Następnie uruchamia się już skompilowany program.
Przykłady języków: Pascal, Fortan, C, ...
Interpretacja
Interpretator pobiera kolejne instrukcje programu, sprawdza ich poprawność, rozpoznaje jakie czynności należy wykonać i wykonuje je.
Każde uruchomienie programu wymaga jego tłumaczenia !!!
Programy interpretowane działają bardzo wolno w porównaniu z programami kompilowanymi.
Zaletą interpretacji jest możliwość wykonania tylko fragmentu programu - łatwe lokalizowanie błędów i nanoszenie poprawek.
Interpreter analizuje postać znakową każdej instrukcji języka źródłowego i tłumaczy ją na kod maszynowy za każdym razem, gdy instrukcja ta jest wykonywana.
Jeśli dana instrukcja wykonywana ma być wielokrotnie, lepszym podejściem jest analizowanie postaci znakowej tylko raz i zastąpienie jej ciągiem symboli łatwiejszym do interpretacji.
Interpretacja - przekształcanie ( translacja ) instrukcji programu na bieżąco do kodu maszynowego lub innej formy pośredniej i natychmiastowe ich wykonywanie. Zmusza to do ustawicznego tłumaczenia instrukcji, co wielokrotnie wydłuża czas działania programu. Zaletą jest natomiast łatwość dokonywania zmian w programie w trybie konwersacyjnym.
Nadawanie informacjom wejściowym nowych znaczeń na wyjściu. Bezpośrednie przetwarzanie informacji ( danych ) w działania.
Reinterpretacja - ponowna interpretacja.
Testowanie - w praktyce testowanie programu na wszystkich możliwych danych teoretycznych jest niemożliwe. Najczęściej stosuje się test:
Funkcjonalny.
Według oceny użytkownika.
Według struktury programu.
Algorytmy:
Wstęp.
Rodzaje algorytmów.
Metody zapisu.
Złożoność.
Przykłady algorytmów sortowania.
Podstawowe pojęcia algorytmów:
Określenie dziedziny algorytmiki.
Klasyfikacja algorytmów.
Własności algorytmów.
Konstrukcje algorytmiczne w językach programowania.
Metody weryfikacji algorytmów.
Pojęcie złożoności obliczeniowej algorytmów.
Algorytmika - nauka o algorytmach:
Jest dziedziną wiedzy zajmującą się badaniem algorytmów.
W informatyce jest ona nieodłącznie związana z algorytmami przetwarzania struktur danych.
Dzisiejsze pojęcie algorytmu:
Dzisiejsze, uogólnione znaczenie słowa „algorytm” zastosowano w zasadzie dopiero w 20-stym stuleciu, kiedy to algorytm zaczął być rozumiany jako:
Zbiór reguł postępowania umożliwiający rozwiązanie określonego zadania w skończonej liczbie kroków i w skończonym czasie.
Każdy algorytm:
Posiada dane wejściowe:
( w ilości większej lub równej zero ) pochodzące z dobrze zdefiniowanego zbioru.
Zwraca pewien wynik:
( nie koniecznie numeryczny).
Jest precyzyjnie zdefiniowany:
( każdy krok algorytmu musi być jednoznacznie określony).
Jest zbieżny:
( dla każdego dopuszczalnego zbioru danych początkowych liczb operacji prowadzących do poszukiwania wyniku jest skończona).
Pochodzenie słowa algorytm:
Słowo algorytm pochodzi od łacińskiego „algorism”, co w średniowieczu było rozumiane jako sztuka rachowania na liczbach w systemie decymalnym. Słowo „algorism” zostało utworzone od nazwiska perskiego matematyka z 9-tego wieku n.e., tj. Muhameda ibu-Musy al.- Choresmi, twórcy systemu dziesiętnego i zasad działania na liczbach dziesiętnych w sposób „ mechaniczny”.
Przykłady algorytmów:
Programowanie matematyczne:
Algorytmy rozwiązywania zadań liniowych ( programowanie liniowe ).
Programowanie dynamiczne, ...
Sztuczne inteligencja, wspomaganie podejmowania decyzji:
Sieci neuronowe.
Algorytmy genetyczne.
Metody symulacyjne.
Przetwarzanie danych:
Wstawianie, wyszukiwanie i usuwanie elementów ze struktur danych.
Sortowanie struktur danych.
Reorganizacja struktur danych, ...
Systemy operacyjne:
Równoważenie obciążenia w dostępie do zasobów w systemach rozproszonych i nierozproszonych.
Synchronizacja procesów współbieżnych.
Usuwanie nieużytków z pamięci operacyjnej, ..., itp. ..., itd. ...
Sposoby zapisu algorytmów:
Algorytm powinien precyzyjnie przedstawiać kolejne jego kroki. Do opisu tych kroków mogą być stosowane następujące sposoby:
Zapisy werbalne.
Zapisy formalne np.:
Zapisy graficzne ( schematy blokowe ).
Formalne specyfikacje programów ( VDM, CSP).
Zapisy w postaci pseudokodów ( „paraprogramów” ).
Implementacje w dowolnym języku programowania.
Algorytm liniowy ( sekwencyjny ):
Składa się z ciągu instrukcji, które wykonywane są jedna po drugiej w kolejności, jaka wynika z ich następstwa w zapisie algorytmu.
Np.: Gotowanie jajka :
Wlanie do garnka zimnej wody.
Zapalenie gazu.
Podgrzewanie wody do wrzenia.
Włożenie jajka.
Odczekanie odpowiedniego czasu ( 5 min ).
Zgaszenie gazu.
Wyjęcie jajka.
Algorytm nieliniowy:
Większość algorytmów ma rozbudowaną strukturę. Często występują w nich instrukcje, których wykonanie uzależnione jest od spełnienia określonego warunku lub też spełnienie pewnego warunku powoduje wykonanie jednej instrukcji, a niespełnienie go innej.
Algorytm nieliniowy może zawierać następujące elementy konstrukcyjne:
Selekcję.
Iterację.
Element konstrukcyjny - Selekcja:
Selekcja ( Instrukcja warunkowa ) działa na podstawie dwóch przedstawionych schematów:
Jeśli spełniony jest warunek W, wykonaj A.
Jeśli spełniony jest warunek W, wykonaj A, w przeciwnym razie wykonaj B.
Instrukcja warunkowa pozwala dokona wyboru jednej z dalszych kilku dróg wykonania algorytmu.
Schemat Instrukcji Selekcji ( alternatywy ) - „if”:
Semantyka: wybór jednego z dwóch torów przetwarzania po sprawdzeniu prawdziwości zdania logicznego.
Syntaktyka:
If logic_assertion _is true then
action_if_true;
T N
Warunek else
action_if_false;
end_if;
Akcja jeśli Akcja jeśli
„TAK” „NIE”
Schemat blokowy instrukcji „if”
Selekcja przykład:
Znajdowanie większej liczby z dwóch liczb podanych:
Wczytanie liczby X.
Wczytanie liczby Y.
Gdy X>=Y, to wynik = X.
W przeciwnym przypadku ( czyli Y>X ), wynik Y.
Wyświetlenie wyniku czyli liczby większej.
Element konstrukcyjny - Iteracja:
Wielokrotne powtarzanie pewnych instrukcji jest cechą istotną wielu algorytmów, lecz nie zawsze można określić ilość powtórzeń. Iteracja umożliwia powtarzanie wykonania instrukcji.
Wyróżnia się iteracje:
Ze znaną ilością powtórzeń.
Ze spełnieniem określonego warunku.
Schemat Iteracji typu „podczas gdy” ( while - do ):
Semantyka: powtarzanie tych samych czynności podczas zachodzenia warunku logicznego, zdefiniowanego na wejściu do każdego kroku pętli.
Syntaktyka:
Schemat blokowy While logic_assertion_is true do
Pętli “while-do”.
N action_in_while-do_loop;
Warunek
End_while;
T
Powtarzane
Kroki
Schemat pętli iteracyjnej „for” ( w wersji z języka C/C++):
Semantyka: powtarzanie tych samych czynności ilość razy określoną wartością startu, przyrostu i niezmiennika pętli.
Syntaktyka:
N = start
For (n=start; for_invariant; change_n_rule)
{
action_in_for_loop;
For_invariant_rule
}
change_n_rule
T
Powtarzane
Kroki
Schemat blokowy pętli “for”
Metody weryfikacji algorytmów ( black box - metoda syntetyczna ):
Metoda czarnej skrzynki, ( ang. Black box method ) - polega na weryfikacji poprawności algorytmu poprzez analizę uzyskanych wyników jego wykonania po zadaniu określonego zestawu danych wejściowych. W tej metodzie nie analizuje się wewnętrznej budowy algorytmu - analizuje się go jako jedną zamkniętą całość.
Wejście ALGORYTM Wyjście
Schematy Nassi - Schneidermana ( NS ):
W schematach NS cały algorytm prezentowany jest jako prostokąt.
Sekwencja poleceń - to podzielony prostokąt poziomą linią - tworzy ona dwa prostokąty.
Selekcja ( instrukcja warunkowa ) - prezentowana jest w sposób przedstawiony poniżej - w trójkącie wpisuje się warunek selekcji, a w prostokąty pod nimi odpowiadają kolejnym krokom algorytmu.
X > 0 TAK NIE
Ostatnia instrukcja - iteracja ( brak w schematach blokowych ) przedstawiona jest w sposób widoczny na rysunkach. Prostokąt to czynność powtarzana.
„Dopóki W, dopóty R” „powtarzaj R, aż do W”
Warunek powtarzania pętli W R
Warunek wyjścia z pętli
W R
Przykład: algorytm sumujący liczby większe od 5 spośród 10 wprowadzonych.
s: =0, i:=0
i < 10
Podaj a
i = i + 1
a > 5
TAK NIE
s: = s + a
Drukuj s
Pseudokod
W wielu publikacjach można spotkać zapis algorytmu w postaci tzw. Pseudokodu. Przeważnie jest to zmodyfikowana wersja języka Pascal.
W książkach, publikacjach poświęconych danemu językowi programowania, algorytmy zapisane są przeważnie w tym języku. Dlatego wygląd tego samego algorytmu może znacznie różnić się u jednego autora, w porównaniu z algorytmem drugiego autora. Najczęściej algorytmy są publikowane w języku: PASCAL, C oraz JAVA.
Własności algorytmów:
Adekwatność.
Własność stopu.
Jednoznaczność.
Powtarzalność.
Złożoność obliczeniowa.
Metody zapisu algorytmów:
Do najbardziej popularnych metod zapisu algorytmów należą:
- Schematy blokowe.
- Schematy NS.
- Pseudokod,
- Języki programowania.
Schematy blokowe:
Schemat blokowy - to graficzny zapis przedstawiający opis i kolejność wykonywania czynności realizujących dany algorytm. W schemacie blokowym poszczególne operacje przedstawione są za pomocą odpowiednio połączonych skrzynek ( klocków ) połączenia określają kolejność i sposób wykonywania operacji.
Elementy schematu blokowego:
1. Skrzynka graniczna - oznacza początek lub koniec algorytmu. Są kształtu owalnego, ze skrzynki START wychodzi jedno połączenie, natomiast skrzynka STOP nie ma połączenia wychodzącego.
START
STOP
Skrzynka operacyjna - wykonanie różnych zadań (np.: sumowanie ), o kształcie prostokąta.
X = a + b +c
Skrzynka wejścia / wyjścia - wprowadzanie lub wyprowadzanie ( np.: wydruk na ekranie ) danych. Kształt równoległoboku.
Czytaj a, b, c Drukuj z
4. Skrzynka warunku - sprawdzanie warunku ( np.: czy x > 0 ). Kształt rombu. Ze skrzynki wychodzą dwa połączenia ( jedno oznaczone jako TAK, drugie jako NIE ).
TAK NIE
x > 0
Zasady budowy:
Każda operacja jest umieszczona w skrzynce.
Schemat ma tylko jedną skrzynkę START i przynajmniej jedna skrzynkę STOP.
Skrzynki są ze sobą połączone.
Ze skrzynki wychodzi jedno połączenie ( wyjątek: skrzynka STOP oraz skrzynka warunkowa ).
Klasyfikacja algorytmów:
Algorytmy równoległe - algorytmy sekwencyjne.
( kroki algorytmu wykonywane kolejno w sekwencji lub równolegle ).
Algorytmy numeryczne - algorytmy nienumeryczne.
( wykonywanie obliczeń lub przetwarzanie danych ).
Algorytmy rekurencyjne - algorytmy iteracyjne.
( algorytm w kolejnych krokach wywołuje sam siebie dla nowych wartości parametrów wykonania lub wykonuje obliczenia w pętli dla zmieniającej się wartości jej niezmiennika ).
Rodzaje algorytmów:
Algorytm równoległy Algorytm sekwencyjny
START START
Krok_1 Krok_1
Krok_2 Krok_3 Krok_2
Krok_3
Krok_4 Krok_5
Krok_4
Krok_6
Krok_5
STOP
Krok_6
STOP
Programowanie współbieżne:
Zbiór technik i notacji programistycznych służących do wyrażania potencjalnej równoległości oraz do rozwiązywania zagadnień związanych z powstającymi przy tym problemami synchronizacji i komunikacji poszczególnych składowych algorytmu.
Programowanie współbieżne pozwala rozważać równoległość algorytmu obliczeniowego bez wdawania się w szczegóły implementacyjne ( liczba procesów, model procesu, model pamięci, implementacja obiektów synchronizacji, algorytm wznawiania procesów, mechanizmy komunikacji, itp. ).
Różnice w zasadach implementacji algorytmów współbieżnych:
Klasyczne programowanie współbieżne:
Polega na dekompozycji problemu na wiele elementów oprogramowania, które wykonane są przez pewna liczbę procesów z pamięcią współdzieloną. Są to tzw. Systemy ściśle powiązane.
Współbieżność rozproszona:
Polega na dekompozycji problemu na wiele elementów oprogramowania, które są wykonywane przez pewną liczbę niezależnych procesów ( własny zegar taktujący i pamięć operacyjna ) komunikujących się przez sieć połączeń ( np.: sieć lokalna ). Są to tzw. Systemy luźno powiązane.
Języki i środowiska programowania współbieżnego:
Z konstrukcjami programowania współbieżnego: Concurrent Pascal, Concurrent C, CSP, Ada, Modula 2, MODSIM II, Java, Linda, Occam, Orca.
Umożliwiające programowanie współbieżne: C/C++, Delphi Pascal.
Język programowania nie zawiera mechanizmów synchronizacji procesów lecz pozwala wykorzystywać obiekty synchronizacji dostarczane przez system operacyjny.
Semantyka języka programowania:
Semantyka zajmuje się interpretacją formuł zapisanych zgodnie z określonymi regułami syntaktycznymi języka.
Tarski ( 1936r. ) zaproponował używanie pojęcia „semantyka naukowa” dla określenia semantyki zajmującej się formalnym badaniem prawdziwości formuł w zakresie znaczeniowym definiowanego języka.
Od lat 70-tych XX w rozwija się tzw. „Semantyka wartości logicznych” ( SWL ), inaczej nazywana semantyka prawdziwościową. Bazuje ona na pojęciu prawdy logicznej, na wyrażeniach zwanych „tautologiami”.
Podstawą wnioskowania w SWL o prawdziwości reguły logicznej jest dowiedzenie poprawności zdania logicznego wyprowadzonego na podstawie kombinacji innych, prawdziwych zdań logicznych.
Kod maszynowy:
Jedyną zrozumiałą bezpośrednio dla komputera ( mikroprocesora ) formą przedstawiania instrukcji stanowią liczby binarne ( dwójkowe ), które dla lepszej czytelności dla człowieka zapisywane są często w postaci liczb szesnastkowych.
Program zapisany w takiej postaci nazywany jest kodem ( językiem ) maszynowym.
I Generacja
Kod maszynowy czyli ciąg zer i jedynek stanowiący binarny zapis funkcji procesora wraz z ich parametrami.
Np.: polecenie: dodaj zawartość komórki 100 do rejestru 1 w kodzie maszynowym należy zapisać:
1001010010110100
Język niskiego poziomu - Asembler:
Język niskiego poziomu, najbliższy kodu maszynowego, wymaga śledzenia zawartości rejestrów.
Programy pisane w asemblerze charakteryzują się dużą prędkością działania, wadą jest ich mało czytelna struktura.
II Generacja
Języki zwane asemblerami lub językami adresów symbolicznych, są językami niskiego poziomu. Funkcje procesora są w nich kodowane za pomocą tzw. Mnemoników, czyli krótkich i prostych poleceń będących dokładnymi odpowiednikami procedur, które może wykonać procesor.
Np.: polecenie: dodaj zawartość komórki 100 do rejestru 1 w kodzie maszynowym należy zapisać:
ADD 1, 100
Asembler - różnica pomiędzy kodem maszynowym a asemblerem polega na zastąpieniu kodów rozkazów procesora, pisanej w postaci binarnej lub szesnastkowej, mnemonicznymi nazwami tych rozkazów oraz stworzeniu pewnej struktury języka, która wygląda następująco:
Etykieta: Rozkaz Argumenty
Jako języki niskiego poziomu, słabo nadają się do tworzenia rozbudowanego oprogramowania użytkowego, dlatego stosuje się je głównie do tworzenia elementów oprogramowania systemowego zwłaszcza tych, w których najważniejsza jest szybkość działania i zgodność ze sprzętem komputerowym. Program napisany w języku asemblera musi zostać przetłumaczony na język maszynowy.
Zalety:
Zalety kodu maszynowego.
Łatwiejsze pisanie programów w porównaniu z kodem maszynowym.
Możliwość wykrywania przez program, tłumaczący ( asembler ) pewnych błędów w kodzie źródłowym.
Języki wysokiego poziomu:
Wśród nich wyróżnia się:
Do zastosowań numerycznych np.:
FORTAN
Do przetwarzania danych ekonomicznych np.:
COBOL
Do symulacji procesów np.:
Simula
Uniwersalne jak: PASCAL, BASIC.
Do tworzenia systemów ekspertowych np.:
PROLOG
III Generacja
Języki III generacji to języki wysokiego poziomu, których poszczególne instrukcje odpowiadają ciągom wielu rozkazów wewnętrznych komputera. Oferują one dla programistów takie udogodnienia jak np.: proceduralność, czyli możliwość jednokrotnego zaprogramowania rozbudowany procedur, a następnie wielokrotnego odwoływania się do nich w programie.
IV Generacja
( Fourth Generation Language - 4GL ) - zaawansowane technologicznie systemy programowania, które jakby ukrywają przed programistą stopień skomplikowania tworzonej aplikacji, umożliwiając mu koncentrowanie się na aspektach merytorycznych.
Najczęściej używane są w środowisku baz danych - o następujących możliwościach funkcjonalnych:
Interaktywne generowanie raportów.
Interaktywne definiowanie dialogu użytkownika z systemem w ramach wprowadzania danych do bazy danych.
Interaktywne opracowanie zapytań dotyczących zawartości baz danych.
Współpraca z wieloma różnymi bazami danych.
Mechanizmy zapewnienia ochrony danych.
Obsługa działania w środowisku wielodostępnym.
Współpraca z nadzorującym systemem operacyjnym.
Java
Często określa się go jako język programowania internetu.
Idea systemu pracy Java: w Java tworzone są programy zwane apletami ( applets ), które następnie przetwarzane są przez specjalny kompilator do binarnej, niezależnej od platformy sprzętowej i systemu operacyjnego postaci, określanej mianem: Kod-bajtowy ( bytecode ) lub klasa ( class ).
Rozmiar wygenerowanych plików jest w przeważającej części przypadków stosunkowo mały ( kilka KB ), co pozwala na realizacje szybkiej transmisji nawet w wolnych sieciach. Klasy mogą by interpretowane przez wirtualna maszynę wbudowaną np.: w przeglądarkę WWW lub w niezależny program ( tzw. Applet Viewer ). Aplety ( klasy ) włączone są do stron Web za pomocą prostego mechanizmu, stanowiącego kolejne rozszerzenie języka HTML.
Rozprzestrzenia się dynamicznie nie tylko w dziedzinie WWW. Opracowywane są projekty włączenia go jako części systemów operacyjnych i programów obsługi baz danych.
Ewolucja programowania
Paradygmaty Programowania
Powstało wiele paradygmatów programowania
Programowanie proceduralne
Programowanie deklaratywne
Programowanie obiektowe
Programowanie strukturalne
Programowanie funkcjonalne
Programowanie intencyjne
Programowanie zdarzeniowe
Programowanie ekstremalne
Programowanie Proceduralne
Programowanie proceduralne charakteryzuje się tym, ze program musi zawierać pełny opis rozwiązywania problemu ( algorytmu ) w postaci sekwencyjnej elementarnych czynności ( instrukcji )
W programowani proceduralnym określa się JAK ma przebiegać proces przetwarzania, aby z wprowadzonych danych otrzymać żądane wyniki.
Programowanie Proceduralne
Języki programowania, które zostały zaprojektowane z myślą o programowaniu proceduralnym, np..:
Fortran,
Algol,
Pascal,
C.
Programowanie Proceduralne
Program składa się z dwóch części:
Deklaratywnej - opisuje się obiekty ( dane ), na których on działa,
Proceduralnej - opisuje się czynności ( instrukcje ), które są wykonywane na tych danych.,
Programowanie Proceduralne
Program pierwiastki
VAR
a,b,c,delta,x1,x2:Real;
BEGIN
writeln(`Obliczanie pierwistkow');
read(a,b,c);
delta:=b+b-4*a*c;
IF delta < 0 THEN writeln(`brak pierwiastkow w R');
ELSE
IF delta = 0 THEn writeln(`x=`,-b/(2*a))
ELSE
BEGIN
x1:=(-b-sqrt(delta))/(2*a);
x2:=(-b+sqrt(delta))/(2*a);
writeln(`x1=`,x1,`x2=`,x2);
END
END
Programowanie Proceduralne
1. punktem centralnym w języku proceduralnym jest instrukcja,
2. program musi zawierać szczegółowy opis kolejnych Kraków postępowania zgodnie z przyjętym algorytmem - JAK przetwarzać,
3. zaletą podejścia proceduralnego jest to, że wiele pojęć łatwiej jest zaprezentować w postaci procedur niż za pomocą np. deklaracji.
Programowanie deklaratywne
Jest to styl programowania polegający na pokreśleniu związków ( relacji ) pomiędzy danymi a wynikami.
Wymagane jest określenie CO ma zostać przetworzone, zamiast JAK ma przebiegać proces przetwarzania.
Programowanie deklaratywne
Omawiany style programowania opiera się na logice.
Najbardziej popularnym językiem tej klasy jest PROLOG, w którym wykorzystano klauzulową odmianę logiki ( klauzule Horna ), ponieważ język klauzul jest prostszy niż standardowy język logiki.
Programowanie deklaratywne
Zadanie do rozwiązania przedstawione jest w postaci celu, natomiast fakty oraz reguły określają obiekty konieczne do rozwiązania danego problemu oraz związki jakie między tymi obiektami zachodzą.
Fakt - bezwarunkowo prawdziwe stwierdzenie.
Reguła - warunkowe stwierdzenie o istnieniu pewnych zależności między obiektami.
Programowanie deklaratywne
FAKT:
Dziecko(Kain, Ewa)
Oznacza, że Kain jest dzieckiem Ewy.
REGUŁA:
matka(X,Y):-kobieta(X),dziecko(X,Y)
oznacza, że „X jest matką Y, jeśli X jest kobietą i Y dzieckiem X”.
Programowanie deklaratywne
Podając cel:
1. Kto jest matką Kasi?
-? matka(X,Kasia)
Odpowiedz: X=Ewa
2. Jakie dzieci ma Jan?
-? ojciec(Jan,X)
Odpowiedz: X=Kasia,X=Ola
Programowanie deklaratywne
W arkuszy kalkulacyjnym
-wzory(formuły)
-funkcja
Programowanie deklaratywne
Zalety:
1. jest często bardziej ekonomiczne pod względem zapisu niż programowanie proceduralne - fakt zapisany jeden raz może być użyty na rożne sposoby, dzięki mechanizmowi wnioskowania,
2. jest komunikatywne - w naturalny sposób definiowane są problemu
3. występuje minimalizacja składnika sterowania na rzecz logiki.
Programowanie obiektowe
Program jest opisem działań zbioru wzajemnie powiązanych obiektów. Obiekty kontraktują się ze sobą za pomocą komunikatów.
Programowanie obiektowe różni się od tradycyjnego programowania tym, że centralnym punktem jest obiekt a nie instrukcja.
Obiekty
Zawierają zarówno metody ( funkcje ), jak i pola (zmienne).
Pojawienie się idei obiektu rozwiązało kilka problemów:
- lepsze odzwierciedlenie świata rzeczywistego,
- ukrycie zmiennych przed wszystkimi metodami innych obiektów.
Programowanie obiektowe
KLASY
Klasy ( ang. class ) stanowi specyfikację ( wzorzec ) jednego lub więcej obiektów.
Często istnieje potrzeba tworzenia wielu obiektów tego samego typu ( tej samej klasy ).
Np.. Klasa Samochód
Obiekty: Ford, Mercedes, Toyota, …
Klasy i obiekty
-Tworzenie obiektów umożliwiają klasy.
- klasa- abstrakcyjna definicja jeszcze nie istniejącego obiektu, określająca jakie4 cechy charakteryzują dany obiekt i jakim operacjom obiekt ten można poddawać.
-Gdy mamy definiowaną klasę, powołujemy do życia obiekty podając konkretne wartości cech jaki dany egzemplarz wyróżniają.
- Na bazie jednej klasy na ogół powołujemy do życia wiele obiektów.
Cechy programowania obiektowego
- Abstrakcja
- Hermetyzacja ( Enkapsulacja )
- Dziedziczenie
- Polimorfizm
Cechy programowania obiektowego
- Abstrakcja
Program abstrahujemy od szczegółów, które na danym etapie nie są istotne.
- Hermetyzacja
Wszystkie dane i funkcje w programie grupujemy wokół klas udostępniając je jedynie upoważnionym przez nas klasom.
Programowanie obiektowe
DZIEDZICZENIE
Oznacza tworzenie pewnej klasy, zwanej rozszerzoną ( ang. extranded )na podstawie innej klasy, zwanej bazową ( ang. base class ).
Dziedziczenie pozwala łatwo dodawać nowe cechy i możliwości do istniejących klas. Dzieki temu mechanizmowi można wykorzystać istniejące klasy do innych celów.
Programowanie obiektowe
POLIMORFIZM
- Polega na traktowaniu obiektów rożnych klas w ten sam sposób.
- Aby to było możliwe, rozpatrywane klasy muszą być pochodnymi tej samej klasy bazowej.
- W praktyce polimorfizm polega zwykle na wywołaniu metody, które w rzeczywistości powoduje wykonanie różnych metod dla obiektów różnych klas.
Na przykład wywołanie metody obliczPole() dla obiektu klasy Kwadrat spowodowałoby wywołanie metody z klasy Kwadrat, podczas gdy dokładnie to samo wywołanie, ale dla obiektu klasy Prostokąt, wywołałoby inna metodę obliczPole() - klasy Prostokąt
Polimorfizm upraszcza projektowanie i implementowanie programu.
- wywołana metoda na rzecz pewnego obiektu, nie musi być zdefiniowana bezpośrednio w klasie opisującej obiekt, ale w której z klas nadrzędnych.
- Jeśli jednak z jakiegoś powodu metoda stworzona w klasie nadrzędnej nam nie odpowiada możemy na nowa tworzonej podklasie zdefiniować nowa wersje tej metody.
- W trakcie wykonywania programu automatycznie dobrana zostaje metoda najbliższa obiektowi na rzecz, którego metoda została wywołana.
Metodyki programowania
Programowanie ekstremalne ( ang. Extreme programming, XP ) ma na celu wydajne tworzenie małych i średnich „projektów wysokiego ryzyka”, czyli takich w których nie wiadomo do końca, co się tak naprawdę robi i jak to prawidłowo zrobić.
Poświęca temu koncepcja prowadzenia projektu informatycznego, wywodząca się z obserwacji innych projektów, które odniosły sukces.
Podstawa ekstremalnego programowania jest synergia wynikająca ze stosowania rozmaitych praktyk, które same w sobie mają wiele zalet, lecz mogą być trudne w zastosowaniu.
Łączne użycie tych praktyk ma zapewniać zanikniecie niedogodności każdej z nich.
Podstawowe założenie zostały sformułowane przez Kenta Becka
Zalecenia:
1. Iteracyjność
2. Nie projektować z założeniami z góry
3. Test zespołów
4. Ciągłe modyfikacje architektury
5. Programowanie parami
6. Stały kontakt z klientem
ITERACYJNOŚĆ
Program tworzy się w iteracjach ( krótkie, przyrostowe kroki programistyczne ) - i co ważniejsze - planuje tylko następną iterację.
Efektem każdej iteracji ( kilka tygodni ) powinna być wersja programu spełniającą założenia dla danej iteracji. Następnie planuje się co zrobić dalej.
NIE PROJEKTOWAC Z GÓRY
Nie można z góry wiedzieć jaka architektura będzie najlepsza dla danego problemu. Dlatego należy ją tworzyć w miarę rozszerzenia programu.
TESTY PODZESPOŁÓW
Testy podzespołów pisze się zanim w ogóle zacznie się pisać kod - najlepiej na początku iteracji. Potem pisze się kod, który potrafi je wszystkie przejść.
Takie testy dają zapewnienie ( o ile testy są dobrze napisane ), że to co ważne zostanie zaprojektowane, na to zaś co nie jest ważne programiści nie będą tracić czasu.
CIĄGŁE MODYFIKACJE ARCHITEKTURY
Architektura nie jest niczym, czego nie wolno ruszać. Jeśli modyfikacja architektury ułatwi przejście danej iteracji i nie zepsuje wyników testów uzyskanych na poprzednich, należy ją wykonać.
Pod tą zasadę podlega także usuwanie wszystkich znanych błędów przed rozszerzeniem funkcjonalności.
PROGRAMOWANIE PARAMI
Danym kodem powinny się zajmować dwie osoby. Kod, którym zajmuje się tylko jedna osoba, ma tendencje do stawiania się całkowicie niezrozumiałym dla kogokolwiek innego niż autor, a więc dodatkowy programista zwiększa jakość kodu. Poza tym umożliwia to wyłapanie wielu błędów.
STAŁY KONTAKT Z KLIENTEM
Specyfikacje są prawie zawsze wieloznaczne, dziurowane i sprzeczne ze sobą. Tak więc należy mieć stały kontakt z tym, dla kogo to oprogramowanie jest tworzone ( klient zamawiający program czy też użytkownicy końcowi ).
Jeśli kontakt jest dobry, można się nawet obyć bez specyfikacji.
SPRAWY KONTROWARSYJNE
- brak dokładnej specyfikacji.
- konieczna stała dostępność przedstawiciela klienta
Programowanie w cyklu kształcenia informatyków
- programowanie a projektowanie systemów informatycznych
- tworzenie aplikacji internetowych
- inżynieria oprogramowania
- programowanie a bazy danych
- programowanie a inżynieria wiedzy
Złożoność Algorytmów
- Rozmiar zadania - rozmiar danych niezbędnych dla realizacji algorytmu. Bierze się pod uwagę:
Rozmiar danych wejściowych
Rozmiar danych ???
Rozmiar danych wyjściowych
-Czas działania algorytmu - liczba kroków przekładająca się na czas faktyczny pracy maszyny realizującej algorytm. Istotne znaczenie mają w tym przypadku:
Złożoność rozwiązywanego zadania
Sposób konstrukcji algorytmu
Wydajność maszyny realizującej obliczenia
Złożoność obliczeniowa algorytmów - analiza algorytmów
- złożoność obliczeniowa jest podstawą własnością określaną dla algorytmów.
- Zadaniem analizy algorytmu jest określenie tej złożoności, a co za tym idzie realizowalności algorytmu.
- Algorytmy realizowane mają złożoność aproksymowaną funkcją:
- liniową ( wielomianem )
- logarytmiczną.
Mówi się, że takie algorytmy określają zadania ze zbioru zadań rozwiązywalnych ( a co za tym idzie implementowanych ). Najszybsze są algorytmy o złożoności logarytmicznej.
- nie potrafimy skutecznie implementować algorytmów o złożoności wykładniczej.
Złożoność obliczeniowa
Złożoność obliczeniowa algorytmu - ilość zasobów komputera jakiej potrzebuje dany algorytm. Pojęcie wprowadzili J. Hartmanis i R. Steams.
Najczęściej przez zasób rozumie się czas oraz pamięć - dlatego też używa się określeń „złożoność czasowa” i „złożoność pamięciowa”.
Rodzaje złożoności algorytmów
- Złożoność zasobowa ( pamięciowa ) - wyrażana w skali zajętości zasobów ( PAO, pamięci wewnętrznych itp. ) niezbędnych dla realizacji algorytmu.
- Złożoność czasowa - wyrażana w skali czasu wykonania algorytmu ( liczna kroków, aproksymowany czas rzeczywisty )
- Szacowanie wartości złożoności algorytmów będziemy realizować na kolejnych wykładach
- De facto wszystko przenosi się w konsekwencji na koszty eksploatacji oprogramowania, realizującego analizowany algorytm.
Funkcja kosztu algorytmu
- Funkcja kosztu zasobowego algorytmu stanowi odwzorowanie rozmiaru zadania w umowne jednostki kosztu algorytmu ( np. rozmiar zasobów, jednostki monetarne ( złotówki, dolary itp. )):
- FKz : RZ -> WKz, gdzie
FKz - funkcja kosztu zasobowego,
RZ - rozmiar zadania,
WKz- wartość kosztu zasobowego,
- Dla potrzeb wykładu pozostaniemy jedynie przy kosztach zasobowych algorytmu.
- Jednak nie tylko koszty zasobowe są brane pod uwagę. Często analizuje się inne koszty realizacji algorytmów ( np. pieniądze ).
Złożoność obliczeniowa
Rozróżnia się dwa typy złożoności:
- pesymistyczną, czyli w najgorszym przypadku,
- oczekiwaną
Jest tablica nieposortowana ( bez duplikatów ):
12 7 2 54 17 19 63
Chcąc wstawić do niej element, należy wykonać jedną operację ( jeden krok). Im więcej potrzebnych jest kroków, tym dłużej algorytm działa.
12 7 2 54 17 19 63 53
Nowy element jest wstawiony na pierwsze ??
Podsumowując:
Wyszukiwane: N/2 porównań
Wstawianie: 0 porównań, 1 przesunięcie
Usuwanie: N/2 porównań, N/2 przesunięć
Notacja O(f(N)) oznacza złożoność algorytmu „rzędu” f(N), gdzie f to pewna funkcja zmiennej N.
Jest to funkcja pomnożona przez pewną stała, dlatego można powiedzieć, że no.: wyszukiwanie w poprzednim algorytmie wymaga czasu O(N), a wstawienie elementu wymaga czasu stałego: O(1).
Używając notacji O(0 nie jest ważny czas wyrażony w sekundach, lecz zależność szybkości działania algorytmu od liczny elementów.
Najczęsciej spotykane złożoności:
- O(1)
- O(logN)
- O(N)
Charakterystyka wybranych języków programowania
Języki programowania
Język programowania jest środkiem umożliwiającym zapis algorytmów w postaci zrozumiałem dla człowieka, a równocześnie przetwarzanej do postaci zrozumiałem dla komputera ( maszyny algorytmicznej )
Semiotyka języka programowania ( syntaktyka, semantyka)
- Semiotyka zajmuje się badaniem symboli, znaków. W jej skład wchodzą:
Syntaktyka, zajmująca się określaniem przynależności danego słowa do zestawu słownika określanego języka programowania
Semantyka - zajmująca się określeniem zaznaczania programu, zapisanego w określonym języku programowania.
- Zapis algorytmu w języku programowania jest traktowany jako zapis formalny. Program komputerowy jest uznawany za jeden z rodzajów modeli matematycznych. Jest to algorytmiczny model zadania czy też rzeczywistości, która modelujemy.
Syntaktyka języka programowania
-Syntaktyka jest częścią ogólnej teorii znaków ( semiotyki ) i zajmuje się strukturą i formą wyrażeń, a także dopuszczalnymi zmianami ich formy, zwanymi „przekształceniami”.
- Wyróżnia się dwa rodzaje reguł składniowych:
-- reguły formowania, określające zbiór wyrażeń poprawnie zbudowanych na określonym alfabecie języka
- Najczęściej przyjmuje się, że mamy do czynienia z dwoma podzbiorami dziedziny nazywanej syntaktyką:
-- syntaktyka formalna, która jest rozumiana jako ogólne badanie formalne, dotyczące języków logiki i matematyki, jak również języków naturalnych,
-- syntaktyka logiczna, która zajmuje się badaniem języków logiki i matematyki ( np. rachunek predykatów, rachunek zadań )
Zapis definicji syntaktyki języka programowania
- Najczęściej stosuje się dwa sposoby opisu syntaktyki języka programowania. Śa to:
- zapis Backusa-Naura BNF ( Backus-Naur Form).
Został on po raz pierwszy zastosowany do opisu języka Algol60. Przykład definicji słownika w zapisie BNF:
<operator arytmetyczny> ::= + | - | * | / | ^ | DIV | MOD ;
<operator logiczny> ::= AND | OR | NOT | XOR | = ;
<nawias> ::= [ | ] | ( | ) | { | } | ` | begin | end.
- Diagramy syntaktyczne Wirth`a ( SD ). Zestaw symboli zapisywany jest w BNF.
Semantyka języka programowania
- Semantyka zajmuje się interpretacją formuł zapisanych zgodnie z określonymi regułami syntaktycznymi języka
- Tarski ( 1936r. ) zaproponował używanie pojęcia semantyka naukowa dla określenia semantyki zajmującej się formalnym badaniem prawdziwości formuł w zakresie znaczeniowy, definiowanego języka.
- Od lat 70-tych 20 wieku rozwija się tzw. Semantyka wartości logicznych (SWL).
Kryteria ( intuicyjne ) oceny języków programowania:
- prostota,
- łatwość nauczenia się,
- czytelność i zwartość struktur programowych,
- uniwersalność,
- modularność,
- niezależność od komputera,
- efektywność tłumaczenia programu źródłowego
Kod maszynowy
Jedyną zrozumiałą bezpośrednio dla komputera ( mikroprocesora ) forma przedstawiania instrukcji stanowią liczny bierne ( dwójkowe ), które dla lepszej czytelności dla człowieka zapisywane są często w postaci liczb szesnastkowych.
Program zapisany w takiej postaci nazywany jest kodem ( językiem) maszynowym.
Przykład fragmentu kodu:
00081E48: 48E7FFFF 2C780004 4EAEFF7C 49FA0042
Pierwsza kolumna przedstawia adresy pamięci operacyjnej.
Języki wyższego rzędu
Niedogodność programowania w asemblerze doprowadziły do powstania języków programowania wyższego rzędu.
Cechy tych języków:
- Istnieją standardy ( wzorce ) tych języków,
- są niezależna od sprzętu komputerowego,
Używają kompilatorów lub interpreterów.
Pascal
Język Pascal którego nazwa wywodzi się od matematyka Blaise'a Pascala, opracowany został w 1971 na politechnice w Zurychu przez Niklausa Wirtha, jednego z największych specjalistów w zakresie języków i metodologii programowania.
SQL
- SQL jest znany jako standardowy język programowania relacyjnych bez danych.
- Istnieje wiele wersji języka SQL, pierwsza z nich została opracowana w IBM-owskim San Jose Research Laboratory ( obecie Almaden Research Center ). Język ten, nazwany pierwotnie Sequel, był zastosowany jako cześć projektu System R powstającego we wczesnych latach 70-tych.
- Język Sequel rozwinął się od tego czasu i jego nazwa została zmieniona na SQL ( Structured Query Language - strukturalny język zapytań ).
- Większość obecnych systemów baz danych obsługuje język SQL.
- W roku 1986 Amerykański Narodowy Instytut Standardów ( ANSI ) i Międzynarodowa Organizacja Standardów ( ISO ) opublikowały standardy SQL, nazywany SQL-86. OBM opracował swój własny standard SQL, SAA-SQL ( System Application Architecture Database Interface ) w roku 1987.
Język C++
- Autorem C++ jest Bjarne Stroustrup. Język ten powstał w roku 1979.
- Jest on nadzbiorem, z pewnymi wyjątkami, języka C. Najważniejszą cechą tego języka jest pojęcie klasy jako typu definiowanego przez użytkownika. Klasy w c++ umożliwiają stosowanie technik programowania obiektowego. Zachowuje on jednak zdolność C do efektywnej współpracy z podstawowymi obiektami sprzętowymi ( bitami, bajtami, adresami itp.).
- C++ jest językiem ogólnego przeznaczenia; jego podstawową dziedziną zastosowań jest programowanie systemowe.
- Jest to język, którego nowe i różnorodne właściwości zostały zbudowane na fundamencie istniejącej już składni - języka C. Z tego powodu nazywany jest on hybrydowym językiem obiektowym.
Najważniejszą cechą jest pojęcie klasy jako typu definiowanego przez użytkownika. Klasy C++ umożliwiają stosowanie technik programowania obiektowego
Język C++
#include <iostrem>
using namespace std;
int main()
{
cout << “PRZYKŁAD” << endl;
}
Java
Platforma Java 2 ma trzy wersje:
J2SE ( Standard Edition )
J2EE ( Enterprise Edition)
J2MM ( Micro Edition )
Platforma .NET
.NET jest platforma stworzoną przez Microsoft jako odpowiedz na dwa produkty firmy SUN - języka JAVA i technologię J2EE.
.NET Framework składa się z maszyny wirtualnej ( CLR ) oraz biblioteki klas ( CLI ). Dzięki takiemu projektowi środowiska pojawiła się możliwość pisania programów w różnych językach i kompilacjach ich do jednakowego kodu pośredniego ( CLI )
Główne języki programowania:
C#
Visual Basic.NET
J#
C++
Platforma .NET
Mimo zapowiedzi Microsoftu, platforma .NET Framework nie jest w pełni przenośna, ponieważ działa jedynie na systemach z rodziny Windows.
Powstały dlatego alternatywne projekty.
MONO, czyli darmowa implementacja .NET rozwijana przez firmę Ximian,
DotGNU portable .NET.
Programowanie z wykorzystaniem komponentów wielokrotnego użycia ( Reusability )
Projektowanie programów z użyciem wielokrotnym kodu:
Problem: Jak w procesie programowania można wykorzystać istniejący kod ( oprogramowanie ) ?
Zagadnienia:
Programowanie z użyciem gotowych komponentów.
Szkielety programów ( frameworks ).
Rodziny programów użytkowych.
Wzorce projektowe.
Założenia:
W większości dziedzin tworzenie jest oparte na wielokrotnym użycie komponentów.
Podstawą projektów są komponenty, które wypróbowano i przetestowano ( np.: budownictwo ).
W wypadku tworzenia oprogramowania potrzebne jest podobne podejście.
Oprogramowanie powinno być uważane za stały składnik majątku, który można wzbogacać ( uzupełniać ).
Użycie wielokrotne tych składników majątku jest zasadniczym warunkiem zwiększenia stopy zwrotu z inwestycji w tworzenie i eksploatację oprogramowania.
Używane wielokrotnie elementy oprogramowania:
Użycie wielokrotne funkcji.
Można wielokrotnie użyć komponenty programowe, takie jak pojedyncze funkcje matematyczne.
Użycie wielokrotne komponentów.
Można wielokrotnie używać komponentów programu użytkowego, mających różne rozmiary od podsystemów do pojedynczych obiektów.
Użycie wielokrotne systemów programów użytkowych.
Można ponownie użyć cały system programów użytkowych przez włączenie go w niezmienionej postaci do innych systemów albo budowę rodziny programów użytkowych działających na różnych platformach lub dostosowanych do potrzeb konkretnych użytkowników.
Praktyka programowania:
Użycie wielokrotne funkcji jest uznane i występuje w postaci standardowych bibliotek funkcji nadających się do wielokrotnego użycia, takich jak biblioteki matematyczne i graficzne.
Użycie wielokrotne programów użytkowych praktykuje się już od wielu lat - firmy budujące oprogramowanie implementują swoje systemy na wielu maszynach oraz dostosowują ( adaptują ) je do rozmaitych środowisk.
Zalety użycie wielokrotnego:
Zwiększona niezawodność.
Zmniejszone zagrożenie procesu.
Efektywne wykorzystanie specjalistów.
Zgodność ze standardami.
Przyspieszone tworzenie.
Wymagania stawiane tworzeniu oprogramowania z użyciem wielokrotnym:
Musi istnieć możliwość znalezienia odpowiedniego komponentu użycia wielokrotnego.
Osoba ponownie używająca komponent musi być przekonana, że będzie on działał zgodnie ze specyfikacją i będzie niezawodny.
Komponenty muszą mieć dokumentację, która pomoże osobie pragnącej je wykorzystać w zrozumieniu ich i zaadaptowaniu do nowych zastosowań.
Koszty i kłopoty:
Zwiększone koszty pielęgnacji.
Brak wspomagania narzędziowego.
Syndrom „nie wymyślono tutaj”.
Prowadzenie biblioteki komponentów.
Znajdowanie i adaptowanie komponentów użycia wielokrotnego.
Podejścia do tworzenia programów z użyciem gotowych komponentów:
Generowanie programów.
Tworzenie komponentowe.
Szkielety programów ( frameworks ).
Wzorce projektowe.
Generowanie programów:
Polega ono na umieszczaniu wielokrotnie używanej wiedzy w systemie generowanie programów ( w generatorze ), który może posługiwać się językiem specyficznym dla dziedziny zastosowania.
W opisie programu użytkowego w abstrakcyjny sposób określa się, które komponenty do wielokrotnego użycia mają być wykorzystane, jak mają być połączone i jakie mają mieć parametry.
Na podstawie tej informacji można wygenerować działający system oprogramowania.
Projektowanie komponentowe:
Pojawiło się we wczesnych latach dziewięćdziesiątych XX wieku w postaci podejścia do tworzenia systemów oprogramowania z użyciem wielokrotnych komponentów.
Przesłanka powstanie było dostrzeżenie, że programowanie obiektowe nie doprowadziło do szerokiego stosowania wielokrotnego użycia jak się wcześniej spodziewano:
Poszczególne klasy obiektów były zbyt szczegółowe i specyficzne.
Musiały by dowiązane do programu użytkowego w czasie kompilacji lub konsolidacji systemu.
Do ich wykorzystania była potrzebna szczegółowa wiedza, co zwykle oznaczało konieczność udostępnienia kodu źródłowego.
Powodowało to trudne problemy ze sprzedażą komponentów na rynku.
Wbrew wczesnym optymistycznym przewidywaniom nigdy nie powstał znaczący rynek pojedynczych obiektów.
Komponenty:
Postrzeganie komponentu jako dostawcy usługi dotyczy dwóch istotnych charakterystyk komponentu użycia wielokrotnego:
Komponent jest niezależnym wykonywalnym bytem. Kod źródłowy nie jest dostępny, a zatem komponentu nie kompiluje się z innymi komponentami systemu.
Komponenty publikują swój interfejs. Wszystkie interakcje odbywają się przez ten interfejs. Interfejs komponentu jest zapisywany w kategoriach parametryzowanych operacji. Jego wewnętrzny stan nigdy nie jest ujawniany.
Interfejsy komponentów:
Interfejs oferowany:
Definiuje się usługi oferowane przez ten komponent.
Interfejs wymagany:
Określa się, jakie usługi muszą być dostępne w systemie używającym tego komponentu, jeśli nie są one oferowane, to komponent nie będzie działał.
Poziomy abstrakcji komponentów:
Abstrakcja funkcyjna.
Komponent jest implementacją jednej funkcji np.: matematycznej.
Przypadkowe grupowanie.
Komponent jest grupą luźno powiązanych bytów.
Abstrakcja danych.
Komponent jest abstrakcją danych lub klasą obiektowego języka programowania.
Abstrakcja grupowa.
Komponent jest grupą powiązanych klas, które działają razem.
Abstrakcja systemowa.
Komponent jest całym samodzielnym systemem.
Proces przypadkowego ponownego użycia komponentów:
Poszukaj Przyłącz
Zaprojektuj architekturę Wyspecyfikuj komponentów znalezione
systemu komponenty użycia wielokrotnego komponenty
Trudności przy tworzeniu komponentowym:
Kwestia pielęgnacji i doskonalenia systemu:
Kod źródłowy komponentów jest zwykle niedostępny. W takiej sytuacji, gdy program użytkowy wymaga modyfikacji, nie ma możliwości modyfikacji komponentu mającej na celu odzwierciedlenie nowych wymagań.
W tej fazie zmiana wymagań tak, by pasowały do istniejących komponentów, nie jest zwykle możliwa, gdyż program użytkowy jest już wykorzystywany.
Trzeba wiec dodatkowej pracy nad ponownym użyciem komponentów i w miarę upływu czasu powoduje to zwiększenie kosztów pielęgnacji.
Tworzenie komponentowe umożliwia jednak szybsze dostarczenie oprogramowania, firmy mogą więc zaakceptować te wyższe koszty w odległej przyszłości.
FrameWorks - Szkielety ( zręby ) programów użytkowych:
Frameworks ( szablony programistyczne, szkielety, zręby programów użytkowych ) są projektami podsystemów składających się z kolekcji klas abstrakcyjnych i klas konkretnych oraz interfejsu między nimi.
Poszczególne części podsystemu programów użytkowych implementuje się przez dodanie komponentów i opracowanie konkretnych implementacji klas abstrakcyjnych zrębu programu.
Szkielety rzadko są programami użytkowymi.
Szkielet, zrąb programu ( framework ):
Idea przygotowywania szkieletów ( zrębów ) aplikacji wynika z rozwoju własnego warsztatu programisty.
Właściwy dla danej aplikacji kod stanowi jedynie część całego programu. Reszta się powtarza i daje się wielokrotnie zastosować w innych aplikacjach.
Rozszerzanie szkieletów ( zrębów ) programów:
Rozszerzenie zrębu może polegać na dodaniu konkretnych klas, które dziedziczą operacje po klasach abstrakcyjnych zrębu.
Dodatkowo można zdefiniować funkcje wywołane zwrotnie.
Są to metody, które wywołuje się w odpowiedzi na zdarzenia rozpoznane przez zrąb.
Użycie wielokrotne produktów COTS:
Podejście produktów COTS ( Commercial-Off-The-Shelf - komercyjne z półki ) może by zastosowane do każdego komponentu oferowanego przez zewnętrznego dostawcę.
Zwykle używa się go jednak tylko w wypadku produktów będących systemami oprogramowania.
Od wielu lat wielokrotnie używano niektórych rodzajów systemów COTS. Systemy baz danych są chyba najlepszym tego przykładem.
Rodziny programów użytkowych:
Rodzina programów użytkowych albo linia produktów jest zbiorem powiązanych programów użytkowych, które mają wspólna architekturę charakterystyczną dla dziedziny.
Poszczególne programy użytkowe są jednak na swój sposób wyspecjalizowane.
Wspólny rdzeń rodziny programów użytkowych jest za każdym razem ponownie używany, gdy jest potrzebny nowy program użytkowy.
Tworzenie nowego programu może polegać na napisaniu dodatkowych komponentów i adaptacji niektórych komponentów programu użytkowego tak, aby sprostać nowym oczekiwaniom.
Systemy inwentaryzacyjne:
Takie systemy muszą oferować podstawowe udogodnienia, takie jak dodawanie zasobu do spisu, usunięcie zasobu ze spisu, przeglądanie i wyszukiwanie w spisie oraz tworzenie raportów.
Można więc tak zaprojektować architekturę systemu inwentaryzacyjnego, aby stał się rodziną programów użytkowych, której każdy członek służy do obsługi innych rodzajów zasobów.
Wzorce projektowe:
Starając się ponownie użyć komponent wykonywalny nie uchronimy się przed ograniczeniami wynikającymi ze szczegółowych decyzji projektowych podjętych przez osoby implementujące ten komponent.
Jeśli te decyzje projektowe nie są zgodne z przyjętymi przez nas szczegółowymi wymaganiami, to ponowne użycie komponentu jest niemożliwe albo prowadzi do istotnego zmniejszenia efektywności systemu.
Jednym ze sposobów radzenia sobie z tą kwestią jest użycie wielokrotne bardziej abstrakcyjnych projektów, które nie obejmują szczegółów implementacyjnych.
Obecnie to podejście do użycie wielokrotnego przybrało postać wzorców projektowych.
Elementy wzorca projektowego:
Nazwa spełniająca funkcję znaczącego odsyłacza do wzorca.
Opis rodzaju problemu, w którym opisuje się części rozwiązania projektowego, ich związki i zobowiązania.
Wyjaśnienie konsekwencji zastosowania, wzorca tzn. wyników końcowych i niezbędnych kompromisów.
Klasy wzorców:
Wzorce infrastruktury systemów:
Wspomagają tworzenie infrastruktury systemów, takiej jak komunikacja, interfejsy użytkownika i kompilatory.
Wzorce integracji programów warstwy pośredniej:
Składają się ze zbioru standardów i związanych z nimi klas obiektów, które wspomagają komunikację komponentów i wymianę informacji.
Wzorce zastosowań przemysłowych:
Dotyczą specyficznych dziedzin zastosowań, takich jak telekomunikacja lub finanse.
Wzorzec Model-Widok-Koordynator ( Kontlorer ):
Po raz pierwszy przedstawiono go w latach osiemdziesiątych XX wieku jak podejście do projektowania GUI, który obejmuje wiele przedstawień obiektów i różne style interakcji z każdym z tych przedstawień.
MVC pomaga w prezentacji danych na różne sposoby i odrębne oddziaływanie każdą z nich.
Gdy dane są modyfikowane, przez jedną prezentację, wszystkie inne są aktualizowane.
Podsumowanie:
Projektowanie z użyciem wielokrotnym polega na projektowaniu oprogramowania zgodnie z istaniejącymi przykładami dobrych projektów i wykorzystaniu komponentów programowych tam, gdzie są potrzebne.
Korzyści z użycia wielokrotnego to niższe koszty, szybsze tworzenie oprogramowania i mniej zagrożeń. Przez wykorzystanie wiedzy specjalistów do budowania komponentów użycia zwiększa się niezawodność systemu, a specjaliści są wydajniejsi.
Tworząc komponentowo, polegamy na komponentach „czarnych skrzynkach” z jasno określonymi interfejsami, wymaganym i oferowanym. Rodzaje komponentów, które można użyć wielokrotnie, obejmują funkcje, abstrakcje danych, zręby i całe systemy programów użytkowych.
Użycie wielokrotne produktów COTS polega na wykorzystaniu wszystkich systemów z półki. Takie systemy mają mnóstwo funkcjonalności lub użycie wielokrotne może znacząco zmniejszy koszty i czas tworzenia.
Selekcja „else” jest opcjonalna.