Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 12 czerwca 2026 09:20
  • Data zakończenia: 12 czerwca 2026 09:22

Egzamin niezdany

Wynik: 9/40 punktów (22,5%)

Wymagane minimum: 20 punktów (50%)

Nowe
Analiza przebiegu egzaminu- sprawdź jak rozwiązywałeś pytania
Udostępnij swój wynik
Szczegółowe wyniki:
Pytanie 1

Co zostanie wyświetlone w konsoli po wykonaniu poniższego kodu?

let arr = [1, 2, 3, 4, 5];
let result = arr.filter(num => num % 2 === 0);
console.log(result);
A. [1, 2, 3, 4, 5]
B. 2,4
C. [1, 3, 5]
D. [2, 4]
Wybór odpowiedzi [1, 3, 5] lub [2, 4] oraz 2,4 odzwierciedla niezrozumienie działania metody filter w JavaScript. Odpowiedź [1] sugeruje, że program wyświetli wszystkie parzyste liczby, lecz nie uwzględnia, że filter tworzy nową tablicę tylko z liczb spełniających określony warunek, a w tym przypadku tylko liczby parzyste. Ponadto, [3] wskazuje na brak zastosowania filtru, a więc pokazuje wszystkie elementy tablicy, co również jest błędne. Z kolei odpowiedź 2,4 nie jest nawet poprawnym formatem dla JavaScript, gdzie wyniki w konsoli są prezentowane w postaci tablicy z elementami oddzielonymi przecinkami. Takie podejście, aby zapisać wynik w konsoli, a nie odwoływać się do jego struktury, może prowadzić do błędnych interpretacji. Należy pamiętać, że w JavaScript, kluczowym elementem do zrozumienia jest różnica między metodą filter a innymi metodami tablic, takimi jak map czy forEach. Metoda filter zwraca nową tablicę, podczas gdy inne mogą działać na oryginalnych danych bez ich zmiany. Dlatego ważne jest, aby nie tylko znać technikę, ale i jej zastosowanie w kontekście rozwiązania problemu, co jest niezbędne w pracy programisty.

Pytanie 2

Jak w CSS definiuje się element, który ma reagować na najechanie kursorem?

A. :click
B. :mouse
C. :hover
D. :over
Zarówno :click, :over, jak i :mouse to koncepcje, które mogą wydawać się logiczne, ale w rzeczywistości są nieprawidłowe w kontekście CSS i interakcji z elementami. :click sugeruje, że można bezpośrednio reagować na kliknięcia, jednak w CSS nie ma takiej pseudo-klasy. Interakcje związane z kliknięciami są zazwyczaj obsługiwane w JavaScript, gdzie można zdefiniować zdarzenia kliknięcia dla elementów, co jest zupełnie innym podejściem niż stylowanie elementu w oparciu o położenie kursora. Kolejna koncepcja, :over, nie istnieje w standardzie CSS i nie jest uznawana w praktyce webowej. Choć może to być intuicyjne w odniesieniu do "nałożenia" kursora na element, nie ma takiej funkcjonalności w CSS. Ostatnia z wymienionych opcji, :mouse, również nie ma zastosowania w standardowym CSS. Pojęcia te mogą wprowadzać w błąd, skłaniając do myślenia, że CSS może obsługiwać interakcje, które są typowe dla JavaScriptu. Ważne jest, aby zrozumieć, że CSS jest językiem stylizacji, a interakcje, takie jak klikanie, wymagają użycia skryptów, które są w stanie dostarczyć bardziej złożone funkcjonalności. Dlatego kluczowe jest rozróżnienie między tym, co można osiągnąć za pomocą CSS, a tym, co wymaga języka skryptowego.

Pytanie 3

Który z wymienionych parametrów określa prędkość procesora?

A. Liczba rdzeni
B. Częstotliwość taktowania
C. Wielkość pamięci podręcznej
D. Rodzaj złącza
Ilość rdzeni w procesorze odnosi się do liczby jednostek obliczeniowych w jego architekturze. Choć większa liczba rdzeni może przyczynić się do zwiększenia multitaskingu i wydajności w aplikacjach obsługujących równoległe przetwarzanie, sama ilość rdzeni nie definiuje szybkości procesora w kontekście jego podstawowych cykli zegara. Pojemność pamięci podręcznej, z kolei, dotyczy ilości pamięci dostępnej bezpośrednio w procesorze, co wpływa na szybkość dostępu do często używanych danych. Większa pamięć podręczna może przyspieszyć operacje, ale znowu, nie jest to bezpośredni wskaźnik szybkości działania procesora. Typ złącza jest parametrem technicznym, który określa, w jaki sposób procesor łączy się z płytą główną. Różne rodzaje złączy, jak LGA czy PGA, wpływają na kompatybilność, ale nie mają bezpośredniego wpływu na samą szybkość obliczeniową procesora. W kontekście oceny wydajności procesora, istotne jest zrozumienie, że chociaż ilość rdzeni, pamięć podręczna i typ złącza są ważnymi parametrami, to jednak to częstotliwość taktowania jest kluczowym wskaźnikiem wskazującym na szybkość jego działania.

Pytanie 4

Co oznacza termin 'polimorfizm' w programowaniu obiektowym?

A. Ustanowienie tylko jednego typu dla klasy
B. Zdolność do przyjmowania wielu form przez obiekt
C. Ograniczenie do jednej formy dla obiektu
D. Dziedziczenie metod z klasy bazowej
Polimorfizm to jedno z fundamentalnych pojęć w programowaniu obiektowym, które pozwala na tworzenie elastycznych i skalowalnych aplikacji. Dzięki polimorfizmowi możemy pisać kod, który operuje na obiektach, nie znając ich dokładnego typu w momencie kompilacji. To bardzo przydatne, gdy mamy do czynienia z hierarchią klas, gdzie różne klasy dziedziczą po jednej bazowej. Praktycznym przykładem może być system, w którym mamy klasę bazową 'Zwierzę' i klasy pochodne, takie jak 'Pies' i 'Kot'. Dzięki polimorfizmowi możemy stworzyć funkcję, która przyjmuje parametr typu 'Zwierzę', a następnie wywołuje metodę, która jest specyficzna dla danej klasy pochodnej. To umożliwia nam pisanie bardziej ogólnego i mniej związanego z konkretnymi typami kodu. Polimorfizm pozwala również na wdrażanie wzorców projektowych, takich jak strategia czy fabryka, które zwiększają modularność i reużywalność kodu. Korzystanie z polimorfizmu jest zgodne z zasadami SOLID, szczególnie zasadą podstawienia Liskov, która mówi, że obiekty klasy bazowej mogą być zastępowane obiektami klasy pochodnej bez wpływu na poprawność działania programu.

Pytanie 5

Jaką wartość zwróci funkcja napisana w języku C++, jeżeli jej argumentem wejściowym jest tablica stworzona w następujący sposób:

int tablica[6] = {3,4,2,4,10,0};

int fun1(int tab[]) {
    int wynik = 0;

    for(int i = 0; i < 6; i++)
        wynik += tab[i];
    return wynik;
}
A. 20
B. 0
C. 10
D. 23
W tego typu zadaniach bardzo łatwo popełnić błąd w ocenie działania pętli oraz sumowania wartości w tablicy. Często pojawia się przekonanie, że funkcja może zwracać zero, bo ostatni element tablicy to 0 – ale trzeba pamiętać, że funkcja sumuje wszystkie elementy i zero po prostu nie wpływa na całą sumę, więc wynik się nie wyzeruje. Bywa też, że sugerujemy się pierwszą liczbą z tablicy albo jakąś wyróżniającą się, na przykład 10, myśląc, że to ona jest odpowiedzią – ale to nie ma uzasadnienia w kodzie. W pętli for wyraźnie jest napisane i < 6, czyli przeglądamy sześć elementów. Każdy z nich jest dodawany do zmiennej wynik. Kod nie ma żadnych warunków ani instrukcji przerwania, więc nie można zatrzymać się „na” jakiejś wartości, ani zignorować jakiejkolwiek liczby. Niektóre osoby mogą też popełnić błąd i dodać tylko część elementów albo pomylić kolejność, przez co suma wychodzi 10, 20 lub inna, ale przy mechanicznej analizie kodu to niemożliwe. Odpowiedź 20 pojawia się czasem, kiedy ktoś przez przypadek nie zliczy ostatniego zera, a z kolei 10 to typowy skrót myślowy – może wynikający z szybkiego rzutu oka na największą liczbę w tablicy, jednak suma elementów to nie to samo, co ich maksimum. Z mojego doświadczenia wynika, że bardzo wielu uczniów nie przywiązuje wagi do sumowania wszystkich elementów, zwłaszcza jak pojawia się zero – a przecież matematyka jest tu bezlitosna. W programowaniu sumujesz wszystko jak leci, jeśli nie ma warunku czy filtru. Takie drobne nawyki, jak dokładne śledzenie każdej iteracji pętli, potem procentują podczas bardziej złożonych zadań na egzaminach czy w prawdziwych projektach. Pamiętaj: jeśli kod nie sprawdza warunków, to wykonuje dokładnie to, co jest napisane – nic mniej, nic więcej. Warto się tego trzymać.

Pytanie 6

Jaką złożoność obliczeniową posiada podany algorytm?
Dane:
Tablica: tab[n]
Index: i = 0, 1, ..., n-1
x: szukana

Algorytm:

// K1: i0
// K2: dopóki i < (n - 1)
    // K3: jeżeli tab[i] = x to wypisz i
    // K4: ii + 1
    // K5: idź do K2
// K6: zakończ
A. O(n2)
B. O(n log n)
C. O(n)
D. O(1)
W kontekście złożoności obliczeniowej łatwo wpaść w pułapkę myślenia, że algorytm wydaje się bardziej złożony, niż jest w rzeczywistości. Przykładowo, wybór O(n log n) sugeruje obecność jakiegoś sortowania lub podziału danych, co zupełnie nie występuje w tym rozwiązaniu – tu nie ma rekurencji, dzielenia na podtablice ani żadnych bardziej skomplikowanych operacji. Złożoność O(n^2) typowa jest dla algorytmów, gdzie mamy zagnieżdżone pętle, czyli każda iteracja głównej pętli wyzwala kolejną pełną pętlę po danych – a tutaj pętla jest tylko jedna i przechodzi przez tablicę jeden raz. Bardzo często myli się to z sortowaniem bąbelkowym czy selekcyjnym, gdzie rzeczywiście występuje kwadratowa złożoność, ale nie w prostym przeszukiwaniu liniowym. Z kolei O(1), czyli czas stały, dotyczy tylko takich algorytmów, gdzie liczba operacji nie zależy od wielkości wejścia – na przykład odczytanie elementu z tablicy po znanym indeksie. Tu jednak liczba kroków wzrasta liniowo wraz z n, czyli liczbą elementów, więc niestety nie jest to czas stały. Moim zdaniem, wiele osób błędnie utożsamia prostotę kodu z czasem stałym, ale w rzeczywistości chodzi o to, jak algorytm zachowuje się, gdy ilość danych znacząco rośnie. W tej sytuacji odpowiednia analiza pętli i sposobu przetwarzania danych pozwala szybko zauważyć, że algorytm ten to klasyczne O(n), zgodne z najprostszymi wzorcami algorytmicznymi spotykanymi w praktyce.

Pytanie 7

Jak zrealizować definiowanie własnego wyjątku w języku C++?

A. Automatycznie wywołać funkcję throw
B. Utworzyć klasę, która dziedziczy po std::exception
C. Skorzystać z domyślnej metody obsługi błędów
D. Wykorzystać blok try z pustym blokiem catch
Użycie standardowej funkcji obsługi błędów, takiej jak 'perror()', nie pozwala na zdefiniowanie własnego wyjątku – 'perror()' wyświetla komunikat o błędzie, ale nie zgłasza wyjątku. Blok 'try' z pustym blokiem 'catch' nie tworzy nowego wyjątku, lecz jedynie przechwytuje istniejące wyjątki. Wywołanie 'throw' automatycznie nie definiuje nowego wyjątku – 'throw' służy do zgłaszania istniejącego wyjątku, ale definicja własnego wyjątku wymaga utworzenia nowej klasy dziedziczącej po 'std::exception'.

Pytanie 8

Jakie znaczenie ma poziom dostępności AAA w WCAG 2.0?

A. Średni standard dostępności
B. Najnizszy poziom dostępności
C. Dostosowanie tylko do użytkowników mobilnych
D. Najwyższy poziom dostępności
Niepoprawne odpowiedzi dotyczące poziomu dostępności w WCAG 2.0 wprowadzają w błąd i nie odzwierciedlają rzeczywistego znaczenia poziomów dostępności. Po pierwsze, stwierdzenie o minimalnym poziomie dostępności jest mylące, ponieważ poziom A nie jest jedynie minimalnym standardem, ale również zawiera kluczowe wytyczne. Uznanie poziomu AAA za minimalny standard mogłoby prowadzić do sytuacji, w której użytkownicy niepełnosprawni nie otrzymaliby odpowiedniej pomocy. Kolejnym błędnym podejściem jest określenie poziomu AAA jako średniego poziomu dostępności, co jasno sugeruje błędne zrozumienie hierarchii poziomów w WCAG. W rzeczywistości poziom AAA jest znacznie bardziej wymagający i zawiera dodatkowe kryteria, które są kluczowe dla pełnej dostępności. Ostatnia niepoprawna odpowiedź sugeruje, że poziom AAA dotyczy jedynie użytkowników mobilnych, co jest całkowicie mylne. WCAG 2.0 jest zaprojektowane tak, aby dotyczyło wszystkich platform i urządzeń, nie ograniczając się tylko do mobilnych. Koncentruje się na zapewnieniu dostępności treści dla wszystkich, niezależnie od używanego urządzenia.

Pytanie 9

Na podstawie definicji zamieszczonej w ramce, wskaż, który z rysunków ilustruje komponent Chip zdefiniowany w bibliotece Angular Material?

Ilustracja do pytania
A. Rysunek 3
B. Rysunek 1
C. Rysunek 4
D. Rysunek 2
Rysunek 1 i 2 mogą przedstawiać inne komponenty, takie jak przyciski lub pola tekstowe, które nie pełnią funkcji interaktywnych znaczników. Rysunek 3 najprawdopodobniej reprezentuje suwak lub inny element nawigacyjny, który nie posiada cech charakterystycznych dla komponentu Chip. Komponenty Chip mają specyficzną strukturę, która odróżnia je od standardowych kontrolek interfejsu użytkownika.

Pytanie 10

Jakie polecenie w Gicie jest używane do zapisywania zmian w lokalnym repozytorium?

A. git pull
B. git commit
C. git clone
D. git push
Polecenie 'git push' przesyła zapisane lokalnie commity do zdalnego repozytorium, ale samo w sobie nie zapisuje zmian lokalnie. 'git clone' kopiuje istniejące repozytorium zdalne na komputer lokalny, co jest pierwszym krokiem do pracy z kodem, ale nie służy do zapisywania zmian. 'git pull' pobiera najnowsze zmiany z repozytorium zdalnego i scala je z lokalnym repozytorium, co umożliwia aktualizację kodu, ale nie zapisuje nowych zmian lokalnie jak 'git commit'.

Pytanie 11

Który z wymienionych elementów UI w aplikacjach mobilnych jest odpowiedzialny za przechodzenie pomiędzy ekranami?

A. Pasek narzędziowy
B. ListView
C. Przycisk
D. Navigation Drawer
Przycisk (Button) jest podstawowym elementem interfejsu użytkownika, ale nie spełnia funkcji nawigacyjnej na poziomie strukturalnym – jego zastosowanie ogranicza się do wywoływania pojedynczych akcji po kliknięciu. ListView to komponent wyświetlający listę elementów, ale nie odpowiada za nawigację pomiędzy ekranami aplikacji, a jedynie za prezentację danych. Pasek narzędziowy (Toolbar) to element, który zwykle znajduje się na górze ekranu i umożliwia dostęp do opcji takich jak wyszukiwanie lub ustawienia, ale nie pełni funkcji bocznego menu nawigacyjnego, jak Navigation Drawer.

Pytanie 12

Jakie ma znaczenie operator "==" w języku C++?

A. Przypisanie wartości do zmiennej
B. Zwiększenie wartości zmiennej o 1
C. Porównanie dwóch wartości
D. Negacja logiczna
Operator `=` to operator przypisania, który służy do przypisywania wartości do zmiennej (`a = 5`). Jest to jedna z najczęstszych przyczyn błędów logicznych, gdy zamiast `==` przypadkowo używa się `=`, co prowadzi do przypisania wartości zamiast porównania. Operator `!=` oznacza nierówność i zwraca `true`, gdy dwie wartości są różne, co jest przeciwieństwem `==`. Operator `!` to negacja logiczna – przekształca wartość logiczną na jej przeciwną, np. `!true` zwraca `false`. W żadnym z tych przypadków operatory te nie służą do porównywania równości w taki sposób, jak `==`.

Pytanie 13

Który z języków programowania jest powszechnie stosowany do tworzenia interfejsów użytkownika przy użyciu XAML?

A. Objective-C
B. C++
C. C#
D. Java
C# to język programowania szeroko stosowany w tworzeniu aplikacji desktopowych, w tym do budowy interfejsów użytkownika przy użyciu XAML. XAML (Extensible Application Markup Language) to język znaczników wykorzystywany w środowisku WPF (Windows Presentation Foundation) oraz UWP (Universal Windows Platform) do projektowania graficznych interfejsów użytkownika. C# i XAML doskonale się uzupełniają, pozwalając na tworzenie nowoczesnych, interaktywnych aplikacji desktopowych, w których logika (C#) jest oddzielona od warstwy wizualnej (XAML). Dzięki tej separacji możliwe jest szybkie prototypowanie i łatwa rozbudowa aplikacji, co czyni je preferowanym wyborem dla deweloperów pracujących w ekosystemie Microsoftu.

Pytanie 14

Jakie środki ochrony zbiorowej najlepiej chronią kręgosłup w warunkach pracy biurowej?

A. Regulowanie poziomu oświetlenia w biurze
B. Ograniczenie hałasu w pomieszczeniu
C. Umieszczanie monitorów na wysokości oczu
D. Korzystanie z regulowanych krzeseł i biurek
Używanie regulowanych foteli i biurek to jeden z najlepszych sposobów na zapobieganie problemom z kręgosłupem w pracy biurowej. Ergonomiczne fotele pozwalają na dostosowanie wysokości siedziska, podparcia lędźwiowego oraz kąta nachylenia oparcia, co zapewnia optymalne wsparcie dla kręgosłupa i zmniejsza ryzyko bólu pleców. Regulowane biurka umożliwiają zmianę pozycji pracy – z siedzącej na stojącą – co redukuje obciążenie kręgosłupa i poprawia krążenie krwi. Ergonomia stanowiska pracy to kluczowy element profilaktyki zdrowotnej, który minimalizuje ryzyko dolegliwości związanych z długotrwałą pracą w jednej pozycji.

Pytanie 15

Testy mające na celu identyfikację błędów w interfejsach między modułami bądź systemami nazywane są testami

A. bezpieczeństwa
B. wydajnościowymi
C. integracyjnymi
D. jednostkowymi
Testy wydajnościowe koncentrują się na ocenie szybkości działania aplikacji pod obciążeniem, a nie na integracji komponentów. Testy bezpieczeństwa analizują podatności aplikacji na zagrożenia zewnętrzne, takie jak ataki hakerskie, i nie zajmują się bezpośrednią współpracą modułów. Testy jednostkowe sprawdzają pojedyncze funkcje lub klasy w izolacji, co oznacza, że nie wychwytują błędów w komunikacji między różnymi częściami systemu. Brak testów integracyjnych może prowadzić do problemów w działaniu aplikacji, mimo że jej poszczególne komponenty przeszły testy jednostkowe bez błędów.

Pytanie 16

Wartości składowych RGB koloru #AA41FF zapisane w systemie szesnastkowym po przekształceniu na system dziesiętny są odpowiednio

A. 170, 65, 255
B. 170, 64, 255
C. 160, 65, 255
D. 160, 64, 255
Przy przekształcaniu wartości szesnastkowych RGB na system dziesiętny łatwo popełnić błąd, bo wystarczy źle podstawić którąś cyfrę albo zmieszać kolejność. W przypadku koloru #AA41FF każda para znaków odpowiada jednej składowej: AA to czerwona, 41 to zielona, a FF to niebieska. Najczęściej błędy pojawiają się, gdy niepoprawnie zinterpretujemy cyfry szesnastkowe jako dziesiętne lub po prostu pomylimy kolejność składowych. Przykładowo, '160' w odpowiedzi zamiast '170' wynika być może z błędnego odczytania AA – bo łatwo pomylić literę A (10) z cyfrą 6 czy 0, zwłaszcza jeśli ktoś nie jest przyzwyczajony do liczb szesnastkowych. Podobnie, '64' zamiast '65' dla 41 to typowy efekt nieuwagi w liczeniu: 4*16+1 daje 65, a nie 64, co pokazuje, jak ważna jest precyzja w prostych działaniach matematycznych. Z kolei zamiana AA na 160 może świadczyć o mechanicznej zamianie liter na liczby bez uwzględnienia ich pozycji w zapisie szesnastkowym. Powszechnym błędem jest też zamiana kolejności składowych lub skupianie się tylko na końcowych cyfrach, przez co mylnie przyjmuje się, że na przykład AA to 160, bo pierwsza cyfra to 1, a nie 10. W praktyce branżowej takie niedokładności prowadzą do złych efektów wizualnych – np. kolor na stronie mocno różni się od zamierzonego lub nie pasuje do reszty projektu. Moim zdaniem takie błędy wynikają zwykle z braku nawyków w przeliczaniu systemów liczbowych. Warto zawsze pamiętać, że każda cyfra szesnastkowa ma swoją wagę, a zamiana wymaga precyzyjnego policzenia: pierwsza cyfra razy 16 plus druga cyfra. W codziennej pracy z grafiką cyfrową czy webdesignem taka pomyłka bardzo rzuca się potem w oczy użytkownikowi, więc lepiej od początku ćwiczyć dokładność niż potem szukać, gdzie zniknęła ta właściwa barwa.

Pytanie 17

Jakie są kluczowe zasady WCAG 2.0?

A. Elastyczna, prosta, przejrzysta, trwała
B. Percepcyjna, operacyjna, zrozumiała, solidna
C. Dostosowana, błyskawiczna, mobilna, dostępna
D. Ewolucyjna, interaktywna, efektywna
Niepoprawne odpowiedzi nie odzwierciedlają kluczowych zasad WCAG 2.0. Pierwsza z nich, określająca elementy jako postępowe, responsywne, efektywne, nie ujęła fundamentalnych wymogów dotyczących dostępności. Postępowe i responsywne odnoszą się bardziej do designu i wydajności strony, a nie do jej dostępności dla osób z różnymi niepełnosprawnościami. Wymagania dotyczące percepcji i interakcji z treścią są kluczowe dla WCAG 2.0, ale nie są poruszane w tej opcji. Kolejna odpowiedź wskazuje na cechy: dostosowana, szybka, mobilna, dostępna, co również nie odpowiada zasadom WCAG. Użyte terminy nie koncentrują się na dostępności treści, a bardziej na wydajności i dostosowywaniu do urządzeń mobilnych, pomijając kluczowe aspekty związane z percepcją i interaktywnością. Ostatnia niepoprawna odpowiedź, która zawiera elastyczność, prostotę, przejrzystość i trwałość, również nie odpowiada rzeczywistym zasadom WCAG. Choć te cechy są pożądane w projektowaniu stron internetowych, nie są częścią formalnych zasad WCAG, które koncentrują się na konkretnej dostępności treści dla osób z ograniczeniami. W rezultacie, te odpowiedzi nie spełniają wymaganych kryteriów dostępności.

Pytanie 18

Jakie są cechy testów interfejsu?

A. Analizują wydajność aplikacji w czasie rzeczywistym
B. Sprawdzają prawidłowość pracy elementów graficznych oraz interakcji użytkownika z aplikacją
C. Weryfikują zgodność aplikacji z przepisami prawnymi
D. Ulepszają kod aplikacji
Testowanie oprogramowania to dość szeroki temat i łatwo się w nim pogubić, szczególnie gdy myli się pojęcia związane z poszczególnymi typami testów. Testy wydajnościowe, choć bardzo ważne, skupiają się na sprawdzaniu, jak aplikacja radzi sobie z dużym obciążeniem lub podczas szybkiej pracy – mierzą na przykład czasy odpowiedzi czy zużycie zasobów, ale absolutnie nie weryfikują bezpośrednio, czy przyciski i okna działają poprawnie dla użytkownika. To zupełnie inna kategoria testów, realizowana najczęściej przy użyciu narzędzi typu JMeter lub Gatling. Z kolei weryfikowanie zgodności z przepisami prawnymi, choć brzmi poważnie, odnosi się raczej do testów zgodności (compliance), które badają, czy aplikacja spełnia wymagania, chociażby w zakresie RODO albo standardów branżowych – tutaj nie testuje się jednak interfejsu, tylko zgodność z dokumentacją i wymogami regulacyjnymi. Jeśli chodzi o ulepszanie kodu aplikacji, to jest to domena refaktoryzacji lub testów jednostkowych (unit tests), które pomagają utrzymać wysoką jakość kodu, ale nie analizują działania elementów graficznych ani doświadczenia użytkownika. Częstym błędem jest też przekonanie, że jeśli aplikacja jest szybka albo zgodna z przepisami, to z automatu jej interfejs musi być dobry – niestety, w praktyce zupełnie tak nie jest. Przegapienie testów GUI prowadzi do sytuacji, gdzie użytkownik klika w niewidoczne przyciski lub nie da się czegoś wpisać, chociaż backend działa bez zarzutu. Warto więc dobrze rozumieć zakres każdego typu testów, żeby wiedzieć, które zadania do nich należą, a które absolutnie nie są ich celem.

Pytanie 19

Które z wymienionych stanowi przykład struktury dziedziczenia?

A. Klasa Pojazd ma dziedziczenie od klasy Samochód
B. Klasa Pojazd nie dziedziczy z żadnej klasy
C. Klasa Samochód i Pojazd nie są ze sobą powiązane
D. Klasa Samochód ma dziedziczenie od klasy Pojazd
Hierarchia dziedziczenia to struktura klas, w której klasa pochodna dziedziczy właściwości i metody klasy bazowej. Klasa 'Samochód' dziedzicząca po klasie 'Pojazd' jest przykładem prawidłowej hierarchii dziedziczenia – klasa 'Samochód' rozszerza klasę 'Pojazd', dziedzicząc ogólne właściwości pojazdu, takie jak prędkość czy typ silnika. Dziedziczenie umożliwia rozszerzanie istniejącej funkcjonalności bez konieczności przepisywania tego samego kodu, co jest jednym z fundamentów programowania obiektowego.

Pytanie 20

Który z wymienionych dysków oferuje najszybszy dostęp do danych?

A. SSD NVMe PCIe 3.0, prędkość odczytu do 3500 MB/s
B. HDD 7200 RPM, SATA III, 64 MB Cache
C. HDD 5400 RPM, SATA II, 32 MB Cache
D. SSD SATA III, prędkość odczytu do 550 MB/s
Odpowiedź wskazująca na SSD NVMe PCIe 3.0 jako najszybszy dysk do odczytu danych jest zgodna z obecnymi standardami technologii przechowywania. Dyski SSD (Solid State Drive) korzystają z pamięci flash, co pozwala na znacznie szybszy dostęp do danych w porównaniu do tradycyjnych dysków HDD (Hard Disk Drive), które działają na zasadzie mechanicznych ruchomych elementów. Dyski NVMe (Non-Volatile Memory Express) są szczególnie wydajne, ponieważ wykorzystują interfejs PCIe (Peripheral Component Interconnect Express), co umożliwia znacznie wyższe prędkości transferu danych. W przypadku SSD NVMe PCIe 3.0, prędkość odczytu może osiągać do 3500 MB/s, co jest znaczącą różnicą w porównaniu do prędkości odczytu w dyskach HDD i SSD SATA. Przykładowo, w zastosowaniach takich jak edycja wideo, renderowanie grafiki 3D czy gry komputerowe, wyższa prędkość odczytu przekłada się na szybsze ładowanie danych i lepszą wydajność systemu. Standardy SATA III dla HDD również mają swoje ograniczenia, ponieważ maksymalna teoretyczna prędkość transferu wynosi 6 Gb/s, co jest dalekie od osiągów oferowanych przez NVMe. Dlatego SSD NVMe PCIe 3.0 jest zdecydowanym liderem w kontekście wydajności odczytu danych w porównaniu do pozostałych opcji.

Pytanie 21

Jakie jest oznaczenie komentarza wieloliniowego w języku Java?

A. """ ... """
B. <!-- ... -->
C. // ... //
D. /* ... */
Wielu początkujących programistów myli składnię komentarzy w różnych językach programowania, co jest całkiem naturalne – szczególnie jeśli ktoś ma styczność z wieloma technologiami naraz albo przechodzi z jednego języka na drugi. W przypadku Javy tylko zapis /* ... */ pozwala na tworzenie komentarzy wieloliniowych, czyli takich, które rozciągają się na kilka kolejnych wierszy kodu. Zapis <!-- ... --> jest charakterystyczny dla języków znaczników, takich jak HTML czy XML. Java nie rozpoznaje tego typu komentarza – jeśli spróbujesz go użyć, kompilator po prostu się „zgubi” i potraktuje to jako błąd składni, a nie komentarz. Z kolei // ... // to pomieszanie dwóch różnych rzeczy: w Java używamy podwójnego ukośnika (//) do komentarzy jednoliniowych, czyli takich, które kończą się na końcu danej linii. Powielenie ukośników po obu stronach nie ma żadnego znaczenia dla interpretera Javy i nie działa w praktyce. Natomiast zapis z trzema cudzysłowami """ ... """, choć jest popularny np. w Pythonie do komentowania bloków tekstu lub docstringów, w języku Java nie jest rozpoznawany nawet jako komentarz – kompilator potraktuje taki fragment jako błąd składni lub nieoczekiwany string w kodzie. Niestety, takie błędy wynikają często z przyzwyczajeń wyniesionych z innych języków, co jest typowym problemem przy nauce nowych technologii. Z mojego punktu widzenia warto od początku rozróżniać te różnice, bo potem przychodzi mniej przykrych niespodzianek na etapie kompilowania czy wdrażania aplikacji. Praktyka pokazuje, że nawet doświadczeni programiści czasami odruchowo stosują nieprawidłową notację, szczególnie gdy edytują kod w różnych językach. W Javie zawsze trzymaj się więc zapisu /* ... */ dla komentarzy wieloliniowych i nie próbuj używać formatów z innych ekosystemów – to po prostu tutaj nie zadziała.

Pytanie 22

Które z wymienionych praw autorskich nie wygasa po pewnym czasie?

A. Licencje wolnego oprogramowania
B. Autorskie prawa majątkowe
C. Autorskie prawa osobiste
D. Prawa pokrewne
Autorskie prawa majątkowe wygasają zazwyczaj po 70 latach od śmierci autora, co oznacza, że po tym czasie utwory przechodzą do domeny publicznej. Prawa pokrewne, które dotyczą m.in. artystów wykonawców i producentów fonogramów, mają ograniczony czas trwania (zwykle 50 lat od publikacji). Licencje wolnego oprogramowania, takie jak GNU GPL, również podlegają określonym warunkom czasowym i mogą wygasnąć lub zostać zmienione, jeśli autor zdecyduje się na aktualizację licencji.

Pytanie 23

Przedstawione w filmie działania wykorzystują narzędzie

A. generatora GUI przekształcającego kod do języka XAML
B. generatora kodu java
C. debuggera analizującego wykonujący kod
D. kompilatora dla interfejsu graficznego
Patrząc na wszystkie dostępne opcje, łatwo się pomylić, bo terminologia może być trochę podchwytliwa. Debugger analizujący wykonujący kod rzeczywiście jest kluczowym narzędziem w pracy programisty, ale jego zadaniem jest szukanie błędów i obserwowanie działania programu w czasie rzeczywistym, a nie generowanie kodu czy interfejsów. Myślę, że sporo osób utożsamia narzędzia developerskie z debuggerem, bo to jedno z najczęściej używanych rozwiązań – jednak tutaj akurat nie ma on nic wspólnego z przekształcaniem kodu do XAML-a. Generator kodu Java brzmi sensownie, jeśli ktoś pracuje więcej w środowiskach Javy, ale w tym przypadku mówimy o ekosystemie .NET i XAML-u, a Java ma zupełnie inne formaty i narzędzia (np. FXML dla JavaFX, ale to zupełnie inna bajka). Generator GUI przekształcający kod do języka XAML to narzędzie dedykowane platformie Microsoftu, bo XAML funkcjonuje właśnie w tych technologiach. Ostatnia odpowiedź, czyli kompilator dla interfejsu graficznego, to trochę pomieszanie pojęć – kompilator rzeczywiście tłumaczy kod na wykonywalny plik (np. EXE), ale nie jest narzędziem służącym do generowania czy przekształcania opisów interfejsów graficznych. Sporo osób może mieć tendencję do mylenia generatorów z kompilatorami, bo oba „tworzą coś automatycznie”, ale ich przeznaczenie jest zupełnie inne. Moim zdaniem najważniejsze to rozumieć, że generatory GUI ułatwiają życie, pozwalając szybko przenieść projekt interfejsu do kodu XAML, a reszta narzędzi ma zupełnie inne zadania. To rozróżnienie jest naprawdę kluczowe w branży.

Pytanie 24

Jakie funkcje realizuje polecenie "git clone"?

A. Tworzy lokalną kopię już istniejącego repozytorium
B. Rejestruje zmiany w historii repozytorium
C. Łączy dwa branche w repozytorium
D. Usuwa zdalne repozytorium
Wielu początkujących użytkowników Gita myli funkcje podstawowych poleceń, co jest zupełnie zrozumiałe – Git bywa momentami dość nieintuicyjny. Zacznijmy od polecenia "git clone". Ono wcale nie służy do łączenia branchy – od tego jest "git merge" albo nowsze "git rebase", które pozwalają na integrację zmian z różnych gałęzi projektu. Łączenie branchy polega bardziej na synchronizacji pracy kilku osób i rozwiązywaniu konfliktów, a nie na kopiowaniu repozytorium. Z kolei rejestrowanie zmian w historii repozytorium to zadanie "git commit" – dopiero to polecenie zapisuje stan projektu w historii. Wiele osób sądzi, że "git clone" zapisuje też zmiany, ale ono tylko pobiera już istniejącą historię. Usuwanie zdalnego repozytorium to zupełnie inna bajka – Git nawet nie daje takiego polecenia jak "git clone" do usuwania czegokolwiek po stronie serwera, bo to byłoby niebezpieczne i niezgodne z ideą bezpieczeństwa danych. Często spotykam się z błędnym rozumieniem terminologii: „klonowanie” kojarzy się niektórym z kopiowaniem gałęzi albo synchronizacją, ale w rzeczywistości chodzi o zrobienie pełnej lokalnej kopii całego repozytorium ze wszystkimi danymi. Kluczowe jest, żeby rozumieć każdy etap pracy z Gitem: clone do pobrania repo, pull do aktualizacji, commit do rejestrowania zmian, merge do łączenia branchy. Nie mieszaj tych pojęć, bo prowadzi to do niepotrzebnych błędów i nieporozumień w pracy zespołowej. Dobrze mieć z tyłu głowy, że każde z tych poleceń realizuje zupełnie inną funkcję i jest częścią większego procesu zarządzania wersjami kodu w projekcie.

Pytanie 25

Jak określa się proces, w trakcie którego klasa przejmuje właściwości innej klasy w programowaniu obiektowym?

A. Polimorfizm
B. Hermetyzacja
C. Dziedziczenie
D. Abstrakcja
Dziedziczenie to kluczowa cecha programowania obiektowego (OOP), która pozwala jednej klasie (klasie pochodnej) przejmować cechy i zachowania innej klasy (klasy bazowej). Dzięki dziedziczeniu można wielokrotnie wykorzystywać kod, co prowadzi do większej modularności i zmniejszenia redundancji. Dziedziczenie umożliwia rozszerzanie funkcjonalności klas bazowych poprzez dodawanie nowych metod lub modyfikowanie istniejących, bez konieczności ingerencji w oryginalny kod. Przykład w C++: `class Pojazd { ... }; class Samochod : public Pojazd { ... };` – `Samochod` dziedziczy wszystkie publiczne i chronione (protected) elementy klasy `Pojazd`.

Pytanie 26

Co to jest wskaźnik w języku C?

A. Zmienna przechowująca adres pamięci
B. Funkcja do dynamicznej alokacji pamięci
C. Zmienna przechowująca wartość logiczną
D. Typ danych do zapisywania tekstów
Zmienne przechowujące wartości logiczne to typ bool (np. true/false) i nie mają związku z wskaźnikami. Funkcje dynamicznie alokujące pamięć, takie jak malloc(), zwracają adresy, ale same nie są wskaźnikami. Typ danych do przechowywania tekstów w C to tablica znaków (char[]) lub wskaźnik do char, ale to nie to samo co wskaźnik w sensie ogólnym, który może wskazywać na dowolny typ danych.

Pytanie 27

Jak nazywa się wzorzec projektowy, do którego odnosi się ta definicja?

Wzorzec projektowy należący do grupy wzorców strukturalnych. Służy do ujednolicenia dostępu do złożonego systemu poprzez wystawienie uproszczonego, uporządkowanego interfejsu programistycznego, który ułatwia jego użycie.
Źródło Wikipedia. Wolna encyklopedia
A. Fasada
B. Prototyp
C. Dekorator
D. Kompozyt
Wzorzec projektowy Fasada jest jednym z kluczowych wzorców strukturalnych używanych w inżynierii oprogramowania. Jego głównym celem jest uproszczenie i ujednolicenie interakcji z złożonym systemem poprzez wystawienie uproszczonego i uporządkowanego interfejsu programistycznego. Fasada ukrywa złożoność systemu, zapewniając jednolity punkt dostępu do zestawu funkcji lub klas. W praktyce fasada jest używana do tworzenia prostych interfejsów dla bardziej złożonych bibliotek lub systemów, co ułatwia ich użycie przez programistów. Na przykład w systemie bankowym fasada może zintegrować różne usługi jak autoryzacja płatności, zarządzanie kontami i generowanie wyciągów, oferując jeden interfejs do ich obsługi. Fasada wspiera dobre praktyki poprzez promowanie niskiej zależności i wysokiej spójności. Zmiany w wewnętrznym działaniu systemu są mniej widoczne na zewnątrz, co zwiększa elastyczność systemu. Fasada jest zgodna z zasadą projektowania SOLID, zwłaszcza z zasadą pojedynczej odpowiedzialności, umożliwiając lepsze zarządzanie kodem i jego utrzymanie. Jej użycie jest powszechne w systemach złożonych, gdzie upraszczanie interfejsów jest kluczowe dla efektywności programistycznej i skalowalności systemu.

Pytanie 28

Jakie z wymienionych funkcji są typowe dla narzędzi służących do zarządzania projektami?

A. Nadzorowanie postępu realizacji
B. Przeprowadzanie analizy statystycznej
C. Opracowywanie diagramów przepływu
D. Tworzenie interfejsu użytkownika
Tworzenie diagramów przepływu to funkcja wspierająca dokumentację i analizę procesów, ale nie jest podstawowym narzędziem monitorowania postępów prac. Projektowanie interfejsu użytkownika dotyczy tworzenia atrakcyjnych wizualnie i funkcjonalnych aplikacji, lecz nie odnosi się bezpośrednio do zarządzania projektami. Analiza statystyczna to ważny element podejmowania decyzji na podstawie danych, jednak jej celem jest przetwarzanie informacji, a nie zarządzanie zadaniami i postępem projektu.

Pytanie 29

Jakie są kluczowe etapy realizacji projektu programistycznego?

A. Planowanie, analiza, implementacja, wdrożenie
B. Projektowanie, testowanie, aktualizacja, implementacja
C. Planowanie, projektowanie, debugowanie, konserwacja
D. Analiza, implementacja, testowanie, aktualizacja
Wiele osób myśli, że wystarczy skupić się na kodzie czy testach i sukces przyjdzie sam, ale w praktyce kluczowe jest zachowanie właściwej sekwencji i kompletności działań. Często spotykam się z przekonaniem, że projektowanie albo debugowanie są najważniejszymi krokami, jednak bez wcześniejszego gruntownego planowania i analizy trudno mówić o efektywności czy przewidywalności rezultatów. Przykładowo, debugowanie to bardzo istotny element pracy programisty, ale samo w sobie nie stanowi etapu realizacji projektu – jest raczej czynnością wykonywaną w toku implementacji i testowania. Z kolei aktualizacja i konserwacja, choć ważne, zaliczają się już do utrzymania systemu po wdrożeniu, a nie do pierwotnego cyklu tworzenia oprogramowania. W niektórych odpowiedziach zabrakło chociażby analizy wymagań, co jest podstawowym etapem według standardów takich jak ISO/IEC/IEEE 12207 czy wytycznych PMBOK. Pominięcie wdrożenia lub zamiana jego kolejności z innym etapem, jak projektowanie albo testowanie, prowadzi do problemów z odpowiedzialnością za przekazanie produktu końcowego. Również połączenie implementacji z aktualizacją to pomieszanie faz projektowych z fazami utrzymania. Takie uproszczenia wynikają często z mylenia faz samego developmentu z późniejszymi procesami eksploatacji. W praktyce, żeby uniknąć błędów takich jak niedopracowana architektura czy chaos przy wdrożeniu, trzeba konsekwentnie stosować pełną sekwencję: planowanie, analiza, implementacja, a na końcu wdrożenie. To jest podejście zgodne i z klasycznym waterfall, i z nowszymi praktykami agile, gdzie nawet jeśli fazy się zazębiają, wciąż mają swoje miejsce. Z mojego doświadczenia, skracanie lub pomijanie tych etapów to prosta droga do kosztownych poprawek i niezadowolenia klienta, dlatego warto je znać i stosować świadomie.

Pytanie 30

Co to jest debouncing w JavaScript?

A. Metoda usuwania zduplikowanych zdarzeń w kodzie
B. Proces optymalizacji kodu JavaScript podczas kompilacji
C. Mechanizm zarządzania pamięcią dla zmiennych globalnych
D. Technika ograniczająca częstotliwość wywoływania funkcji poprzez opóźnienie jej wykonania
Błędne odpowiedzi na to pytanie wynikają z nieporozumienia dotyczącego funkcji i technik w JavaScript. Wspomnienie o metodzie usuwania zduplikowanych zdarzeń w kodzie sugeruje mylne rozumienie debouncingu, który nie ma na celu eliminacji zdarzeń, ale kontrolę nad ich częstością wywoływania. Terminy związane z eliminacją zduplikowanych zdarzeń odnoszą się raczej do technik takich jak throttling, które również ograniczają liczbę wywołań, ale w sposób, który różni się od debouncingu. Proces optymalizacji kodu JavaScript podczas kompilacji to zupełnie inny temat, dotyczący narzędzi takich jak minifikatory i kompilatory, które nie mają związku z zarządzaniem zdarzeniami. Ponadto, mechanizm zarządzania pamięcią dla zmiennych globalnych to odrębna kwestia, dotycząca zarządzania pamięcią w JavaScript, a nie techniki związanej z wywoływaniem funkcji. Właściwe zrozumienie debouncingu wymaga uwzględnienia kontekstu zdarzeń oraz ich wpływu na wydajność aplikacji, co jest istotnym zagadnieniem w nowoczesnym programowaniu webowym. Typowe błędy myślowe prowadzące do mylnego wnioskowania mogą obejmować utożsamianie różnych technik programistycznych lub mylenie pojęć związanych z optymalizacją i zarządzaniem zdarzeniami.

Pytanie 31

W jednostce centralnej, za obliczenia na liczbach zmiennoprzecinkowych odpowiada

A. AU
B. FPU
C. IU
D. ALU
FPU, czyli Floating Point Unit, to specjalizowany układ w jednostce centralnej, który zajmuje się właśnie obliczeniami na liczbach zmiennoprzecinkowych. Moim zdaniem bardzo często się o tym zapomina, bo „procesor to procesor”, a tu jednak mamy konkretne podzespoły odpowiadające za różne rodzaje operacji. Współczesne CPU praktycznie zawsze mają wbudowaną FPU, bo operacje na zmiennych typu float czy double są na porządku dziennym, szczególnie w grafice komputerowej, symulacjach fizycznych czy obliczeniach naukowych. Przykładowo, FPU jest niezbędna podczas renderowania grafiki 3D albo nawet przy zwykłych obliczeniach matematycznych, które wymagają dużej precyzji. Standardy branżowe jak IEEE 754 określają sposób reprezentacji i przetwarzania liczb zmiennoprzecinkowych, a FPU jest zaprojektowana właśnie pod takie standardy, żeby wyniki były przewidywalne i zgodne ze światowymi normami. Dla mnie to jest ciekawe, bo chociaż FPU działa raczej „w tle”, to bez niej większość zaawansowanych aplikacji praktycznie by nie działała albo byłaby po prostu niewyobrażalnie wolna. Czasem w kontekście architektury komputerów mówi się nawet o osobnych układach FPU, które kiedyś były dokładane do procesorów, zanim trafiły bezpośrednio do ich wnętrza. Warto o tym pamiętać, bo to właśnie FPU pozwala komputerom liczyć z dużą dokładnością i szybkością wartości, których zwykła ALU by nie ogarnęła.

Pytanie 32

Przyjmując, że opisana hierarchia klas właściwie odzwierciedla figury geometryczne i każda figura ma zdefiniowaną metodę do obliczania pola, to w której klasie można znaleźć deklarację metody liczPole()?

Ilustracja do pytania
A. figura
B. trapez
C. trójkąt
D. czworokąt
Częstym błędem przy projektowaniu hierarchii klas figur geometrycznych jest umieszczanie kluczowych metod, takich jak liczPole(), w zbyt szczegółowych klasach, np. w klasie trapez, czworokąt czy trójkąt. To prowadzi do powielania kodu oraz utrudnia późniejszy rozwój aplikacji. Jeżeli metoda liczPole() znalazłaby się w którejś z tych klas, to każda z nich miałaby własną, niezależną implementację, bez jednego, wspólnego punktu odniesienia. Zdarza się, że osoby początkujące traktują każdą figurę z osobna, próbując umieścić jej logikę tylko w konkretnej klasie, ale to prosta droga do chaosu i dublowania kodu. Standardy branżowe i literatura przedmiotu (np. wzorce projektowe GoF) jasno wskazują, że w takich przypadkach warto korzystać z tzw. abstrakcji – czyli deklarować abstrakcyjną metodę w klasie bazowej, a implementować ją w klasach potomnych. Pozwala to na spójność interfejsu i wykorzystanie polimorfizmu – kluczowej cechy nowoczesnych języków obiektowych. Umieszczając liczPole() na poziomie np. czworokąta, tracimy możliwość wymuszania implementacji tej metody w innych figurach, jak trójkąt czy koło, co jest poważnym ograniczeniem. Także z praktycznego punktu widzenia – gdyby kod miał być rozwijany przez większy zespół albo miał być podstawą do dalszych rozszerzeń (np. nowe typy figur), to scentralizowana deklaracja metody w klasie figura jest rozwiązaniem najbezpieczniejszym, najbardziej elastycznym i najłatwiejszym w utrzymaniu. Praktyka pokazuje, że trzymanie się tych zasad po prostu się opłaca i minimalizuje potencjalne błędy w przyszłości.

Pytanie 33

Która z poniższych nie jest cechą architektury mikroserwisów?

A. Wspólna baza danych dla wszystkich usług
B. Odporność na awarie pojedynczych komponentów
C. Autonomia zespołów rozwijających poszczególne usługi
D. Niezależne wdrażanie poszczególnych usług
Architektura mikroserwisów opiera się na praktykach, które umożliwiają wzrost skalowalności, elastyczności oraz odporności systemu. Wspólna baza danych dla wszystkich usług, będąca jedną z zaproponowanych odpowiedzi, jest sprzeczna z tymi fundamentalnymi zasadami. Utrzymywanie centralnej bazy danych prowadzi do sytuacji, gdzie zmiany w jednym mikroserwisie mogą mieć niepożądane konsekwencje dla innych, co z kolei zmniejsza niezależność każdej usługi. W mikroserwisach kluczowe jest, aby każda usługa miała swoje własne źródło danych, co pozwala na decoupling, czyli luźne powiązanie między komponentami. Ponadto, w architekturze mikroserwisów, każda usługa powinna być w stanie działać i być wdrażana niezależnie, co jest niemożliwe w przypadku korzystania z jednej bazy danych, ponieważ wszelkie zmiany wymagałyby zsynchronizowanego podejścia. Kolejnym aspektem jest odporność na awarie, która również ulega osłabieniu w przypadku wspólnej bazy danych. Jeśli baza danych ulegnie awarii, wszystkie usługi korzystające z niej są jednocześnie dotknięte problemem, co jest sprzeczne z koncepcją mikroserwisów, gdzie pojedyncze komponenty powinny być zdolne do działania niezależnie. Wreszcie, autonomia zespołów jest również podważana przez wspólną bazę danych, ponieważ zespoły nie mogą pracować równolegle nad swoimi usługami, a zmiany są wymuszone przez współzależności. Dlatego stosowanie wspólnej bazy danych jest jednym z najczęstszych błędów, który może prowadzić do problemów w projektowaniu i zarządzaniu architekturą mikroserwisów.

Pytanie 34

Jakie metody umożliwiają przesyłanie danych z serwera do aplikacji front-end?

A. formatu JSON
B. biblioteki jQuery
C. protokołem SSH
D. metody POST
Jest taka sprawa z jQuery – chociaż to super narzędzie do manipulacji DOM i pracy z asynchronicznymi żądaniami HTTP, to jednak nie jest formatem danych. Tak, jQuery świetnie działa z AJAX-em, ale nie definiuje, jak dane powinny być przesyłane. Jak już używasz jQuery do przesyłania danych, to potrzebujesz formatu, na przykład JSON. Dlatego ta odpowiedź jest niepoprawna. Metoda POST umożliwia przesyłanie danych do serwera w protokole HTTP, ale sama w sobie nie mówi, w jakim formacie te dane będą przesyłane. Można używać różnych formatów, w tym JSON, ale sama metoda POST to za mało. A SSH, czyli Secure Shell, to protokół do bezpiecznego logowania i zdalnego zarządzania systemami, a nie do przesyłania danych między aplikacjami webowymi a serwerem. Dlatego tu też mamy błąd. Wszystkie te technologie są ważne, ale nie mówią o przesyłaniu danych w kontekście front-endu tak, jak robi to JSON.

Pytanie 35

Która z poniższych nie jest zasadą czystego kodu (clean code)?

A. Jedna odpowiedzialność funkcji
B. Maksymalna złożoność funkcji
C. Samodokumentujący się kod
D. Konsekwentne nazewnictwo
Wszystkie podane odpowiedzi odzwierciedlają zasady czystego kodu, z wyjątkiem maksymalnej złożoności funkcji, która nie jest akceptowaną normą. Samodokumentujący się kod to istotny element, który sprawia, że kod staje się bardziej przystępny i łatwiejszy do zrozumienia dla innych programistów. Użycie odpowiednich nazw zmiennych oraz struktura kodu, która jasno pokazuje, co dany fragment kodu wykonuje, są nieodłącznymi elementami dobrego stylu programowania. Pojęcie jednej odpowiedzialności funkcji (Single Responsibility Principle) utożsamiane jest z tym, że każda funkcja powinna realizować jedną, jasno określoną funkcję. To z kolei prowadzi do lepszej modularności kodu oraz ułatwia jego testowanie i ponowne wykorzystanie. Konsekwentne nazewnictwo zapewnia, że kody są spójne w całym projekcie, co minimalizuje ryzyko nieporozumień i błędów. Typowe błędy myślowe prowadzące do błędnych wniosków mogą wynikać z mylnego przekonania, że złożoność kodu jest oznaką jego zaawansowania. W rzeczywistości, prostota i klarowność są kluczowe dla efektywności programowania i utrzymania jakości kodu w dłuższej perspektywie.

Pytanie 36

Z podanej definicji pola licznik można wywnioskować, iż

class MojaKlasa
{
    private static int licznik;
    ...
A. bieżąca wartość pola jest wspólna dla wszystkich instancji klasy
B. pole nie może być zmieniane w kodzie klasy
C. bieżąca wartość pola jest wspólna dla wszystkich instancji klasy i nie może być zmieniana
D. pole jest związane z określoną instancją klasy i jego wartość jest unikalna tylko dla tej instancji
Warto się chwilę zatrzymać i przeanalizować, skąd biorą się błędne przekonania dotyczące pól statycznych. Bardzo częstym nieporozumieniem jest utożsamianie słowa static z czymś „niezmiennym” albo uniemożliwiającym modyfikacje. Tymczasem static oznacza tyle, że pole nie jest związane z pojedynczym obiektem, tylko z całą klasą – czyli wszystkie obiekty tej klasy dzielą jedną, wspólną wartość licznik. To nie jest tak, że static czyni pole stałym – żeby pole było niezmienne, potrzeba słowa kluczowego final (w Javie), a tutaj go ewidentnie nie ma. Często osoby początkujące mylą static z final i stąd pojawia się przekonanie, że pole nie może być modyfikowane – co nie jest prawdą. Równie błędne jest zakładanie, że każde pole, które nie jest static, jest automatycznie unikalne per instancja. Gdybyśmy usunęli static z definicji licznik, wtedy rzeczywiście każda instancja MojaKlasa miałaby swoją własną wersję tej zmiennej, ale w tym przypadku wszystkie obiekty współdzielą tę samą wartość. Jeszcze inny błąd to przekonanie, że pole prywatne (private) nie może być zmieniane w kodzie klasy – w rzeczywistości private ogranicza dostęp do pola tylko do wnętrza klasy, ale metody tej klasy mają pełne prawo je modyfikować. Tak więc, patrząc z perspektywy dobrych praktyk programistycznych i samej składni, static to po prostu cecha, która decyduje o zakresie współdzielenia pola pomiędzy instancjami, a nie o jego niezmienności czy widoczności na zewnątrz. Moim zdaniem kluczowe jest wyciągnięcie z tego wniosku, że static to współdzielenie, a nie blokada zmian – i na tym polega istota poprawnej odpowiedzi w tym pytaniu.

Pytanie 37

Jaki protokół komunikacyjny jest używany w aplikacjach IoT (Internet of Things)?

A. SMTP
B. FTP
C. MQTT
D. HTTP
Protokół MQTT (Message Queuing Telemetry Transport) jest jednym z najczęściej używanych protokołów w aplikacjach Internetu Rzeczy (IoT). Jest to lekki protokół komunikacyjny zaprojektowany z myślą o ograniczonych zasobach urządzeń oraz niskiej przepustowości połączeń. Jego architektura opiera się na modelu publikacja-subskrypcja, co sprawia, że idealnie nadaje się do komunikacji między wieloma urządzeniami. W praktyce, MQTT jest wykorzystywany w różnych aplikacjach, takich jak monitorowanie czujników, zdalne sterowanie urządzeniami czy zarządzanie inteligentnymi domami. Dzięki zastosowaniu mechanizmów QoS (Quality of Service), MQTT zapewnia niezawodność dostarczania wiadomości, co jest kluczowe w krytycznych zastosowaniach przemysłowych. Co więcej, jest on wspierany przez wiele platform IoT, takich jak AWS IoT, Google Cloud IoT oraz Azure IoT, co czyni go standardem branżowym. W praktyce inżynierowie IoT często wybierają MQTT ze względu na jego niskie opóźnienia i niski narzut na zasoby systemowe, co przekłada się na efektywność działania systemów IoT.

Pytanie 38

Jaki typ złośliwego oprogramowania funkcjonuje w tle, zbierając dane o wprowadzanych hasłach?

A. Spyware
B. Adware
C. Trojan
D. Keylogger
Trojan, spyware i adware to inne rodzaje złośliwego oprogramowania, które różnią się od keyloggerów. Trojan to taki program, który niby jest legalny, ale tak naprawdę wprowadza złośliwe kody do systemu. Nie zawsze oczywiście rejestruje naciśnięcia klawiszy, ale potrafi wpuścić inne złośliwe oprogramowanie, które już działa jak keylogger. Spyware zbiera dane o użytkownikach, ale to bardziej pasywne działanie, więc nie zawsze chodzi o klawisze. Adware z kolei wyświetla uciążliwe reklamy, jego celem jest zarabianie na reklamach. Mimo że adware może zbierać dane, to nie jest tak groźne jak keyloggery, które naprawdę potrafią przechwycić hasła i inne poufne informacje. Każdy z tych typów malware ma swoje unikalne cechy i sposoby działania.

Pytanie 39

Który z wymienionych mechanizmów umożliwia ograniczenie dostępu do wybranych sekcji aplikacji webowej?

A. Mechanizm renderowania treści
B. Formularze dynamiczne
C. Pliki CSS statyczne
D. System logowania i kontroli dostępu
Dynamiczne formularze umożliwiają interakcję użytkownika z aplikacją, np. przesyłanie danych, ale same w sobie nie zapewniają mechanizmów autoryzacji ani ograniczenia dostępu. Statyczne pliki CSS odpowiadają za wygląd i stylizację strony internetowej, nie mają jednak wpływu na mechanizmy kontroli dostępu. Mechanizm renderowania treści służy do wyświetlania elementów interfejsu i generowania dynamicznych stron, ale nie pełni roli systemu logowania ani autoryzacji użytkowników.

Pytanie 40

Który z przedstawionych poniżej przykładów ilustruje prawidłową deklarację zmiennej typu całkowitego w języku C++?

A. bool liczba;
B. float liczba;
C. int liczba;
D. char liczba;
Deklaracja `float liczba;` oznacza zmienną przechowującą liczby zmiennoprzecinkowe, a nie całkowite. `char liczba;` definiuje zmienną znakową, przechowującą pojedynczy znak, np. 'A' lub 'z'. Deklaracja `bool liczba;` odnosi się do zmiennej logicznej, która może przechowywać tylko wartości `true` lub `false`. Każdy z tych typów ma swoje zastosowanie, ale żaden z nich nie jest równoważny zmiennej typu całkowitego (int).