Pytania do obrony inżynierki PDF
Document Details
Uploaded by AstoundingGrossular
Tags
Summary
This document contains questions related to engineering defense, covering topics such as electrical engineering, electronics, and programming. It includes questions about principles of electro-technical and electronic basics, electronic circuits, and measurement techniques.
Full Transcript
I. Podstawy elektrotechniki i elektroniki 1. Zasada superpozycji. Zasada superpozycji wykorzystuje zjawisko, że układ z wieloma źródłami (u nas jedno prądowe i jedno napięciowe) możemy rozłożyć na kilka układów z pojedynczym źródłem, a na koniec zsumować otrzymane wyniki. Usunięcie źródła...
I. Podstawy elektrotechniki i elektroniki 1. Zasada superpozycji. Zasada superpozycji wykorzystuje zjawisko, że układ z wieloma źródłami (u nas jedno prądowe i jedno napięciowe) możemy rozłożyć na kilka układów z pojedynczym źródłem, a na koniec zsumować otrzymane wyniki. Usunięcie źródła prądowego zastępujemy przerwą w obwodzie, usunięcie źródła napięciowego zastępujemy zwarciem w gałęzi. 2. Twierdzenie Thevenina. Twierdzenie Thevenina jest jedną z podstawowych zasad stosowanych w rozwiązywaniu obwodów elektrycznych zarówno prądu stałego jak/i zmiennego. Twierdzenie Thevenina pozwala na przedstawienie obwodu elektrycznego „widzianego” z jego dowolnych dwóch zacisków za pomocą napięcia źródłowego Thevenina Vth i rezystancji Thevenina Rth. Napięcie źródłowe Thevenina Vth i rezystancja Thevenina Rth połączone są szeregowo z zaciskami obwodu dla których były wyznaczane. Twierdzenie to pozwala na „zwinięcie” części obwodu lub innymi słowy potraktowaniu go jak przysłowiową czarną skrzynkę. / Twierdzenie Thevenina mówi, że z każdej aktywnej sieci można wydzielić gałąź lub podsieć spomiędzy wybranych zacisków a i b, a dwuzaciskowy obwód, który pozostał między tymi zaciskami, można zastąpić rzeczywistym źródłem napięcia stanowiącym szeregowe połączenie: - idealnego źródła napięcia równego napięciu między rozwartymi a i b, Uab, - oraz rezystancji równej oporowi między rozwartymi a i b, Rab, wyznaczonemu po wyłączeniu wszystkich niezależnych źródeł napięcia i prądu, czyli zastąpieniu ich odpowiednio zwarciami i przerwami. 3. Twierdzenie o mocy maksymalnej w obwodzie. Twierdzenie o przeniesieniu mocy maksymalnej stwierdza, że maksymalna moc jest przenoszona ze źródła na obciążenie, gdy rezystancja obciążenia jest równa rezystancji wewnętrznej źródła. Innymi słowy, gdy rezystancja obciążenia jest odpowiednio ustawiona, osiągana jest maksymalna wydajność przenoszenia mocy. / Jeżeli rezystancja obciążenia równa jest rezystancji Thevenina/Nortona obwodu zasilającego, to w obciążeniu wydzieli się maksymalna moc. Jeśli rezystancja obciążenia jest mniejsza lub większa od rezystancji Thevenina/Nortona źródła zasilającego, rozpraszana na niej moc będzie mniejsza od maksymalnej. 4. Zasada działania oraz zastosowania prostownika jednopołówkowego. Prostownik jednopołówkowy działa jak przełącznik, który dla prądów płynących w określonym kierunku jest zawsze otwarty, natomiast dla prądów płynących w kierunku przeciwnym jest zawsze zamknięty. Wartość skuteczna napięcia wyjściowego jest w tym przypadku znacznie mniejsza od wartości wejściowej. Używa się ich w ładowarkach akumulatorów i zasilaczach prądu stałego oraz w prostownikach napięcia przemiennego i inwerterach. Ze względu na wysoki prąd przewodzenia oraz charakterystyki napięciowe, mogą być użyte jako diody zabezpieczające oraz w tłumikach przepięć. 5. Zasada działania oraz podstawowe parametry wzmacniacza operacyjnego odwracającego. Wzmacniacz operacyjny odwracający to podstawowy układ wzmacniacza operacyjnego, który generuje wyjściowe napięcie, odwrotne do sygnału wejściowego. Zasada jego działania opiera się na ujemnym sprzężeniu zwrotnym, co oznacza, że różnica napięć między wejściem odwracającym (-) a wejściem nieodwracającym (+) jest utrzymywana blisko zera. Podstawowe parametry wzmacniacza operacyjnego - Wzmocnienie w pętli otwartej (ang. Open Loop Gain) – stosunek zmiany napięcia wyjściowego do zmiany napięcia różnicowego (występującego na wejściach). W karcie katalogowej zwykle podawana jest wartość dla napięcia stałego oraz wykres pokazujący wartość tego parametru w funkcji częstotliwości. Parametr o bardzo dużej wartości rzędu setek tysięcy. - Impedancja wejściowa (ang. Input impedance) – Impedancja wejściowa jest stosunkiem napięcia wejściowego do prądu wejściowego. Dla idealnego wzmacniacza przyjmuje się, że jest nieskończona. Rzeczywiste wzmacniacze operacyjne mają wejściowe prądy upływowe od kilku pikoamperów do kilku mikroamperów. - Impedancja wyjściowa (ang. Output impedancje) – Impedancja wyjściowa idealnego wzmacniacza operacyjnego wynosi zero. Zakłada się, że idealny wzmacniacz działa jako doskonałe wewnętrzne źródło napięcia bez wewnętrznej rezystancji. Rezystancja wewnętrzna jest połączona szeregowo z obciążeniem, zmniejszając w ten sposób napięcie wyjściowe dostępne dla obciążenia. Rzeczywiste wzmacniacze operacyjne mają impedancje wyjściowe najczęściej w zakresie 100-20kΩ (kiloomów). - Pasmo (ang. Bandwidth) – Idealny wzmacniacz operacyjny ma nieskończoną charakterystykę częstotliwościową i może wzmacniać dowolny sygnał częstotliwościowy od DC (0 Hz) do najwyższych częstotliwości AC, dlatego zakłada się, że ma nieskończoną szerokość pasma. W przypadku rzeczywistych wzmacniaczy operacyjnych przepustowość jest ograniczona przez iloczyn Wzmocnienie-Pasmo, który jest równy częstotliwości, przy której wzmocnienie wzmacniacza staje się równe 1. - Współczynnik tłumienia sygnału wspólnego (ang. Common Mode Rejectio Ratio CMRR) – Idealny wzmacniacz powinien wzmacniać tylko różnicę napięć między wejściami (odwracającym i nieodwracającym). Powinien tłumić wszystkie sygnały współbieżne, podawane jednocześnie na oba wejścia. Jeśli jednak na oba wejścia rzeczywistego wzmacniacza zostanie podany ten sam sygnał, to na wyjściu pojawi się niewielka jego część. Współczynnik CMMR wskazuje, jaka część sygnału wejściowego przedostanie się na wyjście, czyli jest to stosunek wzmocnienia różnicowego do współbieżnego. - Szybkość narastania zbocza (ang. Slew Rate SR) – lub inaczej szybkość zmian napięcia wyjściowego. Jest to parametr podawany w jednostkach V/μs (wolty/mikrosekundę) i określa jak szybko może zmienić się napięcie na wyjściu wzmacniacza. - Napięcie niezrównoważenia (ang. Offset Voltage) – Wyjście wzmacniacza będzie równe zero, gdy różnica napięć między wejściem odwracającym i nieodwracającym będzie równa zero, taka sama lub gdy oba wejścia są uziemione. Rzeczywiste wzmacniacze operacyjne mają pewną ilość wyjściowego napięcia niezrównoważenia. II. Układy elektroniczne i technika pomiarowa 1. Wyjaśnij na czym polega zjawisko skalowalności tranzystora MOS. Jak brzmią prawa Moore'a. Zmniejszenie wymiarów: Tranzystory MOS mogą być produkowane z coraz mniejszymi wymiarami, co prowadzi do mniejszych rozmiarów układów scalonych i zwiększonej gęstości integracji. Zwiększenie prędkości: Zmniejszenie wymiarów tranzystora MOS może prowadzić do zwiększenia prędkości działania, ponieważ krótsze trasy sygnału i mniejsza pojemność mogą skutkować szybszymi czasami przełączania. Zmniejszenie zużycia energii: Mniejsze tranzystory MOS wymagają niższych napięć zasilania i generują mniejsze straty mocy, co przekłada się na mniejsze zużycie energii. Zwiększenie niezawodności: Poprawa technologii produkcji może przynieść także korzyści związane z niezawodnością, takie jak zmniejszenie prawdopodobieństwa wystąpienia wad układu. Głównym prawem Moore'a jest stwierdzenie, że liczba tranzystorów na jednostce obszaru układu scalonego podwaja się co około dwa lata. Prawo Moore'a jest często używane do prognozowania tempa rozwoju technologicznego w przemyśle półprzewodnikowym. 2. Wyjaśnij dlaczego stosuje się pary komplementarne tranzystorów w technologii CMOS. Niskie zużycie energii: Pary komplementarne tranzystorów CMOS pracują na zasadzie komplementarnego przewodzenia. Oznacza to, że jeden typ tranzystora jest otwarty, podczas gdy drugi jest zamknięty. Dlatego prąd płynie tylko przez jeden tranzystor na raz, minimalizując straty mocy. W rezultacie układy CMOS charakteryzują się niskim zużyciem energii, co jest szczególnie ważne w dzisiejszych układach zasilanych bateryjnie i w aplikacjach przenośnych. Małe straty mocy w stanie statycznym: Ponieważ tranzystory CMOS zużywają prąd tylko podczas przełączania, a nie w stanie statycznym, straty mocy są minimalne, co pozwala na efektywne zarządzanie zużyciem energii. Wysoka odporność na zakłócenia elektromagnetyczne (EMI): Dzięki zastosowaniu par komplementarnych tranzystorów, sygnały są różnicowe, co pomaga w redukcji promieniowania elektromagnetycznego oraz wpływu zakłóceń elektromagnetycznych. Stabilność temperaturowa: Pary komplementarne tranzystorów składające się na technologię CMOS są zazwyczaj wykonane z tego samego materiału półprzewodnikowego, co sprawia, że mają zbliżone charakterystyki temperaturowe. To przyczynia się do stabilności działania układów CMOS w różnych warunkach temperaturowych. Szeroki zakres napięć zasilających: Technologia CMOS jest elastyczna jeśli chodzi o zakres napięć zasilających, co pozwala na projektowanie układów, które mogą działać zarówno przy niskich, jak i wysokich napięciach. 3. Wyjaśnij zasady działania pamięci półprzewodnikowych typu RAM. SRAM (Static RAM): Zasada przechowywania informacji: SRAM przechowuje informacje w formie bistabilnych układów flip-flop. Każda komórka pamięci SRAM składa się z czterech lub więcej tranzystorów, tworzących dwie zintegrowane bramy NAND lub NOR. Trwałość informacji: Informacje są przechowywane w SRAM, dopóki są zasilane. Nie wymagają odświeżania, co oznacza, że są trwałe, dopóki zasilanie jest podtrzymywane. Szybki dostęp: SRAM oferuje szybki dostęp do danych, ponieważ flip-flopy mogą utrzymywać stan bez konieczności ciągłego odświeżania. Skomplikowana struktura: Ze względu na złożoną strukturę, SRAM zajmuje więcej miejsca na chipie w porównaniu do DRAM. DRAM (Dynamic RAM): Zasada przechowywania informacji: W DRAM, informacje są przechowywane w formie ładunków elektrycznych na kondensatorach. Każda komórka pamięci DRAM składa się z pojedynczego tranzystora i kondensatora. Konieczność odświeżania: Kondensatory tracą ładunek z czasem z powodu naturalnych strat, więc informacje muszą być cyklicznie odświeżane (odtwarzane). Mniejsze miejsce na chipie: DRAM zajmuje mniej miejsca na chipie niż SRAM, co sprawia, że jest bardziej efektywne pod względem zajmowanego miejsca. Mniej złożona struktura: Struktura komórek pamięci DRAM jest prostsza niż w SRAM, co ułatwia produkcję dużych pojemności pamięci. Szybkość dostępu: W porównaniu do SRAM, DRAM ma zazwyczaj dłuższy czas dostępu, ponieważ odczyt danych wymaga cyklu odświeżania. Obie te technologie są szeroko stosowane w różnych zastosowaniach, a wybór między SRAM a DRAM zależy od wymagań dotyczących szybkości dostępu, wielkości, kosztów produkcji i innych czynników. W systemach komputerowych często stosuje się obie rodzaje pamięci RAM: SRAM dla pamięci cache, ze względu na szybkość dostępu, oraz DRAM dla głównej pamięci operacyjnej, ze względu na wydajność kosztową i większą pojemność. III. Podstawy programowania 1. Scharakteryzuj koncepcję programowania strukturalnego, ilustrując ją na przykładzie języka C. Programowanie strukturalne to paradygmat programistyczny, który nadaje struktury kodowi źródłowemu, podkreślając czytelność i zrozumiałość. Jest koncepcją, która zaleca rozwijanie oprogramowania poprzez podział na mniejsze, łatwe do zarządzania moduły. Bazuje na kilku podstawowych konstrukcjach, które są fundamentem tej metodologii. - Pierwszą z nich jest sekwencja, czyli wykonanie instrukcji krok po kroku, w ustalonej kolejności. Użycie procedur i funkcji umożliwia organizację kodu w porządkowanych jednostkach, które można wielokrotnie używać w programie. - Kolejną konstrukcją jest wybór (czyli instrukcje warunkowe if-else), który pozwala na wykonywanie różnych fragmentów kodu w zależności od spełnienia określonych warunków. - Trzecim elementem są pętle, czyli for oraz while, umożliwiające powtarzanie określonego bloku kodu dopóki nie zostanie spełniony pewien warunek. Te trzy konstrukcje pozwalają na tworzenie jasnych i logicznych struktur programistycznych, redukując potrzebę skomplikowanego skoku w kodzie (goto), co było charakterystyczne dla wcześniejszych technik programowania. 2. Omów pojęcia wyrażenia i instrukcji w programowaniu. Jakie są między nimi różnice? Wyrażenie w programowaniu to kombinacja literałów, zmiennych, operatorów i wywołań funkcji, które generują wartość po ocenie. Reprezentuje obliczenie i może być tak proste jak pojedyncza zmienna lub tak złożone jak równanie matematyczne. Instrukcja w programowaniu jest to najmniejszy samodzielny element imperatywnego języka programowania. Może być niskiego poziomu, czyli być napisana w asemblerze (np. mov ax, bx), która po przetłumaczeniu na kod maszynowy nadaje się do uruchomienia przez procesor. Albo wysokiego poziomu, czyli napisana w języku wysokiego poziomu (np. if (a==b) goto 10), która jest zazwyczaj tłumaczona na kilka instrukcji niskiego poziomu. Program jest tworzony jako zbiór różnych instrukcji. Instrukcja może zawierać wewnętrzne komponenty, np. wyrażenia. 3. Wyjaśnij, czym jest funkcja w programowaniu oraz z jakich części się składa. Jaką rolę pełnią poszczególne jej elementy? Jakie są sposoby przekazywania parametrów do funkcji? Funkcja (czasami nazywana podprogramem, rzadziej procedurą) to wydzielona część programu, która przetwarza argumenty i ewentualnie zwraca wartość, która następnie może być wykorzystana, jako argument w innych działaniach lub funkcjach. Pomaga zachować czytelność kodu i zmniejsza potrzebę powtarzania instrukcji (redundancji). Ogólny wzorzec definicji funkcji jest następujący: typ_wartości_zwracanej nazwa_funkcji(lista_parametrów) { … } Pierwszy wiersz w tym wzorcu jest nazywany prototypem lub nagłówkiem funkcji. Rozpoczyna się on typem wartości zwracanej przez funkcję (typem danych), po którym następuje nazwa funkcji, która podlega tym samym zasadom tworzenia, co inne identyfikatory w danym języku (np. nazwy zmiennych). Po nazwie, w nawiasach okrągłych umieszczana jest lista parametrów, które są specjalnymi zmiennymi umożliwiającymi funkcji wymianę danych z innymi częściami programu. Po liście parametrów znajduje się blok instrukcji, który stanowi ciało lub treść funkcji, czyli zasadniczą część decydującą o jej działaniu. Aby funkcja zwracała wynik należy w jej ciele użyć słowa kluczowego return. Za nim umieszcza się wyrażenie, którego wartość funkcja przekaże na zewnątrz. Jedyny wymóg, to zgodność typu wartości wyrażenia z typem wartości zwracanej przez funkcję umieszczonym w jej nagłówku. Słowo return oprócz zwracania wartości kończy działanie funkcji, a więc po jego wykonaniu żadne inne instrukcje nie są wykonywane. Metody przekazywania parametrów. ❖ Przekazywanie przez wartość (pass by value): Parametry są przekazywane do funkcji poprzez przekazanie kopii ich wartości. Zmiany dokonywane wewnątrz funkcji nie wpływają na oryginalne wartości zmiennych. Jest to najczęstsza metoda przekazywania parametrów. ❖ Przekazywanie przez referencję (pass by reference): Parametry są przekazywane do funkcji poprzez przekazanie referencji do oryginalnych zmiennych. Zmiany dokonywane wewnątrz funkcji wpływają na oryginalne wartości zmiennych. ❖ Przekazywanie przez wskaźnik (pass by pointer): Podobne do przekazywania przez referencję, ale używane są wskaźniki do zmiennych. Zmiany dokonywane wewnątrz funkcji wpływają na oryginalne wartości zmiennych. ❖ Przekazywanie przez wartość zwracaną (return by value): Funkcje zwracają wartość, która jest następnie przypisywana zmiennej poza funkcją. Zwracana wartość może być używana w wywołującym kodzie. 4. Jakie są cechy pamięci statycznej, stosu oraz sterty. Podaj przykłady, w jakich sytuacjach każdy typ pamięci jest używany. Pamięć RAM możemy podzielić na 3 zasadnicze obszary: - Stos (stack) – obszar, w którym przechowywane są wszystkie zmienne lokalne oraz odkładany jest kontekst przy wywoływaniu funkcji lub przerwania. Stos zwykle umieszcza się na końcu pamięci RAM i rośnie on w kierunku malejących adresów, czyli graficznie w dół. Stos jest kolejką typu LIFO (Last-In-First-Out). Ostatni element odłożony na stosie jest pierwszym elementem, który możemy z tego stosu zdjąć. Zasadniczo na stos odkładamy dane żyjące krótko, przechowywane w pamięci na potrzeby tych kilku milisekund, kiedy wywoływana jest konkretna funkcja, która dodatkowo woła jeszcze jedną bądź kilka innych funkcji. Nad położeniem wierzchołka stosu czuwa dedykowany rejestr sprzętowy (SFR) zwany wskaźnikiem stosu. - Sterta (heap) – jest to obszar, do którego trafiają wszystkie zmienne dynamicznie zaalokowane za pomocą polecenia malloc(). Należy pamiętać o zwalnianiu tej zaalokowanej pamięci za pomocą polecenia free(), żeby nie dopuścić do jej wycieków. Stertę od stosu oddziela pas (ziemi) pamięci niczyjej. Jest ona używana, kiedy chcemy, aby coś istniało przez jakiś czas, niezależnie od funkcji i zakresów. - Obszar danych statycznych – położony przy najniższych adresach RAM-u zawiera w sobie wszelkie dane globalne, przechowywane w naszym programie, np. wszystkie zmienne czy struktury globalne oraz zmienne statyczne. Czyli wszystkie te wartości, które mają przetrwać między wywołaniami funkcji. Wielkość obszaru danych statycznych jest ustalana na etapie kompilacji i stała przez cały czas działania programu. Obszar ten dzieli się dodatkowo na dwa podobszary:.bss i.data 5. Jak działa mechanizm rekurencji w programowaniu i kiedy warto go stosować? Rekurencja, to koncepcja programistyczna, w której funkcja wywołuje samą siebie. Jest to alternatywne podejście do iteracji, gdzie funkcja powtarza pewne kroki lub operacje poprzez wielokrotne wywoływanie samej siebie. Stosuje się ją gdy: - Problem ma rekurencyjną naturę – część rozwiązań danego zagadnienia jest stworzona typowo pod rekurencję, np. wieże Hanoi, ciąg Fibonacciego - Struktura danych jest rekurencyjna – przykładowo chodzi o takie struktury jak grafy lub drzewa, - Możliwy jest podział na podobne podproblemy – jeśli dany problem możesz łatwo podzielić na mniejsze podproblemy, które są praktycznie takie same, to rekurencja okazuje się dobrym rozwiązaniem. 6. Wyjaśnij pojęcia wskaźnika i referencji. Jakie możliwości oferują, z jakimi problemami należy się liczyć? Wskaźnik to zmienna, która przechowuje adres pamięci obiektu. Wskaźniki są szeroko używane zazwyczaj w trzech głównych celach: - aby przydzielić nowe obiekty na stercie, - przekazywać funkcje do innych funkcji, - iterować elementy w tablicach lub innych strukturach danych. Celem wskaźnika jest zaoszczędzenie miejsca w pamięci i osiągnięcie szybszego czasu wykonania. Zalety wskaźników w C - Wskaźniki są przydatne przy uzyskiwaniu dostępu do komórek pamięci. - Wskaźniki zapewniają skuteczny sposób uzyskiwania dostępu do elementów struktury tablicowej. - Wskaźniki służą do dynamicznej alokacji i dealokacji pamięci. - Wskaźniki służą do tworzenia złożonych struktur danych, takich jak listy powiązane, grafy, drzewa itp. Wady wskaźników w C - Wskaźniki są nieco skomplikowane do zrozumienia. - Wskaźniki mogą prowadzić do różnych błędów, takich jak błędy segmentacji, lub mogą uzyskać dostęp do komórki pamięci, która w ogóle nie jest potrzebna. - Jeśli do wskaźnika zostanie podana niepoprawna wartość, może to spowodować uszkodzenie pamięci. - Wskaźniki są również odpowiedzialne za wycieki pamięci. - Wskaźniki są stosunkowo wolniejsze niż zmienne. - Programistom bardzo trudno jest pracować ze wskaźnikami; dlatego też obowiązkiem programisty jest ostrożne manipulowanie wskaźnikiem. Referencję możemy traktować jako inną nazwę na już istniejący obiekt. To stały wskaźnik. Składnia referencji zabrania wykonywania operacji znanych dla wskaźników: referencji nie można ustawić na inny obiekt, nie jest dostępna arytmetyka referencji. Po kompilacji (w kodzie maszynowym) referencje i wskaźniki niczym się nie różnią. Korzystając z referencji świadomie rezygnujemy z pewnych możliwości oferowanych nam przez wskaźniki. W zamian dostajemy: - łatwiejszą notację - nie musimy używać operatora wyłuskania (*) do odwoływania się do obiektu - większe bezpieczeństwo - brak arytmetyki dla referencji znacznie utrudnia popełnienie błędów związanych z niepoprawnym odwołaniem do pamięci 7. Omów funkcję i zastosowanie typów tablicowych w programowaniu strukturalnym, a także przedstaw ich rodzaje. Funkcja typów tablicowych - Przechowywanie danych: Tablice umożliwiają przechowywanie wielu wartości w jednym obiekcie, co upraszcza zarządzanie danymi. - Dostęp za pomocą indeksów: Elementy tablicy można odczytywać i modyfikować za pomocą indeksów, co umożliwia szybki i łatwy dostęp do konkretnych danych. - Ułatwienie iteracji: Tablice wspierają iterację, np. za pomocą pętli, co pozwala na efektywne wykonywanie operacji na wielu elementach jednocześnie. - Organizacja danych: Tablice pomagają organizować dane w logiczny sposób, co zwiększa czytelność i modularność kodu. Zastosowanie typów tablicowych - Przechowywanie kolekcji danych: Tablice są używane do przechowywania list wartości, np. nazw użytkowników, wyników pomiarów czy wartości w wektorach matematycznych. - Algorytmy i sortowanie: Wiele algorytmów operuje na tablicach, np. sortowanie bąbelkowe czy wyszukiwanie binarne. - Operacje na danych numerycznych: Tablice są kluczowe w przetwarzaniu danych w analizie numerycznej, obliczeniach macierzowych czy grafice komputerowej. - Przechowywanie struktur bardziej złożonych: Tablice mogą służyć jako podstawowe elementy bardziej złożonych struktur danych, np. macierzy, list wielowymiarowych czy struktur drzewiastych. Rodzaje tablic 1. Tablice jednowymiarowe (wektory) Definicja: Tablice przechowujące wartości w jednej linii (jednym wymiarze). 2. Tablice wielowymiarowe Definicja: Tablice, które przechowują dane w wielu wymiarach. 3. Tablice dynamiczne Definicja: Tablice, których rozmiar można określić lub zmieniać w trakcie działania programu. 4. Tablice statyczne Definicja: Tablice o stałym rozmiarze, określonym w momencie kompilacji. 5. Tablice asocjacyjne Definicja: Tablice, w których dane są przechowywane w postaci par klucz-wartość. 8. Wyjaśnij, w jaki sposób struktury i unie pozwalają na efektywne zarządzanie danymi w języku C. Jakie są typowe scenariusze ich zastosowania? Struktury (struct) Struktury w języku C umożliwiają grupowanie różnych typów danych w jednym logicznym obiekcie. Są to złożone typy danych, które pozwalają na lepszą organizację i czytelność kodu. Cechy struktur: - Kombinacja różnych typów: Struktury mogą przechowywać elementy o różnych typach, np. liczby całkowite, zmiennoprzecinkowe i ciągi znaków. - Hierarchia i organizacja: Pozwalają na stworzenie logicznej struktury danych, co ułatwia ich obsługę i zarządzanie. - Dostęp przez pola: Dane w strukturze są dostępne przez zdefiniowane pola, co upraszcza manipulację nimi. Zalety struktur: Czytelność: Łatwiej zrozumieć kod, gdy dane są pogrupowane logicznie. Reużywalność: Można definiować struktury jako abstrakcyjne typy danych i używać ich w różnych częściach programu. Rozszerzalność: Dodanie nowych pól do struktury jest proste i pozwala na rozwój aplikacji bez zmiany jej podstawowych założeń. Unie (union) Unie są podobne do struktur, ale różnią się zasadniczo sposobem przechowywania danych. Wszystkie pola unii dzielą ten sam obszar pamięci, co czyni je bardziej pamięciooszczędnymi, ale mniej elastycznymi niż struktury. Cechy unii: 1. Wspólna pamięć: Wszystkie pola unii zajmują to samo miejsce w pamięci, co pozwala na przechowywanie tylko jednej wartości w danym momencie. 2. Oszczędność pamięci: Unie są używane tam, gdzie różne pola nie będą potrzebne jednocześnie. 3. Elastyczność w interpretacji danych: Unie są przydatne w sytuacjach, gdzie ten sam fragment pamięci musi być odczytywany w różny sposób. Typowe scenariusze zastosowania Struktury 1. Reprezentacja obiektów i danych rzeczywistych: ○ Przykład: dane o pracownikach, produktach, klientach. 2. Przekazywanie danych do funkcji: ○ Ułatwiają przekazywanie zbioru danych jako jednego argumentu. 3. Tworzenie abstrakcyjnych typów danych: ○ Przykład: implementacja list, stosów czy kolejek. Unie 1. Oszczędność pamięci: ○ Przydatne w systemach wbudowanych, gdzie pamięć jest ograniczona. 2. Reprezentacja danych o zmiennym formacie: ○ Przykład: struktury nagłówków protokołów sieciowych, gdzie różne pola zależą od typu wiadomości. 3. Elastyczne odczytywanie danych binarnych: ○ Przykład: odczyt tej samej pamięci jako liczby całkowitej lub ciągu znaków. IV. Systemy operacyjne 1. Omów diagram stanów procesu i przejścia pomiędzy stanami. Nowy - proces został utworzony Gotowy - proces czeka na przydział procesora ○ Proces mógłby się wykonać, ale nie wykonuje się, ponieważ w tej chwili wykonuje się jakiś inny proces Aktywny - wykonywane są instrukcje procesu ○ W systemie z jednym procesorem w danej chwili jeden proces może być aktywny Oczekujący (uśpiony) - proces czeka na zdarzenie (np. zakończenie operacji we-wy). ○ Proces w stanie uśpionym nie otrzyma procesora Zakończony - proces zakończył działanie. Przejścia pomiędzy stanami procesu 1 (Nowy => Gotowy). Nowo utworzony proces przechodzi do kolejki procesów gotowych. ○ W systemach wsadowych zarządza tym Planista długoterminowy 2 (Gotowy => Aktywny). Proces otrzymuje przydział procesora. 3 (Aktywny => Gotowy). Procesowi został odebrany procesor (i przekazany innemu procesowi). ○ Przejściami 2 oraz 3 zarządza planista krótkoterminowy. 4 (Aktywny => Oczekujący). Proces przechodzi w stan oczekiwania na zajście zdarzenia (np. na zakończenie transmisji wejścia - wyjścia) 5 (Oczekujący => Gotowy). Zdarzenie na które czekał proces nastąpiło (np. przerwanie we/wy) ○ Przejścia 4 oraz 5 są wykonywane przy przeprowadzeniu synchronicznej operacji wejścia-wyjścia (ale nie tylko). 6 (Aktywny => Zakończony). Proces zakończył pracę (np. funkcja exit w Uniksach, błąd ochrony) 7 (Gotowy => Zakończony oraz Oczekujący => Zakończony). Proces został zakończony przez inny proces (np. funkcja kill w systemie Unix). 2. Omów zasadę działania monitora i zmiennych warunkowych. Mechanizm synchronizacji w programowaniu wielowątkowym, który pozwala na kontrolowanie dostępu do współdzielonych zasobów w sposób bezpieczny pod względem równoległego wykonywania wielu wątków. Udostępnienie procesom operacji pozwalającej procesowi wejść w stan uśpienia (zablokowania) – wait oraz operacji signal pozwalającej na uśpienie obudzonego procesu. Zmienne warunkowe Problem: proces postanawia zaczekać wewnątrz monitora aż zajdzie zdarzenie sygnalizowane przez inny proces. ○ Jeżeli proces po prostu zacznie czekać, to nastąpi blokada, bo żaden inny proces nie będzie mógł wejść do monitora i zasygnalizować zdarzenia. Zmienne warunkowe (typu condition). Proces będący wewnątrz monitora, może wykonać na niej dwie operacje. ○ Niech deklaracja ma postać: Condition C; ○ C.wait() - Zawiesza wykonanie procesu i jednocześnie zwalnia monitor pozwalając innym procesom wejść do monitora. ○ C.signal() - Jeżeli nie ma procesów zawieszonych przez operację wait nic się nie dzieje. W przeciwnym wypadku dokładnie jeden proces zawieszony przez operację wait zostaje wznowiony (od następnej instrukcji wait). ○ Możliwa jest trzecia operacje C.signalAll() wznawiająca wszystkie zawieszone procesy. 3. Omów algorytmy szeregowania rotacyjny, FCFS, SJF i SJF z wywłaszczaniem. Algorytm First Come First Served (FCFS) - proces, który pierwszy został dodany do kolejki procesów gotowych, jest wykonywany jako pierwszy (pierwszy nadszedł –pierwszy obsłużył) - algorytm implementuje się za pomocą kolejki FIFO (procesy otrzymują procesor na zasadzie FIFO) - algorytm niewywłaszczający - zalety: sprawiedliwy dostęp każdego procesu do procesora łatwy do zrozumienia łatwy do zaimplementowania - wady: proces o dużym zapotrzebowaniu na procesor opóźnia wszystkie procesy czekające za nim w kolejce (nie zapewnia szybkiej obsługi) może powstać efekt konwoju (niekorzystny efekt blokowania dostępu przez proces do procesora) Algorytm Shorter Job First (SJF) - algorytm ten wiąże z każdym procesem długość jego najbliższej z przyszłych faz procesora. Gdy procesor staje się dostępny, wówczas zostaje przydzielony procesorowi proces o najkrótszej następnej fazie procesora - SJF jest przykładem planowania z wykorzystaniem priorytetów. – W tym przypadku priorytetem jest długość fazy procesora. - dwie wersje: SJF bez wywłaszczania. SJF z wywłaszczaniem - zalety: SJF jest optymalny minimalizuje średni czas oczekiwania dla danego zbioru procesów - wady: poważną trudność sprawia określenie długości następnej fazy procesora W przypadku planowania niewywłaszczającego, gdy cykl procesora zostanie przydzielony procesowi, proces wstrzymuje go do momentu osiągnięcia stanu oczekiwania lub zakończenia. W planowaniu z wywłaszczaniem SJF zadania są umieszczane w kolejce gotowych w miarę ich pojawiania się. Rozpoczyna się proces z najkrótszym czasem trwania serii. Jeśli nadejdzie proces z jeszcze krótszym czasem impulsu, bieżący proces zostanie usunięty lub wywłaszczony z wykonania, a krótszemu zadaniu przydzielany jest cykl procesora. Planowanie rotacyjne - Algorytm wykorzystuje wywłaszczanie przy pomocy przerwania zegara. - Proces otrzymuje kwant czasu procesora. - Jeżeli po upływie kwantu czasu proces nie zakończy cyklu procesora. Proces jest wywłaszczany i dodawany na koniec kolejki procesów gotowych. Kolejny proces z kolejki procesów gotowych otrzymuje kwant czasu. - Algorytm stosowany powszechnie w systemach z podziałem czasu. - Problem: Jak dobierać długość kwantu czasu? – Typowa wartość: 10ms. Bardzo duży kwant czasu => algorytm degeneruje się do FCFS, duży średni czas oczekiwania Bardzo mały kwant czasu => straty wydajności związane z przełączeniam kontekstu. V. Algorytmy i struktury danych 1. Wyjaśnij pojęcia: złożoność czasowa algorytmu (pesymistyczna i średnia). Określ złożoność czasową wybranego algorytmu sortowania. Złożoność czasowa algorytmu to miara, która opisuje, jak zmienia się czas wykonania algorytmu w stosunku do rozmiaru danych wejściowych. Jest to ważne pojęcie w analizie algorytmicznej, ponieważ pozwala ocenić, jak algorytm skaluje się w obliczu rosnącego rozmiaru problemu. Określa, ile głównych operacji musi wykonać algorytm, aby rozwiązać problem dla n elementów będących danymi wejściowymi. Elementami tymi mogą być liczby, znaki itd. Główną operacją może być porównywanie elementów i ich przestawienie (np. w algorytmach sortujących), dodawanie, mnożenie itp. Przykładowe algorytmy o złożoności obliczeniowej O(log n) - Wyszukiwanie binarne Przykładowe algorytmy o liniowo logarytmicznej złożoności obliczeniowej O(n log n) - Sortowanie przez scalanie, 2 Przykładowe algorytmy o złożoności obliczeniowej O(𝑛 ) - Sortowanie bąbelkowe. - Sortowanie przez wstawianie. 2. Wyjaśnij na przykładach różnice pomiędzy techniką zachłanną projektowania algorytmów a programowaniem dynamicznym. Technika zachłanna i programowanie dynamiczne to dwa różne podejścia do rozwiązywania problemów algorytmicznych, które często stosuje się w różnych sytuacjach. ❖ Technika Zachłanna Decyzje lokalne: Algorytm zachłanny podejmuje decyzje w każdym kroku, wybierając najlepszą opcję w danym momencie, bez analizy przyszłości. Brak cofania: Po podjęciu decyzji, algorytm nie zmienia już swojego wyboru. Optymalne lokalnie: Algorytm dąży do znalezienia lokalnie optymalnego rozwiązania w każdym kroku, ale nie gwarantuje, że rozwiązanie globalnie będzie optymalne. Przykład (Algorytm wybierania monet): Rozważmy problem wybierania najmniejszej ilości monet do wydania danej kwoty pieniężnej. Algorytm zachłanny będzie wybierał największą dostępną monetę w każdym kroku, aż do momentu osiągnięcia żądanej kwoty. Na przykład, aby wydać 30 centów przy monetach {1, 5, 10, 25}, algorytm zachłanny wybierze najpierw monetę 25, potem 5. ❖ Programowanie Dynamiczne: Zachowuje informacje: Algorytm programowania dynamicznego rozwiązuje problem poprzez rozwiązanie podproblemów i przechowywanie wyników w tablicy lub pamięci, aby uniknąć wielokrotnego obliczania tych samych podproblemów. Cofanie się: Algorytm programowania dynamicznego może wykonywać cofanie, jeśli okaże się, że aktualnie wybrane rozwiązanie nie prowadzi do optymalnego rozwiązania problemu globalnego. Przykład (Problem plecakowy): Rozważmy klasyczny problem plecakowy, w którym mamy plecak o ograniczonej pojemności i zbiór przedmiotów, z których każdy ma wartość i wagę. Celem jest wybranie takich przedmiotów, aby suma ich wartości była maksymalna, a suma ich wag nie przekraczała pojemności plecaka. Algorytm programowania dynamicznego rozwiązuje ten problem, wykorzystując tablicę, w której przechowuje się optymalne rozwiązania dla różnych pojemności plecaka i różnych podzbiorów przedmiotów. 3. Co to znaczy, że problem komputerowy jest trudno rozwiązalny? Podaj przykłady problemów trudnych obliczeniowo. Kiedy mówimy, że problem komputerowy jest trudno rozwiązalny, odnosimy się do złożoności obliczeniowej tego problemu. Problemy trudne obliczeniowo są te, dla których nie istnieje znane efektywne rozwiązanie w ogólnym przypadku. ❖ Problem plecakowy (Knapsack Problem): Wersja decyzyjna tego problemu jest NP-trudna, co oznacza, że znalezienie rozwiązania jest trudne, ale sprawdzenie, czy dane rozwiązanie jest poprawne, jest łatwe. ❖ Problem handlowego podróżnika (Traveling Salesman Problem): Polega na znalezieniu najkrótszej trasy łączącej wszystkie miasta dokładnie raz. Jest to problem NP-trudny. NP-trudny Problem TSP (traveling salesman problem) polega na znalezieniu najkrótszej trasy, która odwiedza każde miasto dokładnie raz i wraca do miasta początkowego. W tym przypadku istnieje wiele możliwych tras, ale znalezienie najkrótszej trasy wymaga przetestowania wszystkich możliwości, co prowadzi do złożoności obliczeniowej, która rośnie wykładniczo w stosunku do liczby miast. To właśnie czyni TSP problemem trudnym obliczeniowo i oznacza, że nie ma znanych efektywnych algorytmów rozwiązujących go w czasie wielomianowym dla wszystkich przypadków. VI. Bazy danych 1. Podaj definicję i znaczenie kluczy w relacyjnych bazach danych. W relacyjnych bazach danych, klucze odgrywają kluczową rolę w identyfikacji, organizacji i zapewnianiu integralności danych. ❖ Klucz Główny (Primary Key): Definicja: Klucz główny to unikalny identyfikator dla każdego rekordu w tabeli. Wartości w kolumnie klucza głównego są unikalne i nie mogą przyjmować wartości NULL. Znaczenie: Unikalność: Zapewnia, że każdy rekord w tabeli jest jednoznacznie identyfikowany przez wartość klucza głównego. Indeksowanie: Automatycznie tworzy indeks Integralność danych: Chroni przed duplikatami i zapewnia spójność danych w bazie. ❖ 2. Klucz Obcy (Foreign Key): Definicja: Klucz obcy to kolumna lub zestaw kolumn w jednej tabeli, który odwołuje się do klucza głównego w innej tabeli. Klucz obcy tworzy relację między tabelami. Znaczenie: Relacje międzytabelowe: Określa powiązania między rekordami w różnych tabelach. Integralność referencyjna: Zapewnia, że wartości w kolumnie klucza obcego muszą istnieć w kolumnie klucza głównego w innej tabeli. Akcje na korzyść referencyjnej integralności: Definiuje akcje, które mają być wykonane, gdy odwołanie do klucza obcego zostanie naruszone, na przykład kasowanie kaskadowe lub ustawianie wartości NULL. 2. Podaj typy zapytań SQL. ❖ SELECT - pobieranie danych z tabeli ❖ INSERT - dodawanie danych do tabeli ❖ DELETE - usuwanie danych z tabeli ❖ UPDATE - aktualizowanie danych w tabeli ❖ CREATE - tworzenie tabeli ❖ DROP - usunięcie tabeli ❖ ALTER - zmiana struktury tabeli 3. Na czym polega proces normalizacji relacyjnej bazy danych? Proces normalizacji relacyjnej bazy danych polega na ustrukturyzowaniu jej w sposób, który nie pozwala jej na posiadanie redundancyjnych informacji. Znormalizowane tabele są łatwiejsze w zrozumieniu i ich rozszerzaniu a także są chronione przed anomaliami dodawania, edytowania i usuwania. Pierwsza postać normalna 1. Wykorzystanie kolejności wierszy do przekazywania informacji jest niedozwolone. 2. Mieszanie typów danych w tej samej kolumnie jest zabronione. 3. Musi posiadać klucz główny. 4. Powtarzające się grupy elementów danych w jednym wierszu są niedozwolone. Druga postać normalna 1. Każdy atrybut w tabeli nie będący kluczem musi być zależny od całego klucza głównego. (niektóre klucze główne składają się z więcej niż jednego atrybutu, wartości muszą być zależne od wszystkich atrybutów klucza głównego) Trzecia postać normalna 1. Każdy atrybut w tabeli nie będący kluczem musi być zależny od klucza, całego klucza i niczego innego tylko od klucza. (Mamy gracza, który posiada poziom, od poziomu zależy jego stopień zaawansowania -> nie można zrobić tabeli składającej się z tych 3 atrybutów łącznie, ponieważ stopień zaawansowania zależy nie tylko od klucza głównego (2PN) ale też od poziomu postaci) 4. Omów możliwości organizacji pliku rekordów. Plik rekordów może być zorganizowany na różne sposoby, w tym jako sekwencyjny, indeksowany lub jako baza danych. W organizacji sekwencyjnej rekordy są przechowywane kolejno, co ułatwia szybkie odczytywanie kolejnych rekordów, podczas gdy organizacja indeksowana umożliwia szybkie wyszukiwanie rekordów za pomocą indeksów. 5. Opisz budowę indeksu w postaci B+ drzewa. B+ drzewo to struktura danych wykorzystywana w bazach danych do organizowania i przyspieszania dostępu do danych poprzez indeksowanie. Jest to specjalna odmiana drzewa B, zoptymalizowana pod kątem operacji na dysku. Budowa B+ Drzewa: ❖ Korzeń Korzeń drzewa zawiera od jednego do wielu kluczy. Jest jednym z elementów drzewa, który może być modyfikowany. ❖ Węzły wewnętrzne Węzły wewnętrzne zawierają klucze i wskaźniki na potomne węzły lub liście. Klucze w węzłach są używane do nawigacji po drzewie i decydowania, którą gałąź należy odwiedzić. ❖ Liście Liście zawierają pary (klucz, wskaźnik do rekordu). Klucze w liściach są posortowane rosnąco. Liście są połączone ze sobą w formie listy podwójnie wiązanej, co ułatwia przeglądanie w kolejności rosnącej i malejącej. ❖ Wysokość drzewa Wysokość drzewa jest równa liczbie poziomów w drzewie, od korzenia do liści. W B+ drzewie zazwyczaj wysokość jest mała, co przyspiesza operacje wyszukiwania. ❖ Wskaźniki i Adresy Węzły wewnętrzne zawierają wskaźniki lub adresy węzłów potomnych. Wskaźniki w liściach wskazują na konkretne rekordy w bazie danych. ❖ Właściwość równoważenia Drzewo B+ utrzymuje równowagę, co oznacza, że każda gałąź od korzenia do liści ma tę samą długość. Równowaga pozwala na efektywne operacje na drzewie bez zbędnego przeszukiwania gałęzi o dużej głębokości. 6. Co to są transakcje w bazach danych? Omów podstawowe właściwości transakcji (ACID). Transakcje to sekwencje operacji bazodanowych, które są wykonywane jako jedna, niepodzielna jednostka. Gwarantują one, że baza danych przechodzi z jednego poprawnego stanu w inny poprawny stan. Transakcje muszą spełniać pewne właściwości, znane jako właściwości ACID. ❖ Atomicity (Atomowość): Definicja: Transakcja jest atomowa; to znaczy, albo wszystkie jej operacje zostaną wykonane, albo żadna z nich. Znaczenie: Jeśli którakolwiek z operacji w transakcji nie powiedzie się, to cała transakcja zostaje wycofana (ang. rollback), a baza danych powraca do poprzedniego stanu. ❖ Consistency (Spójność): Definicja: Transakcja przekształca bazę danych z jednego poprawnego stanu w inny poprawny stan. Znaczenie: Wszystkie reguły integralności danych muszą zostać zachowane po zakończeniu transakcji. ❖ Isolation (Izolacja): Definicja: Każda transakcja działa izolowana od innych transakcji, co oznacza, że efekty innych transakcji są niewidoczne dla bieżącej transakcji do momentu zatwierdzenia. Znaczenie: Chroni przed interferencją i zapewnia, że jedna transakcja nie wpływa na wyniki innych transakcji w trakcie ich wykonania. ❖ Durability (Trwałość): Definicja: Po zatwierdzeniu transakcji, jej efekty są trwałe i przetrwają wszelkie awarie systemu. Znaczenie: Zapewnia, że dane, które zostały zapisane w trakcie transakcji, nie zostaną utracone w przypadku awarii systemu. VII. Programowanie obiektowe 1. Czym są klasa i obiekt w programowaniu obiektowym? Omów ich składowe. Klasa ❖ Klasa to szablon, który definiuje strukturę i zachowanie obiektów. Jest to opis, który zawiera definicje pól (atrybutów) i metod (funkcji), które będą dostępne dla obiektów stworzonych na podstawie tej klasy. ❖ Definicja klasy w języku PHP ma postać: class Osoba { //składowe klasy } Po słowie kluczowym class podajemy nazwę klasy, zaś pomiędzy nawiasami klamrowymi — składowe. Składowymi klasy są: stałe, czyli np. const TYPE = "pies"; właściwości (nazywane także polami lub zmiennymi klasy), np. string imie = “Aga” oraz metody (inaczej funkcje), np. int sumuj(). Obiekt ❖ Obiekt to konkretna instancja klasy. Jest to realizacja koncepcji zdefiniowanej przez klasę. Każdy obiekt ma swoje unikalne atrybuty i może wywoływać metody zdefiniowane w klasie. 2. Na czym polega koncepcja abstrakcji w programowaniu obiektowym i jakie mechanizmy języków programowania ją wspierają? Abstrakcja polega na ukrywaniu wszelkich pól i metod tak, aby jak najmniejsza ich ilość była widoczna dla posiadających instancje tej klasy. Znamy funkcje danej klasy, parametry jakie przyjmuje i typ jaki zwraca, ale w ogóle nie obchodzi nas to, co dzieje się wewnątrz metody. Dzięki abstrakcji możemy zachować przejrzystość kodu, jednocześnie umożliwiając rozbudowę klasy o dodatkowe elementy, bez konieczności zmian wielu innych właściwości klasy. W programowaniu możemy zastosować abstrakcję poprzez klasy abstrakcyjne oraz interfejsy. 3. Czym jest dziedziczenie w programowaniu obiektowym i kiedy warto je stosować? Dziedziczenie, to mechanizm współdzielenia funkcjonalności między klasami. Klasa może dziedziczyć po innej klasie, co oznacza, że oprócz deklaracji swoich własnych atrybutów oraz zachowań, uzyskuje także te pochodzące z klasy, z której dziedziczy. Klasa dziedzicząca jest nazywana klasą pochodną lub potomną, zaś klasa, z której następuje dziedziczenie — klasą bazową. Z jednej klasy bazowej można uzyskać dowolną liczbę klas pochodnych. Klasy pochodne posiadają obok swoich własnych metod i deklaracji pól, również kompletny interfejs klasy bazowej. Klasy pochodne mogą dziedziczyć tylko z jednej klasy bazowej. Dziedziczenie jest dobrym wyborem, gdy: - Hierarchia dziedziczenia reprezentuje relację typu jest-coś, a nie relację typu posiada-coś. - Możesz ponownie wykorzystać kod z klas bazowych. - Musisz zastosować tę samą klasę i metody do różnych typów danych. - Chcesz dokonać globalnych zmian w klasach pochodnych poprzez zmianę klasy bazowej. 4. Czym jest polimorfizm i jak realizuje się go w językach obiektowych? Polimorfizm jest jednym z fundamentów programowania obiektowego, pozwalającym obiektom różnych klas na bycie traktowanymi jako instancje tej samej klasy bazowej. Umożliwia to wykonanie tych samych działań na różnych typach obiektów, które implementują te same interfejsy lub dziedziczą te same klasy abstrakcyjne, ale zachowują się w sposób specyficzny dla swojego typu. W Javie, dziedziczenie i interfejsy umożliwiają jego szerokie wykorzystanie, umożliwiając tworzenie bardziej elastycznych i łatwych do testowania aplikacji. W Pythonie, dzięki typowaniu dynamicznemu, polimorfizm jest wręcz naturalnym elementem języka. Natomiast w językach takich jak TypeScript czy C#, mimo że są one silnie typowane, istnieje możliwość skorzystania z tzw. polimorfizmu parametrycznego. 5. Na czym polega hermetyzacja (enkapsulacja) i jakie korzyści wynikają z jej stosowania? Hermetyzacja jest jednym z filarów programowania obiektowego. Polega ona na tym, by ukryć pewne pola lub metody z klas – aby nie były one widoczne dla użytkowników czy innych programistów. Robimy tak, ponieważ im więcej udostępniamy na zewnątrz, tym bardziej może to być niebezpieczne. Dzięki hermetyzacji zapobiegamy niekontrolowanemu działaniu programu, a także zachowujemy przejrzystą strukturę obiektów w projekcie. 6. Czym jest kompozycja w programowaniu obiektowym i jakie jest jej zastosowanie? Jest to relacja "całość – część" ( B "zawiera" A). Np. obiekty typu Pojazd zawierają obiekty typu Rozmiar, Koła, Silnik itd.. Kompozycję uzyskujemy poprzez definiowanie w nowej klasie pól, które są obiektami istniejących klas. Poprzez zastosowanie kompozycji zyskujemy elastyczność. W razie potrzeby możemy dynamicznie w czasie wykonywania aplikacji zmienić implementację jakiej używamy. Kolejnym plusem jest rozbicie klas na mniejsze, co pozwala nam na dostarczanie rozwiązań zgodnych z zasadami programowania obiektowego SOLID. Technika kompozycji w programowaniu obiektowym polega na tworzeniu nowych klas poprzez zawieranie (składanie) obiektów innych klas jako swoich składowych. Innymi słowy, klasa używa instancji innych klas jako swoich pól, co pozwala na tworzenie bardziej złożonych struktur poprzez kombinowanie funkcjonalności istniejących klas. Zalety: ❖ Hermetyzacja: Kompozycja umożliwia tworzenie interfejsu do zarządzania bardziej złożonymi obiektami, ukrywając ich wewnętrzne szczegóły implementacyjne. ❖ Modularność: Programy mogą być łatwiej podzielone na mniejsze, bardziej zrozumiałe i łatwiejsze do utrzymania części. ❖ Ponowne Wykorzystanie Kodu 7. Na czym polega mechanizm wyjątków w programowaniu obiektowym i jaka jest jego rola? Mechanizm wyjątków w programowaniu obiektowym jest techniką używaną do obsługi i sygnalizowania wyjątkowych sytuacji, które mogą wystąpić podczas działania programu. Wyjątki pozwalają na przerywanie standardowego przepływu programu w sytuacjach, w których zachodzi błąd lub nieoczekiwana sytuacja i umożliwiają programowi reagowanie na te sytuacje w odpowiedni sposób. Obsługiwanie wyjątków: ❖ Rzucanie Wyjątków (Throwing Exceptions): Wyjątek może być rzucony w kodzie za pomocą instrukcji throw. ❖ Przechwytywanie Wyjątków (Catching Exceptions): Wyjątek może być przechwycony w bloku try-catch. ❖ Przekazywanie Wyjątków (Propagating Exceptions): Wyjątki mogą być przekazywane przez kilka warstw kodu, gdzie mogą być przechwytywane na różnych poziomach hierarchii. 8. Jak wygląda zarządzanie pamięcią w kontekście czasu życia obiektów w programowaniu obiektowym? 1. Fazy życia obiektu Każdy obiekt w OOP przechodzi przez trzy podstawowe etapy: Tworzenie (inicjalizacja): ○ Obiekt jest tworzony w wyniku wywołania konstruktora. ○ Pamięć dla obiektu jest alokowana (zwykle na stosie lub stercie). ○ Inicjalizowane są zmienne członkowskie obiektu. Życie (używanie): ○ Obiekt wykonuje swoje zadania – metody obiektu są wywoływane, dane są przetwarzane. Zniszczenie: ○ Obiekt jest usuwany, co wiąże się z wywołaniem destruktora (jeśli istnieje). ○ Pamięć jest zwalniana (ręcznie lub automatycznie). 2. Zarządzanie pamięcią: ręczne vs automatyczne Ręczne zarządzanie pamięcią W językach takich jak C++: Programista jest odpowiedzialny za jawne alokowanie pamięci (new) i jej zwalnianie (delete). Niewłaściwe zarządzanie pamięcią może prowadzić do: ○ Wycieku pamięci (memory leak): jeśli obiekt nie zostanie usunięty. ○ Uszkodzenia pamięci: np. jeśli pamięć zostanie zwolniona wielokrotnie lub używana po zwolnieniu. Automatyczne zarządzanie pamięcią W językach takich jak Java, Python czy C#: Zarządzanie pamięcią jest realizowane przez mechanizm Garbage Collector (GC). Programista nie musi jawnie zwalniać pamięci; system automatycznie usuwa obiekty, które są już niedostępne (brak do nich referencji). 3. Alokacja pamięci: stos vs sterta Stos (stack): ○ Obiekty o krótkim czasie życia (lokalne zmienne funkcji) są alokowane na stosie. ○ Pamięć jest automatycznie zwalniana po wyjściu z zakresu (scope). ○ Szybka alokacja i dealokacja, ale ograniczona przestrzeń. Sterta (heap): ○ Obiekty o dłuższym czasie życia są alokowane na stercie. ○ Programista lub garbage collector zarządza pamięcią na stercie. ○ Większa elastyczność, ale wolniejsza alokacja i dealokacja. 9. Czym są typy generyczne w programowaniu obiektowym i jakie są korzyści ich stosowania? W uproszczeniu można powiedzieć, że typy generyczne są “szablonami”. Pozwalają na opóźnienie w dostarczeniu specyfikacji typu danych w elementach takich jak klasy czy metody do momentu użycia ich w trakcie wykonywania programu. Innymi słowy, typy generyczne pozwalają na napisanie klasy lub metody, która może działać z każdym typem danych. Używając typów generycznych można użyć zastępczego parametru określającego typ danych. Gdy kompilator napotka konstruktora klasy czy wywołanie metody generuje kod do obsługi konkretnego typu danych. Korzystanie z kolekcji generycznych i delegatów ma wiele zalet: - Bezpieczeństwo typu. Generyki przenoszą ciężar bezpieczeństwa typu z użytkownika na kompilator. Nie ma potrzeby pisania kodu w celu przetestowania poprawnego typu danych, ponieważ jest on wymuszany w czasie kompilacji. Potrzeba rzutowania typu i możliwość błędów w czasie wykonywania są ograniczone. - Mniej kodu i kod jest łatwiejszy do ponownego wykorzystania. Nie ma potrzeby dziedziczenia z typu bazowego i nadpisywania członków. - Lepsza wydajność. Typy kolekcji generycznych generalnie lepiej sprawdzają się w przechowywaniu i manipulowaniu typami wartości, ponieważ nie ma potrzeby pakowania typów wartości. - Usprawniają dynamicznie generowany kod. Gdy używasz generyków z dynamicznie generowanym kodem, nie musisz generować typu. Zwiększa to liczbę scenariuszy, w których możesz używać lekkich metod dynamicznych zamiast generować całe zestawy. VIII. Sieci komputerowe 1. Omów mechanizmy adresacji w sieciach oraz zależności pomiędzy poszczególnymi rodzajami adresów Adres IP: Unikalne identyfikatory przypisane urządzeniom w sieci. Wyróżniamy adresy IPv4 (32-bitowe) i IPv6 (128-bitowe). Adresy IPv4 zapisujemy formacie X.X.X.X:maska, natomiast IPv6 w formacie X:X:X:X:X:X:X:X/prefix (jeżeli występują segmenty składające się z samych zer możemy je pominąć zapisując :: np. 1050:0000:0000:0000:0005:0600:300c:326b => 1050:0:0:0:5:600:300c:326b). Maska podsieci: Określa, która część adresu IP jest częścią sieciową, a która hosta. Pozwala na podział większych sieci na mniejsze (podsieci), co ułatwia zarządzanie i zwiększa bezpieczeństwo. W IPv6 nie używa się maski tylko prefixu, określającego na ile podsieci podzielona jest sieć, w której znajduje się adres. Adres MAC: unikalny numer nadawany dla interfejsów sieciowych na poziomie sprzętowym. Przechowywane w tablicy ARP w parze z adresem IP identyfikują urządzenie do komunikacji w warstwie łącza danych (np. switche) 2. Omów mechanizm wyznaczania trasy w sieciach komputerowych, podaj przykłady protokołów routingu. Mechanizm wyznaczania trasy w sieciach komputerowych, znany jako routing, polega na wyborze optymalnej ścieżki, którą pakiety danych będą przesyłane od źródła do celu w sieci. Wyróżniamy routing statyczny i dynamiczny. W przypadku routingu statycznego ścieżki definiowane są ręcznie przez administratora sieci, co daje prostą i przewidywalną listę połączeń, jednakże każda zmiana w topologii wymusza na administratorze aktualizację tablicy routingu. W przypadku zastosowania routingu dynamicznego trasy obliczane są automatycznie, na podstawie zastosowanego algorytmu routingu. Dzięki temu zmiany w topologii sieci zostaną automatycznie uwzględnione w tablicy, kiedy tylko router wykryje taką zmianę. RIP (Routing Information Protocol): prosty protokół routingu o niskich wymaganiach sprzętowych, dzięki czemu może być używany przez wszystkie routery. Działa, wysyłając (standardowo, można skonfigurować inaczej) co 30 sekund zawartość swojej tablicy routingu do bezpośrednich sąsiadów. Po uzyskaniu odpowiedzi, jeżeli zajdzie taka potrzeba uaktualnia swoją. Jakość trasy jest mierzona liczbą przeskoków (hopów), z limitem 15, co ogranicza zastosowanie RIP do małych i średnich sieci. Najlepiej sprawdza się w sieciach jednorodnych o jednakowej przepustowości łączy. OSPF (Open Shortest Path First): protokół wykorzystujący algorytm Dijkstry (SPF) do obliczenia najkrótszych ścieżek. Zakłada on że im większa przepustowość tym niższy koszt. Sieć wykorzystująca protokół OSPF może być podzielona na obszary, z których każdy musi być podłączony do jednego 'głównego' (szkieletowego, 0). Dzięki takiemu podejściu zmiana w jednym z obszarów nie wymusza obliczania ścieżek w całej sieci tylko w obszarze, w którym zmiana nastała. Zwiększa to wydajność przez redukcję ilości obliczeń. IGRP (Interior-Gateway Routing Protocol): opracowany przez firmę CISCO, działa analogicznie do protokołu RIP. Różnicą jest metryka - nie jest to tylko ilość skoków tylko kombinacja miar: opóźnienia, przepustowości, obciążenia i niezawodności. Jego następca - EIGRP (Extended IGRP) do wyznaczania tras stosuje algorytm DUAL (Diffusing – Update ALgorithm), który wymusza przeliczenie ścieżki jeżeli zdarzy się sytuacja pętli routingu. 3. Wyjaśnij zasadę działania systemu DNS (Domain Name System). Podstawą działania DNS jest światowa sieć serwerów, przechowująca rekordy dotyczące stron. Każdy rekord przechowuje informację o nazwie domenowej (google.com, wp.pl itp) i odpowiedniego dla niego adresu IP (google => 142.250.186.206, wp => 212.77.98.9). Po wpisaniu nazwy domeny do przeglądarki, do serwera DNS wysyłane jest zapytanie. Serwer DNS odpowiada, przekazując adres IP przypisanego serwera WWW. Przeglądarka może wtedy skierować zapytanie do serwera docelowego, a następnie odesłać do internauty otrzymane dane, czyli wyszukiwaną stronę internetową. 4. Wyjaśnij zasadę działania systemu DHCP (Dynamic Host Configuration Protocol). DHCP jest protokołem typu klient-serwer. Klientem jest komputer próbujący podłączyć się do sieci podczas uruchamiania systemu operacyjnego lub chcący przedłużyć tzw. okres dzierżawy. Klient łączy się zdalnie z serwerem DHCP, aby pobrać parametry konfiguracji sieci, m.in. adres IP. Protokół DHCP umożliwia automatyczne przydzielanie adresów IP z określonego przez administratora zakresu. Z tego zakresu adresy mogą być wyłączone (wykluczone - nie mogą zostać przypisane do żadnego z urządzeń), lub 'zarezerwowane' dla konkretnego urządzenia (poprzez przypisanie statyczne na podstawie adresu MAC). Mogą to być zarówno adresy z puli publicznej, jak i prywatnej. Serwer DHCP przechowuje bazę danych z informacjami o niewykorzystanych w danej chwili adresach IP. Każdy adres jest przydzielany na określony w konfiguracji czas dzierżawy (lease time), po którego upływie wysyła ponowne żądanie do serwera. Jeżeli serwer nie otrzyma takiego żądania adres jest 'oddawany' do puli dostępnych adresów. 5. Omów model OSI. Model ISO/OSI opisuje ramy używane w ruchu sieciowym. Składa się z 7 warstw (komunikacja użytkownik → urządzenia sieciowe: w dół; urządzenia sieciowe → użytkownik: w górę) 7 - warstwa aplikacji ┓ 6 - warstwa prezentacji ┣→ warstwy "wyższe" 5 - warstwa sesji ┛ 4 - warstwa transportowa ┓ 3 - warstwa sieci | 2 - warstwa łącza danych ┣→ warstwy "niższe" 1 - warstwa fizyczna ┛ Warstwa aplikacji udostępnia użytkownikom możliwość korzystania z usług sieciowych, takich jak WWW, poczta elektroniczna, wymiana plików, połączenia terminalowe czy komunikatory. Warstwa prezentacji odpowiada za kodowanie i konwersję danych oraz za kompresję / dekompresję; szyfrowanie / deszyfrowanie. Warstwa sesji odpowiada za synchronizację danych przesyłanych między użytkownikiem a różnymi aplikacjami np. ze stron WWW czy komunikacji video. Warstwa transportu obsługuje komunikację pomiędzy urządzeniami. W warstwie tej dane dzielone są na mniejsze części, następnie opatrywane są dodatkowymi informacjami pozwalającymi zarówno przydzielić je do właściwej aplikacji na urządzeniu docelowym (↓), jak i pozwalającymi złożyć je na urządzeniu docelowym w odpowiedniej kolejności (↑). Korzysta z protokołów TCP i UDP. Warstwa sieciowa jako jedyna dysponuje wiedzą dotyczącą fizycznej topologii sieci. Jej główne zadanie to adresowanie i wyznaczanie najlepszej ścieżki przesyłu danych. Warstwa łącza danych nadzoruje jakość przekazywanych informacji. Ma za zadanie zmieniać parametry w celu zmniejszenia ilości błędów (↑) i pakować dane w ramki (↓) a także naprawiać błędy zaistniałe w ramkach (↨) Warstwa fizyczna koduje dane do postaci czystych bitów (zer i jedynek) i przesyła je poprzez medium transmisyjne do odpowiednich urządzeń. Składa się z czterech obszarów funkcjonalnych: mechanicznego, elektrycznego, funkcjonalnego, proceduralnego. 6. Omów zasady mechanizmu tunelowania połączeń. Tunelowanie to technika umożliwiająca przesyłanie danych z jednej sieci do drugiej przy użyciu protokołów, które nie są ze sobą kompatybilne. Zestawia połączenia między dwoma odległymi hostami tak, by stworzyć wrażenie, że są połączone bezpośrednio, przy założeniu, że sieć Internet nie zna protokołu, którym posługują się te hosty. Tunelowanie polega na enkapsulacji danych w pakiety, które można przesyłać w sieci docelowej. Może być również używane do szyfrowania danych, przez co jest podstawą działania sieci VPN. 7. Wyjaśnij różnice pomiędzy protokołami TCP oraz UDP. TCP: Protokół ten nawiązuje połączenie przed wysłaniem danych, co gwarantuje uporządkowane i bezpieczne dostarczenie informacji. UDP: W przeciwieństwie do TCP, protokół ten nie nawiązuje połączenia i nie gwarantuje dostarczenia pakietów, co czyni go szybszym, ale mniej niezawodnym. Różnice: Protokół TCP jest bardziej niezawodny, ponieważ gwarantuje dostarczanie danych w tej samej kolejności, w jakiej zostały wysłane, podczas gdy UDP jest szybszy, ale dostarczanie danych nie jest gwarantowane. cechy: Protokół TCP jest zorientowany połączeniowo, niezawodny i odpowiedni do zastosowań wymagających bezpiecznego i uporządkowanego dostarczania danych. UDP jest bezpołączeniowy, szybki i odpowiedni do zastosowań w czasie rzeczywistym, takich jak gry wideo lub transmisja strumieniowa na żywo. Wykorzystanie: TCP służy między innymi do przesyłania plików, poczty e-mail i przeglądania stron internetowych. UDP służy między innymi do wideokonferencji, transmisji w czasie rzeczywistym, gier online. 8. Wyjaśnij zasadę działania koncentratora, przełącznika oraz rutera. Koncentrator (hub) pracuje w warstwie pierwszej modelu ISO/OSI (warstwie fizycznej), przesyłając sygnały elektryczne z jednego portu (gniazda) na wszystkie pozostałe. Takie podejście prowadzi do wielokrotnego powielenia sygnałów, przez co tworzy on domenę kolizyjną. Aktualnie niemal wyparty przez przełączniki. Przełącznik (switch) pracuje głównie w drugiej warstwie modelu ISO/OSI (łącza danych). Jego zadaniem jest przekazywanie ramki między segmentami sieci z doborem portu przełącznika, na który jest przekazywana. Zwiększa to bezpieczeństwo (dane trafiają tylko do docelowego odbiorcy) i szybkość sieci (nie ma przypadków sprawdzania X urządzeń zanim pakiet trafi na swoje miejsce). Router pracuje w trzeciej warstwie modelu OSI. Służy do łączenia różnych sieci komputerowych (węzeł komunikacyjny). Na podstawie danych w pakietach przekazuje dane pomiędzy sieciami, do których jest podłączony (np. wewnętrzna ↔ zewnętrzna). Steruje ruchem podsieci na podstawie tablicy routingu. 9. Omów zastosowania protokołu ICMP. ICMP (Internet Control Message Protocol) pełni przede wszystkim funkcję kontroli transmisji w sieci. Jest używany do przesyłania komunikatów o błędach i diagnostyki w sieciach IP. Wykorzystywany jest również w programach ping oraz traceroute. Przykładowe sytuacje wykorzystania protokołu ICMP: Gdy router lub host jest zbyt obciążony, by móc przyjąć do buforów kolejne datagramy, komunikaty ICMP służą do zwolnienia szybkości napływania datagramów do danego routera. Gdy router lub host znajduje lepsza trasę do miejsca przeznaczenia, może wysłać do hosta źródłowego komunikat ICMP, powiadamiający o krótszej trasie. Gdy host docelowy jest nieosiągalny, ostatnia brama wysyła komunikat ICMP z powrotem do hosta źródłowego, informując o niedostępności adresata. Gdy host lub brama przetwarza pakiet o TTL równym 0 hopów, wówczas odrzuca ten pakiet i ewentualnie wysyła komunikat ICMP do hosta źródłowego. 10. Omów mechanizm maskarady. Maskarada (Network address translation; NAT) - technika przesyłania ruchu sieciowego przez router. Wiąże się to ze wzrostem liczby komputerów, powstała aby nie wyczerpać puli możliwych adresów IPv4. Urządzenie podłączone do routera identyfikuje się swoim adresem prywatnym, który następnie jest tłumaczony na adres publiczny, najczęściej adres routera. / NAT (Network Address Translation) jest technologią, która pozwala na przetłumaczenie adresów sieciowych wewnętrznej sieci na adresy publiczne, które są używane na zewnątrz sieci. Jest to często stosowane, aby nadać dostęp do Internetu wielu urządzeniom wewnątrz sieci z jednego publicznego adresu IP. Dzięki temu nie trzeba przydzielać każdemu urządzeniu osobnego adresu IP. Oszczędza to ilość publicznych adresów IP. Częstym zastosowaniem NAT-a jest ukrywanie adresów wewnętrznych, czyli tak zwana “maskarada”. Dzięki wcześniej wspomnianemu przetłumaczeniu, urządzenia wewnątrz sieci są chronione przed próbami połączenia z zewnątrz, ponieważ dla zewnętrznego obserwatora są ukryte/niewidoczne. IX. Narzędzia procesu tworzenia oprogramowania 1. Co to są systemy kontroli wersji, jakie są ich zalety? Systemy kontroli wersji (VCS) są narzędziami używanymi przez programistów do zarządzania zmianami w kodzie źródłowym i plikach projektu. Pozwalają one na śledzenie historii zmian, przywracanie wcześniejszych wersji, równoległą pracę wielu programistów nad tym samym projektem oraz rozwiązywanie konfliktów integracji. Zalety: ❖ Śledzenie Historii Zmian: VCS śledzi historię każdej zmiany w kodzie, włącznie z informacjami o autorze, dacie i opisie zmiany. ❖ Przywracanie Poprzednich Wersji: Umożliwia łatwe przywrócenie poprzednich wersji plików lub całego projektu, co jest przydatne w przypadku popełnienia błędu lub konieczności powrotu do wcześniejszego stanu. ❖ Równoległa Praca Wielu Programistów: Programiści mogą równolegle pracować nad tym samym projektem, a VCS automatycznie integruje i zarządza zmianami. ❖ Rozgałęzianie i Scalanie (Branching and Merging): Pozwala na tworzenie odgałęzień (branchów) w repozytorium, co umożliwia eksperymentowanie z nowymi funkcjami lub naprawianie błędów bez ryzyka zepsucia głównego kodu. ❖ Kontrola Dostępu: Systemy kontroli wersji zapewniają kontrolę dostępu, umożliwiając określenie, którzy użytkownicy mają prawo do modyfikacji kodu lub innych zasobów. ❖ Śledzenie Zmian Pomiędzy Wersjami: VCS umożliwia śledzenie, które linie kodu zostały dodane, zmodyfikowane lub usunięte pomiędzy wersjami ❖ Wsparcie dla Kolaboracji: Systemy kontroli wersji ułatwiają współpracę zespołową 2. Czym różni się profilowanie pamięci kodu zarządzanego a kodu niezarządzanego? Profilowanie pamięci jest procesem analizowania zużycia pamięci przez program w celu zidentyfikowania obszarów, które mogą być zoptymalizowane w celu zmniejszenia zużycia pamięci lub poprawy wydajności. Profilowanie Pamięci Kodu Zarządzanego: ❖ Zarządzanie Pamięcią przez Środowisko Wykonawcze W językach programowania zarządzanych, takich jak Java, C#, czy Python, pamięć jest zarządzana przez środowisko wykonawcze (np. JVM,.NET CLR), które automatycznie alokuje i zwalnia pamięć. ❖ Większa Abstrakcja Kod zarządzany często korzysta z abstrakcji, takich jak automatyczne zarządzanie pamięcią, zbieranie śmieci, tablice dynamiczne itp. ❖ Profilowanie Względem Obiektów i Struktur Danych: Profilowanie pamięci w kodzie zarządzanym często skupia się na analizie zużycia pamięci przez obiekty, kolekcje i inne struktury danych zarządzane przez środowisko wykonawcze. Profilowanie Pamięci Kodu Niezarządzanego: ❖ Ręczne Zarządzanie Pamięcią W językach niezarządzanych, takich jak C++ czy C, programista jest odpowiedzialny za ręczne alokowanie i zwalnianie pamięci za pomocą funkcji jak malloc() i free() w C, lub new i delete w C++. ❖ Zarządzanie Wskaźnikami W kodzie niezarządzanym programista musi szczególnie uważać na wycieki pamięci, niewłaściwe odwołania do pamięci, czy inne błędy związane z zarządzaniem wskaźnikami. ❖ Profilowanie Niskopoziomowe Profilowanie pamięci w kodzie niezarządzanym często wymaga bardziej niskopoziomowych technik, takich jak analiza alokacji pamięci, monitorowanie wskaźników, analiza wycieków pamięci itp. 3. Do czego służą narzędzia do zarządzania błędami, jakie są ich zalety? Zastosowania Narzędzi do Zarządzania Błędami: ❖ Monitorowanie Błędów Narzędzia te automatycznie zbierają informacje o błędach, ostrzeżeniach i incydentach, które występują w systemie. ❖ Analiza Błędów Pomagają w analizie i diagnozowaniu przyczyn błędów, umożliwiając programistom zrozumienie, dlaczego błędy występują i jak je naprawić. ❖ Śledzenie Błędów Umożliwiają śledzenie błędów od ich zgłoszenia do ich rozwiązania, zapewniając przejrzystość w procesie naprawy błędów. ❖ Raportowanie Błędów Pozwalają na generowanie raportów na temat częstości, typów i wzorców błędów w systemie, co pomaga w identyfikacji obszarów wymagających poprawy. ❖ Zarządzanie Priorytetami Umożliwiają ustalanie priorytetów dla błędów, co pozwala zespołowi deweloperskiemu skupić się na rozwiązywaniu najważniejszych problemów w pierwszej kolejności. ❖ Integracja z Narzędziami Programistycznymi Mogą być zintegrowane z narzędziami programistycznymi, takimi jak systemy kontroli wersji, IDE czy systemy raportowania błędów, co ułatwia zarządzanie błędami w procesie rozwoju oprogramowania. Zalety Narzędzi do Zarządzania Błędami: ❖ Poprawa Wydajności Poprawa wydajności poprzez szybkie wykrywanie, diagnozowanie i usuwanie błędów, co zmniejsza czas przestoju systemu. ❖ Zwiększenie Niezawodności Zwiększenie niezawodności systemu poprzez eliminację błędów i zapobieganie ponownemu występowaniu tych samych problemów. ❖ Poprawa Bezpieczeństwa Poprawa bezpieczeństwa poprzez szybką reakcję na błędy, które mogą stanowić zagrożenie dla danych i infrastruktury systemu. 4. Co to jest refaktoring kodu, podaj dwa przykłady? Refaktoring kodu to proces restrukturyzacji istniejącego kodu źródłowego bez zmiany jego zewnętrznej funkcjonalności. Celem refaktoryzacji jest poprawa czytelności, jakości, czy elastyczności kodu. ❖ Ekstrakcja Metody Polega na wyodrębnieniu części kodu z istniejącej metody i umieszczeniu ich w nowej, oddzielnej metodzie. Jest to przydatne, gdy długość metody przekracza normy czytelności kodu lub gdy fragment kodu można wykorzystać w innych miejscach. ❖ Rozdzielenie Modułu (Klasy) Polega na podziale jednego modułu lub klasy na mniejsze, bardziej spójne i czytelne części. Jest to przydatne, gdy moduł lub klasa jest zbyt duża lub wykonuje zbyt wiele zadań. X. Architektura komputerów 1. Omów konstrukcję modelu programowego procesora w podejściu CISC i RISC. CISC: Podejście stosowane w latach 60-tych i 70-tych XX w. Zakłada odpowiedniość pomiędzy instrukcjami procesora i instrukcjami języka wysokiego poziomu ○ instrukcja języka wysokiego poziomu jest zamieniana na jedną lub kilka instrukcji procesora Rejestry służą tylko do tymczasowego przechowywania wyników pośrednich i adresów, dane znajdujące się w pamięci ○ instrukcje operują na danych w pamięci Instrukcje operują na argumentach o różnych długościach ○ bajty, słowa 16, 32, ew. 64-bitowe ○ długość argumentu zapisana w kodzie instrukcji Bogaty repertuar trybów adresowania ○ konieczny dostęp do argumentów operacji w pamięci ○ zwykle operacje stosowe zrealizowane w liście instrukcji Max. 16 rejestrów Operacje warunkowe - najczęściej z użyciem znaczników Dominują instrukcje dwuargumentowe - wynik zastępuje argument źródłowy ○ specyfikacja dwóch argumentów wymaga mniejszej liczby bitów w obrazie binarnym instrukcji niż specyfikacja trzech argumentów ○ rejestry przechowują tymczasowe wyniki obliczeń - nowy wynik tymczasowy zastępuje poprzedni RISC: Skalarne dane lokalne procedury są przechowywane w rejestrach ○ Odwołania do pamięci głównie w prologu i epilogu procedury - przeładowanie ramki stosu Duży zestaw rejestrów - min. 16, zwykle przynajmniej 32 ○ rejestry powinny mieścić skalarne argumenty i dane lokalne procedury Instrukcje trójargumentowe - nie niszczą argumentów źródłowych ○ dane lokalne nie są zamazywane podczas wykonywania na nich operacji Rzadkie odwołania do pamięci nie wymagają złożonych trybów adresowania ○ proste kodowanie instrukcji Proste instrukcje dają się wykonać w prostej i szybkie jednostce wykonawczej ○ Każda instrukcja ma tylko jeden argument docelowy ○ Najwyżej jedno odwołanie do pamięci Złożone operacje można zsyntezować z kilku instrukcji ○ Również tryby adresowania Instrukcje arytmetyczne i logiczne operują tylko na danych w rejestrach i argumentach natychmiastowych ○ długość argumentu jest zwykle równa długości rejestru ○ brak operacji 8- i 16-bitowych Tylko dwa rodzaje instrukcji operują na pamięci: ○ Load - “ładuj” ○ Store - “składuj” ○ Tzw. “architektura load-store” 2. Zdefiniuj superskalarną jednostkę centralną – omów zasady działania, występujące hazardy i opóźnienia. Co to jest procesor wielopotokowy? ➔ Idealna (aczkolwiek jedynie teoretyczna) wydajność procesorów potokowych wynosi 1 CPI (Cycle Per Instruction). ➔ Logiczne zatem jest, że procesor nie jest w stanie wykonywać instrukcji w ułamku cyklu, ale może zrealizować więcej niż pojedynczą instrukcję w czasie jednego cyklu. ➔ Procesor taki musi zatem posiadać więcej aniżeli jeden potok wykonawczy. ➔ Procesory posiadające wiele potoków wykonawczych nazywać będziemy procesorami wielopotokowymi, superskalarnymi albo po prostu superskalarami. potok - grupa instrukcji … Superskalar ze zmianą kolejności instrukcji ➔ Rozważmy następującą sekwencję instrukcji addu $4, $3, $2 addu $2, $5, $4 ◆ Pierwsza instrukcja korzysta z argumentu źródłowego w rejestrze $2. ◆ Jednocześnie rejestr ten jest rejestrem docelowym dla drugiej instrukcji. ➔ Problem: Jaką wartość rejestru drugiego ($2) pobierze pierwsza instrukcja? ➔ Taka niejednoznaczność nazywana jest hazardem W-A-R (Write-After-Read - zapis po odczycie) - CPU musi gwarantować poprawność wykonania takiej sekwencji ➔ Rozważmy następującą sekwencję instrukcji: addu $4, $3, $2 addu $4, $8, $9 addu $2, $5, $4 ◆ Trzecia instrukcja korzysta z argumentu źródłowego w rejestrze $4. ◆ Jednocześnie rejestr ten jest docelowym rejestrem dla pierwszej i drugiej instrukcji. ➔ Problem: Jaką wartość rejestru czwartego ($4) pobierze trzecia instrukcja? ➔ Taka niejednoznaczność nazywana jest hazardem W-A-W (Write-After-Write - zapis po zapisie) - CPU musi gwarantować poprawność wykonania takiej sekwencji Hazardy W-A-R i W-A-W ➔ Obydwa te hazardy nie wynikają z prostej zależności instrukcji. ➔ Zależność między instrukcjami w przypadku hazardu W-A-R daje się zauważyć dopiero po odwróceniu kolejności instrukcji. ➔ Zależności tego rodzaju nazywa się zależnościami wstecznymi, fałszywymi albo antyzależnościami. ➔ Usunięcie hazardów W-A-R oraz W-A-W wymaga zrozumienia przyczyn ich powstania. 3. Zdefiniuj wyjątki podając ich definicje i klasyfikacje. Omów obsługę wyjątków. Co to jest wyjątek w systemie komputerowym? ➔ Wyjątek (sytuacja wyjątkowa) - jest to zdarzenie występujące w ramach systemu komputerowego, które wymaga natychmiastowego (zazwyczaj) przerwania aktualnie realizowanego strumienia instrukcji (niekoniecznie jest to program) i przekazania sterowania do systemu operacyjnego. ➔ Podział sytuacji wyjątkowych: ◆ Przerwania ◆ Pułapki ◆ Błędy Przerwania ➔ Powstają poza CPU - za wyjątkiem asynchronicznego przerwania programowego. ➔ Są one asynchroniczne względem aktualnie realizowanego strumienia instrukcji - ich wystąpienie nie jest najczęściej bezpośrednim wynikiem wykonania konkretnej instrukcji. ➔ Służą do sygnalizacji zdarzeń istotnych z punktu widzenia systemu operacyjnego: ◆ Zmiana kontekstu urządzeń zewnętrznych - np. zmiana klawisza na klawiaturze, ruch myszką, nadejście pakietu z sieci lokalnej ◆ Upłynięcie określonego odcinka czasu - np. timer systemowy, który służy do periodycznego przełączania procesorów w trybie wieloprocesorowym Pułapki ➔ Są one generowane przez procesor. ➔ Powodowane przez konkretną instrukcję. Znajdują się na końcu wykonania danej instrukcji - są ściśle synchroniczne względem aktualnego ciągu instrukcji. ➔ Rodzaje pułapek: ◆ Wywołanie usługi systemu operacyjnego przez program użytkowy - np. w ramach procesorów MIPS służy do tego instrukcja SYSCALL. ◆ Sygnalizacja błędów wykonania, które zostały wykryte przez program użytkowy do systemu operacyjnego - np. w ramach procesorów MIPS, instrukcje ADD i SUB wygenerują pułapkę w momencie wystąpienia przepełnienia. ◆ Pułapki śledzenia - wygenerowane po wykonaniu dowolnej instrukcji przy ustawionym trybie śledzenia Błędy ➔ Zazwyczaj są one generowane przez CPU. ◆ Zarówno przez jednostkę wykonawczą jak i przez jednostkę zarządzania pamięcią. ◆ Wyjątkiem jest “błąd transmisji”, który jest generowany poza procesorem. ➔ Wynikają z wykonywanych instrukcji, ale nie zawsze w sposób jednoznaczny. ➔ Służą do sygnalizacji błędnych i niedozwolonych zachowań oprogramowania oraz sprzętu. ◆ Próba wykonania niezdefiniowanej instrukcji. ◆ Błąd wyrównania przy dostępie do pamięci. ◆ Naruszenie zasad ochrony - CPU i pamięci. ➔ Są one wykorzystywane do implementacji systemu pamięci wirtualnej. Obsługa wyjątków ➔ Każdy wyjątek (niezależnie od reprezentowanego rodzaju!) musi być obsłużony. ➔ Istnieją dwa podstawowe pojęcia obsługi wyjątków: ◆ Na poziomie oprogramowania - reakcja programowa systemu operacyjnego na zdarzenie - np. gotowość kolejnej porcji danych do urządzenia zgłaszającego gotowość. ◆ Na poziomie CPU - zespół czynności, których efektem jest zaniechanie wykonywania bieżącego strumienia instrukcji i rozpoczęcie wykonania programowej procedury systemu operacyjnego - np. obsługa wyjątku przez OS rozpoczyna się w momencie, w którym jego obsługę zakończy CPU. Obsługa wyjątków przez CPU - fazy ➔ Rozpoznanie i identyfikacja źródła wyjątku. ➔ Przerwanie wykonania bieżącego strumienia instrukcji i zapamiętanie bieżącego kontekstu CPU. ➔ Załadowanie nowego kontekstu CPU i rozpoznanie wykonywania nowego strumienia instrukcji - procedury systemowej zapewniającej programową reakcję systemu na wyjątek. 4. Omów podstawy realizacji systemu pamięci podręcznej uwzględniając jej poziomowość. System pamięci podręcznej (cache memory) jest kluczowym elementem w architekturze komputerowej, służącym do przyspieszenia dostępu do danych poprzez przechowywanie najczęściej używanych bloków danych w szybszej, ale mniejszej pamięci podręcznej. Poziomy Pamięci Podręcznej: ❖ Poziom L1 (Level 1 Cache) L1 to najbliższy procesorowi poziom pamięci podręcznej, który jest zazwyczaj zintegrowany bezpośrednio z rdzeniem procesora. Jest bardzo szybki, ale ma ograniczoną pojemność z powodu fizycznych ograniczeń miejsca. Przechowuje najczęściej używane dane i instrukcje. ❖ Poziom L2 (Level 2 Cache) L2 to poziom pamięci podręcznej znajdujący się nieco dalej od procesora niż L1, ale nadal jest on często zintegrowany z samym procesorem lub znajduje się w pobliżu na tej samej kości. Posiada większą pojemność niż L1, ale jest trochę wolniejszy. Może przechowywać dane i instrukcje, które nie mieszczą się w pamięci L1. ❖ Poziom L3 (Level 3 Cache) L3 to najdalszy poziom pamięci podręcznej w hierarchii, który często jest wspólny dla wszystkich rdzeni w danym procesorze lub grupie rdzeni. Ma jeszcze większą pojemność niż L2, ale jest wolniejszy. Jest wykorzystywany do przechowywania większych ilości danych, które nie mieszczą się w pamięciach L1 i L2. 5. Zdefiniuj budowę modelu programowego jednostki centralnej – omów niezbędne rejestry, tryby adresowania, listę instrukcji oraz model operacji warunkowych. Rejestry: Rejestry to małe, szybkie pamięci znajdujące się bezpośrednio w procesorze. Są one wykorzystywane do przechowywania danych i instrukcji niezbędnych do wykonywania bieżących operacji akumulatora: używany do przechowywania wyników operacji arytmetycznych i logicznych danych: przechowują dane, które mają być przetworzone lub zostały już przetworzone wskaźników (np. program counter - PC): przechowują adresy, np. następnej instrukcji do wykonania indeksowe: używane do obliczania adresów pamięci w operacjach związanych z tablicami stanu: zawierają flagi statusowe, takie jak flaga przepełnienia, flaga zerowa Tryby adresowania: Sposób, w jaki instrukcje w procesorze identyfikują operand (np. dane, na których mają operować). Bezpośredni: adres operandu jest bezpośrednio w instrukcji. Pośredni: adres w instrukcji wskazuje na miejsce, gdzie znajduje się rzeczywisty adres operandu Rejestrowy: operand znajduje się w jednym z rejestrów Indeksowy i bazowy: wykorzystują rejestr indeksowy lub bazowy do obliczenia adresu operandu. Lista instrukcji: Zestaw podstawowych operacji, które CPU może wykonać Operacje arytmetyczne: takie jak dodawanie, odejmowanie, mnożenie, dzielenie Operacje logiczne: AND, OR, NOT, XOR. Instrukcje przesunięcia i rotacji Instrukcje transferu danych: ładowanie do rejestru, zapis z rejestru Instrukcje kontrolne: skoki, wywołania funkcji, powroty z funkcji Model operacji warunkowych: Określa sposób realizacji przez procesor operacji warunkowych Model ze znacznikami - sposób wykonania zależy od wartości znaczników Model bez znaczników np. "skocz jeśli zawartości rejestrów równe" Model z predykatami XI. Inżynieria oprogramowania 1. Wymień i krótko scharakteryzuj najważniejsze modele cyklu życia oprogramowania. ❖ Model wodospadowy Linearny model, w którym kolejne fazy projektowania (analiza, projektowanie, implementacja, testowanie, wdrożenie) są wykonywane sekwencyjnie, podobnie jak woda spływająca po kaskadzie. Każda faza musi zostać zakończona, zanim rozpocznie się następna. Zalety: Prosta i łatwa do zrozumienia struktura. Łatwe zarządzanie postępem projektu. Wady: Brak elastyczności w dostosowywaniu się do zmian wymagań. Trudności w ocenie wymagań i oczekiwań klienta przed rozpoczęciem implementacji. ❖ Model spiralny Model iteracyjny, który łączy elementy modelu wodospadowego z elementami prototypowania. Projekt jest podzielony na cykle, w których każdy cykl obejmuje planowanie, analizę ryzyka, budowę, ewaluację i przegląd. Zalety: Elastyczność w dostosowywaniu się do zmian w trakcie projektu. Możliwość oceny i zarządzania ryzykiem na wczesnych etapach projektu. Wady: Wymaga dużej ilości zasobów i czasu na przeprowadzenie iteracji. Może być trudny do zarządzania w przypadku dużych projektów. ❖ Model COTS Model, w którym oprogramowanie jest kupowane od zewnętrznego dostawcy i dostosowywane do specyficznych potrzeb klienta. Zamiast tworzyć oprogramowanie od podstaw, wykorzystuje się gotowe rozwiązania rynkowe. Zalety: Oszczędność czasu i zasobów dzięki wykorzystaniu gotowych produktów. Możliwość skorzystania z funkcjonalności i doświadczenia dostawcy. Wady: Brak kontroli nad kodem źródłowym i mniej elastyczności w dostosowywaniu się do specyficznych wymagań. Ryzyko związane z niekompatybilnością z innymi systemami lub brakiem wsparcia w przyszłości. 2. Wymień i krótko omów zastosowania najważniejszych diagramów UML. ❖ Diagram przypadków użycia opisuje działanie systemu z punkty widzenia użytkownika relacje między aktorami a systemem ❖ Diagram klas opisuje strukturę klas i ich relacje w systemie pokazuje atrybuty, metody, zależności klas ❖ Diagram stanów cykl życia obiektu opisując jego stany i przejścia pomiędzy nimi ❖ Diagram wdrożeń pokazuje fizyczną infrastrukturę systemu wraz z jego oprogramowaniem i połączeniami między urządzeniami 3. Podaj i krótko scharakteryzuj rodzaje testów oprogramowania. ❖ testy jednostkowe sprawdzają pojedyncze fragmenty kodu ❖ testy ludzkie ręczne testowanie aplikacji przez użytkowników ❖ testy automatyczne wykonywane przez specjalne narzędzia i skrypty, które automatycznie uruchamiają testy i analizują wyniki ❖ testy dymne szybkie testy sprawdzające działanie systemu po wprowadzeniu zmian ❖ testy integracyjne sprawdzają czy komponenty poprawnie ze sobą współpracują 4. Podaj przykłady dwóch metryk dla oceny jakości programu obiektowego i skomentuj jakie kryteria jakości te metryki odzwierciedlają. ❖ Metryka Zależności Między Klasami Liczba zewnętrznych zależności między klasami Kryteria jakości Niska zależność między klasami oznacza, że zmiany w jednej klasie mają niewielki wpływ na inne klasy Wysoka zależność może prowadzić do trudności w modyfikacji i testowaniu kodu, a także utrudniać ponowne wykorzystanie ❖ Metryka Spójności Wewnętrznej Spójność metody - miara, która określa, jak dobrze metody w klasie są powiązane ze sobą Kryteria jakości Wysoka spójność oznacza, że metody w klasie są silnie powiązane ze sobą i współpracują w ramach jednego celu Niska spójność może oznaczać, że klasa próbuje wykonywać zbyt wiele różnych zadań lub nie ma jasno określonego celu, co może prowadzić do trudności w zrozumieniu i utrzymaniu kodu ❖ Metryka Rozmiaru Klasy Liczba linii kodu w klasie Kryteria jakości Optymalna wielkość klasy to taka, która jest odpowiednia dla jej zadania i nie jest ani zbyt duża, ani zbyt mała Duże klasy mogą być trudne do zrozumienia i utrzymania, a także mogą oznaczać, że klasa próbuje wykonywać zbyt wiele zadań Zbyt małe klasy mogą być zbyt ogólne lub niekompletne, co może prowadzić do nadmiernego uzależnienia od innych klas. XII. Sztuczna inteligencja 1. Algorytmy przeszukiwania przestrzeni stanów w systemach sztucznej inteligencji. ❖ Przeszukiwanie wszerz (BFS) Zaczyna od początku, przeszukuje wszystko na tym samym poziomie, potem idzie dalej dobre dla niskiej gęstości ❖ Przeszukiwanie w głąb (DFS) Zaczyna od początku, wybiera ścieżkę i podąża nią do momentu końca lub osiągnięcia warunku ograniczającego eksploatację, potem wraca i idzie kolejną ścieżką dobre dla ślepych zaułków lub głębokich struktur ❖ Przeszukiwanie z wykorzystaniem heurystyki Wykorzystuje dodatkowe informacje (np. wartości danych ścieżek), aby wybrać najlepszą ścieżkę 2. Obliczenia ewolucyjne. Rodzaj podejścia heurystycznego do rozwiązywania problemów, wykorzystuje zasady ewolucji biologicznej jako model do tworzenia optymalnych rozwiązań Aspekty obliczeń ewolucyjnych: ❖ Populacja W obliczeniach ewolucyjnych rozwiązania problemu są reprezentowane przez osobniki, które tworzą populację Populacja składa się z pewnej liczby osobników, które ewoluują w czasie ❖ Selekcja Selekcja polega na wyborze najlepszych osobników z populacji, którzy zostaną poddani krzyżowaniu i mutacji Najlepsze osobniki są wybierane na podstawie ich oceny lub wartości funkcji celu ❖ Krzyżowanie Krzyżowanie polega na wymianie części informacji genetycznej między osobnikami w celu stworzenia nowych rozwiązań potomnych ❖ Mutacja Mutacja polega na wprowadzaniu losowych zmian w genotypie osobników w celu zachowania różnorodności w populacji ❖ Ocena Ocena polega na przypisaniu wartości numerycznej każdemu osobnikowi w populacji, która reprezentuje ich jakość lub dostosowanie do problemu Jest to funkcja celu, która informuje, jak dobrze dany osobnik radzi sobie w rozwiązywaniu problemu ❖ Elityzm Elityzm polega na zachowaniu najlepszych osobników z populacji w każdej iteracji algorytmu, aby zapewnić, że najlepsze rozwiązania nie zostaną utracone. 3. Polska Szkoła Sztucznej Inteligencji - zbiory przybliżone. Teoria zbiorów przybliżonych zajmuje się klasyfikacją danych zorganizowanych w postaci tabel. Dane uzyskane mogą być z pomiarów, testów lub od ekspertów. Głównym celem analizy danych jest wyznaczenie aproksymacji idei (koncepcji) na podstawie danych w celu: - Dokładnej analizy problemu, związków, zależności - Uzyskania narzędzia klasyfikującego nowe przypadki Zalety zbiorów przybliżonych nie wymaga ona dodatkowych założeń odnośnie danych (np. prawdopodobieństwa czy rozmytości), oferuje szybkie algorytmy analizy danych, łatwość interpretacji wyników, prostota matematyczna, uzupełnia istniejące metody i może być stosowana łącznie z nimi. ❖ klasy decyzyjne - wyniki jakie mogą wystąpić (śliwki dojrzałe lub niedojrzałe) ❖ klasy nieodróżnialności (zbiory elementarne) - grupujemy obiekty w zbiory, w których atrybuty są identyczne ❖ dolna aproksymacja - to co możemy wywnioskować i jest zawsze prawdą (jeżeli śliwka jest fioletowa = jest dojrzała) (zbiory elementarne w pełni zawarte w klasie decyzyjnej) ❖ górna aproksymacja - dolna aproksymacja + niepewność (zbiory elementarne, które mają przecięcie z klasą decyzyjną) ❖ obszary brzegowe - różnica górnej aproksymacji i dolnej aproksymacji ❖ obszar pozytywny - suma dolnych aproksymacji wszystkich klas decyzyjnych ❖ redukt - atrybuty (przedstawiane jako zbiór), które nie decydują o klasyfikacji (wyniku) obiektu (liczone są jako porównanie obszaru pozytywnego dla 1 atrybutu z obszarem pozytywnym całego obiektu, jeżeli są takie same to ten atrybut jest reduktem) 4. Wnioskowanie oparte na logice w systemach sztucznej inteligencji. Wnioskowanie oparte na logice jest jednym z podstawowych mechanizmów wykorzystywanych w systemach sztucznej inteligencji do wyciągania wniosków na podstawie dostępnych danych i reguł logicznych. Ten rodzaj wnioskowania opiera się na formalnych zasadach logiki, które są używane do analizy i przetwarzania informacji. Wnioskowanie formalne (oparte na rachunku zdań lub logice predykatów) zakłada, że wiedza ma charakter dwuwartościowy: fakty zawarte w bazie wiedzy oraz uzyskane na ich podstawie konkluzje mogą być albo prawdziwe, albo fałszywe. W życiu codziennym występują jednak pojęcia i zjawiska, które mają charakter wieloznaczny i nieprecyzyjny. Opisanie ich za pomocą klasycznej teorii zbiorów oraz logiki dwuwartościowej jest niemożliwe. W przypadku przetwarzania wiedzy niepewnej lub niepełnej stosowana jest teoria zbiorów rozmytych i oparte na niej metody wnioskowania np. wnioskowanie przybliżone, logika rozmyta itd. Głównym działem teorii zbiorów rozmytych jest logika rozmyta stosowana do modelowania i sterowania systemów. 5. Sztuczne sieci neuronowe. Model obliczeniowy, który działa na zasadzie biologicznego neuro