Metodyki programowania

Szczawik

     1 Wstęp
     2 Klasyfikacja metodyk
     3 Podstawowe nadtypy paradygmatów
     4 Podstawowe typy paradygmatów
     5 Podstawowe rodzaje metodyk
          5.1 Programowanie liniowe
          5.2 Programowanie proceduralne
          5.3 Programowanie stanowe
          5.4 Programowanie funkcyjne
          5.5 Programowanie strukturalne
          5.6 Programowanie obiektowe
          5.7 Programowanie generyczne
          5.8 Programowanie zdarzeniowe
          5.9 Programowanie agentowe

Wstęp

Metodyka (zwana też często paradygmetem) to ustandaryzowane dla wybranego obszaru podejście do rozwiązywania problemów. Metodyka programowania to wykorzystywany sposób programowania oparty na mechanizmach, udostępnionych przez język programowania oraz jego konkretną implementację, a więc kompilator, nawet czasem i całość środowiska programistycznego. W związku z ewolucją języków programowania oraz ich odmiennym zastosowaniem, w ramach podobnej grupy języków mogą występować znaczne różnice w dostępnych metodykach.

Środowisko rzadko narzuca konkretną metodykę; na ogół oferuje możliwości zastosowania jednej z pewnego zbioru, albo wręcz mieszanie i przeplatanie kilku w ramach jednego kodu. Dobór odpowiedniej metodyki zależy od rozwiązywanego problemu, sposobu jego realizacji oraz indywidualnych preferencji programisty. Ma jednak bardzo duży wpływ na złożoność powstałego kodu, proces tworzenia aplikacji, a czasem i szybkość działania programu wynikowego.

Niniejszy tekst nie ma na celu encyklopedycznej klasyfikacji metodyk, oferowanych przez języki programowania, a jedynie przedstawienie ich cech charakterystycznych, wad oraz zalet. Jest oparty na wiedzy i doświadczeniu autora.

Klasyfikacja metodyk

W związku z dużą ilością języków programowania i bogactwem literatury, w różny sposób definiującej podział metodyk, najczęściej przyjmuje się zasadę trójpodziału: na nadtyp paradygmatów, na rodzinę (typ) paradygmatów i na konkretne metodyki (rodzaj).

Podstawowe nadtypy paradygmatów

Podstawowymi nadtypami są:

#Programowanie stacjonarne - tworzenie programu, uwzględniającego obliczenia wykonywane przez jeden procesor, włókno, wątek i proces na jednym lub więcej zbiorach danych
#Programowanie rozproszone - tworzenie programu, uwzględniającego obliczenia wykonywane bez współdzielenia zasobów obliczeniowych, ze współdzieleniem danych często rozproszonych geograficznie; istnienie dodatkowych zadań komunikacji między systemami oraz synchronizacji
#Programowanie równoległe lub współbieżne - tworzenie programu, uwzględniającego obliczenia wykonywane przez więcej niż jeden procesor, włókno, wątek lub proces w sposób równoczesny lub z przełączaniem; istnienie dodatkowych zadań komunikacji, synchronizacji oraz podziału danych między procesorami, włóknami, wątkami lub procesami

Programowanie rozproszone jest szczególnym przypadkiem programowania równoległego. Jednak programowanie równoległe nie musi być programowaniem rozproszonym.
Pomimo, że powyższe nadtypy mogą wiązać się z konkretnymi architekturami systemów i określonymi sposobami przetwarzania, nie są z nimi równoznaczne. Są jedynie podejściem zorientowanym na tworzenie programów dla określonych rodzajów platform. Nie wpływają one na ogół na rodzaj użytej metodyki, ale często na wybór algorytmu lub wręcz formę, kolejność czy sposób złożenia instrukcji w celu osiągnięcia optymalnego wyniku na platformie docelowej.

Podstawowe typy paradygmatów

Podstawowymi typami paradygmatów są:
#Programowanie imperatywne (co - jakie instrukcje - wykonanać na danych programu, by otrzymać pożądany rezultat?)
#Programowanie funkcyjne (w jaki sposób złożyć wyrażenia, by otrzymać pożądany rezultat?)
#Programowanie opisowe (dla jakiego stanu wejść i postaci systemu otrzymany zostanie pożądany rezultat?)
#Programowanie logiczne (dowodem jakiego twierdzenia jest pożądany rezultat?)

Programowanie typu imperatywnego jest często mylone z metodyką programowania proceduralnego (zwanego czasem również programowaniem imperatywnym). Programowanie typu funkcyjnego jest często mylone z metodyką programowania funkcyjnego. Jednak jako typy paradygmatów, a nie same rodzaje paradygmatów, są pojęciami szerszymi.

Podstawowe rodzaje metodyk

Podstawowymi rodzajami paradygmatów są:

#Programowanie liniowe
#Programowanie proceduralne
#Programowanie stanowe
#Programowanie funkcyjne
#Programowanie deklaratywne
#Programowanie strukturalne
#Programowanie obiektowe
#Programowanie aspektowe
#Programowanie logiczne
#Programowanie generyczne
#Programowanie intencyjne
#Programowanie ekstremalne
#Programowanie zdarzeniowe
#Programowanie agentowe
#Programowanie wieloparadygmetowe
#Programowanie komponentowe

Programowanie liniowe

Metodyka programowania liniowego oparta jest na założeniu, że całość programu jest postrzegana jako jeden, ciągły blok. Dane programu mogą znajdować się w tym samym bloku, albo w oddzielnym lub oddzielnych fragmentach pamięci. Wykonanie programu jest procesem, polegającym na wykonywaniu kolejno operacji od początku bloku do końca.

W metodyce tej nie istnieje pojęcie procedury, funkcji, metody czy podprogramu. W ramach bloku możliwe jest przemieszczanie się jedynie poprzez instrukcje skoków warunkowych i bezwarunkowych, często związanych z instrukcjami warunkowymi, sterującymi pętlą lub bezpośrednim skokiem do etykiety (rodzina instrukcji Go To). Cechą charakterystyczną języków wspierających programowanie liniowe jest możliwość wstawiania do kodu znaczników lokacji czyli etykiet.

Metodyka ta często jest wykorzystywana podczas programowania prostych układów mikroprocesorowych, szczególnie w przypadku, gdy nie posiadają zaimplementowanej wewnętrznie obsługi stosu, przez co nie mają możliwości automatycznego skoku do podprogramu. Odbywa się to klasycznie przed odłożenie aktualnego adresu programu na stos i skok w miejsce odpowiadające początkowi procedury lub funkcji; po wykonaniu podprogramu następuje pobranie ze stosu adresu i powrót do zapamiętanego miejsca wykonania. Jeśli układ nie posiada zaimplementowanej obsługi stosu, na ogół metodyka liniowa jest jedyną dostępną, chyba, że kompilator automatycznie tłumaczy kod, wykorzystujący inną metodykę, na kod maszynowy, odpowiadający programowaniu liniowemu.

Programowanie liniowe jest często nierozumiane lub atakowane przez zwolenników programowania strukturalnego. Podstawę do krytyki stanowi artykuł Edsgera W. Dijkstry Go To Statement Considered Harmful (Communications of the ACM, 1968)

Programowanie liniowe jest często stosowane w językach rodzin assembler, instruction list, przy programowaniu mikrokomputerów, przemysłowych układów sterowania, a także w starszych odmianach języków Pascal oraz Basic. Jest jednocześnie wspierane przez prawie wszystkie języki programowania z lat siedemdziesiątych.

Programowanie liniowe jest zaliczane do metodyk typu imperatywnego.

Zalety:

  • niekorzystanie ze stosu,
  • podobieństwo formy kodu maszynowego i źródłowego.

Wady:

  • duże rozmiary kodu,
  • częsta duża ilość etykiet - zmniejszenie czytelności kodu,
  • trudność w analizie kodu źródłowego (patrz: Dijkstra), związana z brakiem instrukcji dedykowanych konstrukcjom logicznym,
  • brak możliwości dekompozycji problemu na mniejsze funkcje.

Programowanie proceduralne

Metodyka ta jest oparta na założeniu o potrzebie dekompozycji problemów i tworzeniu programów w taki sposób, że blok główny programu stanowi szkielet, przez co określa kolejność toku prowadzonych operacji, natomiast za poszczególne operacje odpowiadają bloki podprogramów w postaci procedur oraz funkcji. W związku z bliskością programowania proceduralnego i liniowego, metodyki te są bardzo często mylone. W programach proceduralnych często spotykane są zarówno instrukcje programowania liniowego (na przykład Go To użyte w celu opuszczenia zagnieżdżonych pętli) oraz strukturalnego (użycie prostych konstrukcji warunkowych oraz pętli).

Dane mogą być zarówno umiejscowione w bloku programu, jak i oddzielnym obszarze - zależnie od platformy. W przeciwieństwie do programowania strukturalnego, dane nie są grupowane (do postaci encji: struktur, rekordów, krotek, unii - zależnie od przyjętej implementacji i nomenklatury). Cechą charakterystyczną jest duża ilość zmiennych (tak globalnych, jak i lokalnych) oraz częste wykorzystanie tablic.

Programowanie liniowe jest często stosowane w językach rodziny assembler (w tym na procesory rodziny x86), przy programowaniu mikrokomputerów, a także przy konstrukcji programów analityczno-obliczeniowych, tworzonych w językach ogólnego przeznaczenia (na przykład Pascal, C). Warto zwrócić uwagę, że metodyka ta jest też często wykorzystywana w językach skryptowych (w związku z brakiem możliwości tworzenia encji w niektórych z nich) oraz w językach obsługi stron internetowych, na przykład: po stronie klienta - Java Script, po stronie serwera PHP (w związku w prostotą implementacji operacji jako ciągłych kroków z użyciem podprogramów).

Nie oznacza to, że języki, wspierające programowanie proceduralne, nie mają możliwości tworzenia encji. Na ogół jednak wykorzystanie encji jest oznaką zmiany podejścia do rozwiązywanego zagadnienia, a więc zmianą metodyki na inną.

Programowanie proceduralne jest zaliczane do metodyk typu imperatywnego.

Zalety:

  • możliwość dekompozycji kodu
  • podobieństwo formy kodu maszynowego i źródłowego.

Wady:

  • duża ilość zmiennych
  • rozdzielenie danych i operacji na nich wykonywanych
  • brak grupowania danych w sposób logiczny

Programowanie stanowe

Metodyka ta jest bardzo rzadko stosowana w programowaniu komputerów osobistych. Jest jednak jedną z głównych podczas programowania elektroniki przemysłowej, w tym PLC (programowalnych sterowników logicznych). Polega na tworzeniu programu, nie poprzez pisanie kodu, ale poprzez tworzenie diagramu, opisującego zachowanie systemu.

Zależnie od tego, na bazie jakiego diagramu oparty jest język, oprogramowywane mogą być inne zjawiska i procesy.

Przykładowo w implementacjach języka Grafcet/Graftec (w normie IEC 61131-3 określonego jako 1 z 5 języków do oprogramowania PLC) tworzony jest diagram przepływu sekwencyjnego (SFC). Należy określić w nim wszystkie stany, w jakich może znaleźć się system, oraz warunki dokonania tranzycji między tymi stanami. Wartości zmiennych w danym stanie oraz warunki tranzycji ustawiane są za pomocą jakiegoś pomocniczego języka, lub są konfigurowane za pomocą interfejsu użytkownika.

Inne języki, operujące na diagramach drabinkowych (LD), opisują graficznie logikę matematyczną układu. Nierzadko diagramy drabinkowe posługują się symbolami bramek logicznych i elementów sekwencyjnych. Diagramy te są też często używane do oprogramowania PLD (programowalnych urządzeń logicznych) oraz PLC.

Programowaniem stanowym jest również opisanie tabelą stanu wyjść układu elektronicznego na podstawie stanu jego wejść. Takie programowanie często jest stosowane dla elementów PLD.

Języki stanowe kierowane są do osób, które potrzebują zaprogramować układ do realizacji określonego typu zadań, a nie w złożony sposób matematyczny czy funkcjonalny. System, interpretowany jako element wykonawczy programu, ma zachować się w określony sposób lub wykonywać odpowiednie kroki, reagując na stan własny i otoczenia. Nie ma natomiast realizować złożonej funkcjonalności obliczeniowej - najwyżej podstawowe funkcje logiczne.

Programowanie stanowe jest zaliczane do metodyk typu opisowego.

Zalety

  • uzależnienie zachowania systemu od stanu
  • praca oparta na idei automatów skończonych
  • niewymagana znajomość poleceń języka od programisty

Wady

  • bez dodatkowego wsparcia innego języka trudno wdrożyć złożoność obliczeniową
  • program nie ma formy tekstowej
  • prosty program może być reprezentowany przez złożony diagram

Programowanie funkcyjne

Metodyka ta jest rozpowszechniona wśród programistów, których podejście do programowania jest ściśle oparte na konstrukcjach matematycznych. Matematyczną podstawę tej metodyki programowania stanowi rachunek lambda oraz rachunek lambda z typami

W przeciwności do programowania stanowego, stan maszyny obliczeniowej nie powinien wpływać na działanie programu. Natomiast rezultat powinien być otrzymany na podstawie złożenia funkcji. Ze względu na brak pamięci odnośnie stanu maszyny, nie stosuje się zmiennych, a konstrukcje pętli zastępuje się rekurencją. W przeciwności do ograniczonego (lub całkowicie zaniechanego) stosowania zmiennych, bardzo ważną rolę odgrywają liczne typy zmiennych, przez co możliwe jest przekazywanie przez funkcje złożonych wartości wielowymiarowych oraz encji.

Wynik jest otrzymywany na podstawie złożenia funkcji. To założenie pociąga za sobą wielokrotnie zagnieżdżone konstrukcje, w których wynik jednej funkcji jest, bez pośrednictwa zmiennej, przekazywanym przez wartość lub referencję (rzadko przez wskaźnik) argumentem funkcji zewnętrznej.

Pętla zastępowana jest przez rekurencję, gdyż użycie zmiennej licznikowej do pętli stanowiłoby zapamiętanie stanu części maszyny obliczeniowej, natomiast rekurencja jest wywołaniem funkcji przez tą samą funkcję, przez co zachowana jest forma zagnieżdżania wywołań funkcji jako własnych argumentów.

W programowaniu funkcyjnym bardzo ważną rolę odgrywają pojęcia: efekt uboczny, wartościowanie zachłanne, wartościowanie leniwe oraz mechanizm wejścia/wejścia oparty o monady.

Do klasycznych języków wspierających programowanie funkcyjne należy Haskel oraz LISP. Metodyka ta jest też popularnie stosowana w językach Python, F#, Nemerle czy Ruby. Większość języków, stosujących metodykę strukturalną lub obiektową, pozwala na zastosowanie także metodyki funkcyjnej, jednak takie podejście nie jest często stosowane; zamiast tego popularność zyskał kod mieszany: strukturalno-funkcyjny lub obiektowo-funkcyjny.

Programowanie funkcyjne samodzielnie jest zaliczane metodyk typu funkcyjnego.

Zalety:

  • zależność budowy programu od złożenia funkcji matematycznych
  • łatwość numerycznej weryfikacji modelu
  • prostota przebiegu procedury testowania

Wady:

  • złożoność zagnieżdżeń wywoływanych funkcji
  • ograniczenie stosowania zmiennych tak lokalnych, jak globalnych
  • duża zajętość stosu przy kolejnych wywołaniach funkcji oraz przy zastosowaniu rekurencji

Programowanie strukturalne

Metodyka ta jest kolejnym krokiem w rozwoju programowania proceduralnego. Wiąże się z analizą strukturalną, jednak nie jest z nią tożsama! Program strukturalny składa się z bloku głównego, który określa kolejność toku prowadzonych operacji, natomiast za poszczególne operacje odpowiadają bloki podprogramów w postaci procedur oraz funkcji. W programach strukturalnych rzadko spotykane są instrukcje programowania liniowego; nacisk kładziony jest na wykorzystanie złożonych (blokowych) instrukcji języka - dedykowanych konstrukcji logicznych, a także instrukcji sterujących przebiegiem programu.

Dane mogą być zmiennymi typów prostych, ale najczęściej są grupowane do postaci typów złożonych - encji (struktur, rekordów, krotek, unii - zależnie od przyjętej implementacji i nomenklatury). Cechą charakterystyczną jest mniejsza, niż w programowaniu proceduralnym, ilość zmiennych oraz częste wykorzystanie tablic o elementach typu złożonego. Znamiennym jest też przekazywanie do podprogramów danych w postaci pojedynczej zmiennej typu złożonego, zamiast wielu parametrów o typach prostych.

Programowanie strukturalne jest często stosowane w ramach implementacji interfejsu programowania aplikacji systemów operacyjnych (tak Linux jak Windows), gdzie nie jest wykorzystywane programowanie zorientowane obiektowo. Jest podstawowym paradygmatem języków Pascal, C oraz wielu innych.

Programowanie strukturalne jest zaliczane do metodyk typu imperatywnego.

Zalety:

  • możliwość łatwej dekompozycji kodu
  • podobieństwo formy kodu maszynowego i źródłowego.
  • mała ilość zmiennych
  • zmienne grupujące powiązane dane

Wady:

  • rozdzielenie danych i operacji na nich wykonywanych

Programowanie obiektowe

Metodyka ta wiąże się z analizą obiektową, jednak nie jest z nią tożsama! Do podstawowych pojęć paradygmatu obiektowego należą klasa, obiekt, metoda, pole (zwane też właściwością), enkapsulacja, dziedziczenie, polimorfizm.

Klasa to definicja obiektu, łącząca zarówno stan obiektu, określony wartościami pól, jak możliwe zachowanie obiektu, określone dostępnymi metodami.
Obiekt to utworzony egzemplarz określonej klasy, który posiada własny, indywidualny stan i zbiór zachowań.
Metoda to funkcja lub procedura, skojarzona z ogółem klasy lub poszczególnymi jej obiektami; określa możliwe zachowania danego obiektu pewnej klasy.
Pole/Właściwość to zmienna, skojarzona z ogółem klasy lub poszczególnymi jej obiektami; określa aktualny stan danego obiektu pewnej klasy.
Enkapsulacja to mechanizm ograniczania dostępu do pól lub metod, podczas prób odwołania się do nich spoza obiektu, klasy, obiektu potomnego, biblioteki lub programu.
Dziedziczenie to mechanizm definiowania nowej klasy na bazie już istniejącej, wzbogacając ją o nowe pola, metody lub zmieniając zakres ich widoczności.
Polimorfizm to mechanizm wywołania metody obiektu, dla którego ją wywołano, bez względu na typ referencji lub wskaźnika, użytego do wywołania.

Program obiektowy składa się z bloku głównego (który często jest metodą określonej klasy lub obiektu). W ramach tego bloku mogą być tworzone obiekty pewnych klas. Podejście obiektowe pozwala na łączenie danych oraz funkcji, które na nich operują, w jedną całość. Pozwala również na łatwe rozdzielenie fragmentów kodu, odpowiadających za opis osobnych elementów wycinka rzeczywistości, przedstawianych przez kod programu. Znamiennym jest przekazywanie całych obiektów do wywoływanych metod i operowanie na nich, zamiast wykonywania bezpośredniego dostępu do danych, co często jest ograniczone przez określenie zakresu widoczności pola lub metody (enkapsulacja).

Programowanie zorientowane obiektowo często występuje w połączeniu ze strukturalnym (programowanie wieloparadygmatowe) lub samodzielnie. Jest podstawowym paradygmatem języków C++, C#, Java oraz wielu innych.

Programowanie obiektowe jest zaliczane do metodyk typu imperatywnego.

Zalety:

  • możliwość łatwej dekompozycji kodu
  • powiązanie danych i operacji na nich wykonywanych
  • możliwość ograniczenia dostępu do danych lub operacji w określonych miejscach kodu

Wady:

  • częsta potrzeba wykorzystania dużej ilości nadmiarowego kodu do zdefiniowania klas
  • potrzeba przeprowadzenia szczegółowej analizy i projektowania budowy klas z uwzględnieniem widoczności metod

Programowanie generyczne

Metodyka ta, zwana również programowaniem uogólnionym, jest oparta o założenie, że wiele fragmentów kodu bywa niepotrzebnie powtarzanych tylko dlatego, że służą do przetwarzania w identyczny sposób danych różnych typów. Podejście generyczne pozwala na tworzenie uogólnionych wzorców konstrukcji kodu (zwanych zależnie od języka: szablonami, funktorami, abstraktami, widmami lub paczkami typowanymi). Wzorzec taki (na przykład w postaci wzorca struktury, klasy, funkcji, procedury lub typu złożonego - zależnie od danego języka) jest deklarowany przy wstępnie nieokreślonych typach, wykorzystanych zmiennych czy pól. Dopiero podczas definiowania konkretnej instancji dla wzorca należy podać podstawienia typów dla wcześniejszych typów nieokreślonych.

Częstym przykładem idei programowania generycznego jest deklaracja wzorca klasy, implementującego działanie listy. Jako, że do opisu działania klasy, obsługującej listę, nie jest konieczne znanie typów danych w jej węzłach, można działanie opisać dla dowolnego typu T. Dopiero przy deklarowaniu lub tworzeniu obiektu listy zmiennych typu float za T podstawiony powinien zostać ten typ; z kolei obiekt listy zmiennych typu string wymaga podczas deklarowania lub tworzenia podstawienia string za T. Utworzenie zatem obiektów, obsługujących listy float oraz string (jak również każdego innego typu), wymaga tylko jednego, wspólnego i uniwersalnego opisu klasy: dla abstrakcyjnego typu T.

Programowanie generyczne, ponieważ oferuje uniezależnienie konstrukcji kodu od przetwarzanych typów zmiennych, a zatem pozwala na uogólnianie rozwiązań określonych problemów, stało się podstawą rozwoju wzorców projektowych.

Programowanie generyczne jest najczęściej zaliczane do metodyk typu imperatywnego, mimo że często występuje również w językach, wykorzystujących metodykę typu funkcyjnego.

Zalety:

  • oszczędność kodu podczas wyrażania konstrukcji, niezależnych od typów zmiennych
  • uniwersalność kodu łatwego do ponownego wykorzystania

Wady:

  • trudności w poszukiwaniu błędów związane ze zbyt ogólnymi podpowiedziami kompilatorów dla uogólnionych konstrukcji (rozwiązaniem tego problemu są koncepty).
  • trudności w poszukiwaniu i usuwaniu błędów, które występują tylko przy określonych typach danych
  • brak odzwierciedlenia bezpośrednich definicji klas w typach tworzonych obiektów
  • nadużywanie przez programistów konstrukcji generycznych, traktowanych często jako zamienników makr prekompilatora

Programowanie zdarzeniowe

Metodyka ta jest stworzona w oparciu o założenie, że w systemie zdefiniowano możliwość wystąpienia określonych zdarzeń (na przykład naciśnięcie klawisza, pokazanie okna, kliknięcie myszą). Do programisty należy jedynie zaprogramowanie zmian stanu aplikacji pod wpływem wystąpienia określonego zdarzenia.

Metodyka ta jest jedną z najchętniej wykorzystywanych współcześnie do tworzenia aplikacji z graficznym interfejsem użytkownika. Stanowi ona podstawę środowisk programistycznych klasy RAD (na przykład Borland Developers Studio, Microsoft Visual Studio). Jest ona również często wykorzystywana podczas programowania układów scalonych, dysponujących systemem przerwań z możliwością wywołania podprogramu na wystąpienie zdarzania (przerwania). W ostatnich latach zyskuje coraz większą popularność podczas programowania aplikacji webowych.

Przyjmuje się, że wszystkie zdarzenia są wprowadzane do systemu przez mechanizm obsługi wektora przerwań (sprzętowo) lub pętlę komunikatów (programowo). Mechanizmy te uważa się za fundamenty systemu, niezależne od programisty. W systemie może występować mechanizm priorytetowania lub blokowania zdarzeń (przerwań).

Programowanie zdarzeniowe jest najczęściej zaliczane do metodyk typu imperatywnego.

Zalety:

  • ograniczenie kodu do opisu tylko obsługiwanych zdarzeń
  • łatwość opisania interakcji z otoczeniem
  • posługiwanie się inną metodologią podczas samego opisu funkcji obsługi zdarzeń

Wady:

  • przy programowej implementacji wykorzystanie ukrytej, lecz de facto istniejącej części programu, odpowiadającej za obsługę pętli komunikatów
  • potrzeba znajomości możliwych zdarzeń i sposobu dostarczenia ich parametrów
  • skomplikowanie budowy systemu, pozwalającego na zaprogramowanie oparte na zdarzeniach (potrzeba implementacji sposobu obsługi nadchodzących przerwań lub komunikatów, wyszczególnienie, zdefiniowanie i udokumentowanie zdarzeń)

Programowanie agentowe

Metodyka ta jest oparta na założeniu o potrzebie dekompozycji problemów i tworzeniu programów w taki sposób, aby wykonanie operacji autonomicznych powierzyć wyodrębnionym podprogramom, wątkom lub - najczęściej - osobnym procesom. Żaden z agentów nie jest w stanie wykonać innych, niż powierzone mu, części zadania. Zatem do pełnego zrealizowania działania systemu potrzebna jest współpraca niezależnych agentów.

Często nie występuje między nimi wzajemna komunikacja lub nadrzędne formy zarządzania. System taki zwany jest systemem wieloagentowym. Jeśli nie występuje komunikacja, zadaniem agentów jest najczęściej utrzymanie pewnego stanu lub podtrzymanie działania w nierozwijanym przez agenty systemie. W przeciwnym razie komunikacja pozwala na reagowanie całego systemu na zdarzenia lub stan otoczenia.

Najczęstszym przykładem, wykorzystywanym do przedstawienia tej metodologii, jest zaprogramowanie robota do sprzątania domu. Łatwiejszym może okazać się zbudowanie małego, specjalizowanego robota do odkurzania, osobnego robota do wynoszenia śmieci, osobnego do mycia okien, niż tworzenie jednej maszyny do wykonania tych wszystkich zadań. Zatem podstawowymi cechami agentów są określoność celu, a przez to inteligencji ograniczonej zależnie od realizowanego zadania), oraz położenia (agent działa w określonej części całego systemu, w określonym otoczeniu, w określonym czasie).

Programowanie zgodne z tą metodologią może być często realizowane z wykorzystaniem dowolnych innych paradygmatów podczas tworzenia poszczególnych agentów. Programowanie agentowe narzuca raczej strukturę całości systemu, niż poszczególnych agentów z osobna. Jest przykładem metodyki nadtypu rozproszonego.

Programowanie agentowe jest często stosowane w środowiskach rozproszonych, a także w aplikacjach sieciowych (n.p.: roboty wyszukiwarek sieciowych). Mimo, że do tworzenia systemów wieloagentowych można wykorzystać większość języków programowania ogólnego przeznaczenia, rozwinęły się środowiska dedykowane, wspierające programowanie agentowe w ramach określonych zakresów zastosowań. Często środowiska te bazują na określonym języku programowania (najczęściej wykorzystującym metodyki imperatywne). Do najpopularniejszych środowisk należą NetLogo, StarLogo oraz Swarn.

Programowanie agentowe jest najczęściej zaliczane do metodyk typu imperatywnego, gdyż - mimo całościowego zorientowania na cel, jak programowanie typu funkcyjnego - każdy z agentów ma określony sposób dysponowania zasobami.

Zalety:

  • możliwość dekompozycji kodu
  • łatwość wprowadzania poprawek w wykonaniu poszczególnych zadań
  • posługiwanie się inną metodologią tworzenia poszczególnych agentów

Wady:

  • złożoność procesu szukania błędów, wynikających z zależności lub interakcji agentów
  • wdrożenie procesu interakcji zbioru agentów pod konkretny system
  • współdzielenie danych może wymagać synchronizacji i nadrzędnego agenta

3 komentarzy

Odnośnie programowania funkcyjnego, to nie zawsze pętla musi być tam zastąpiona prze rekurencję, bardzo często można użyć funkcji wyższego rzędu, takich, jak map, fold, etc, tutaj jest link do Wikipedii:

http://pl.wikipedia.org/wiki/Funkcja_wy%C5%BCszego_rz%C4%99du

jako przykład można by podać taki kod w Haskellu do policzenia kwadratów liczb, które zawarte są w liście

*Main> map (2^) [3,4,66]
[8,16,73786976294838206464]

PS. warto by też dopisać do listy języków funkcyjnych Erlanga.

Wszystkie wyliczone w:
Metodyki programowania
będą opisane, jak będzie czas.

Zwracam uwagę na nagłówek:

"Strona w budowie
Ktoś pracuje nad tą stroną, jej zawartość może się wkrótce zmienić. Prosimy o cierpliwość!"

co z programowaniem aspektowym? wiem że to mało jeszcze popularne ale warto wspomnieć