Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 6 maja 2026 08:49
  • Data zakończenia: 6 maja 2026 09:06

Egzamin zdany!

Wynik: 23/40 punktów (57,5%)

Wymagane minimum: 20 punktów (50%)

Nowe
Analiza przebiegu egzaminu- sprawdź jak rozwiązywałeś pytania
Pochwal się swoim wynikiem!
Szczegółowe wyniki:
Pytanie 1

W frameworkach do budowy aplikacji mobilnych lub desktopowych znajduje zastosowanie wzorzec MVVM, oznaczający Model-View-ViewModel. Te podejście do programowania oznacza, że

A. kontrolki i widoki interfejsu użytkownika są zintegrowane z logiką aplikacji
B. w aplikacji obecny jest jedynie interfejs użytkownika
C. interfejs użytkownika i logika aplikacji są umieszczone w jednym pliku
D. interfejs użytkownika oraz logika aplikacji są oddzielone
Wzorzec MVVM, czyli Model-View-ViewModel, jest jednym z kluczowych podejść w architekturze aplikacji, szczególnie w kontekście aplikacji mobilnych i desktopowych. Zakłada on wyraźne rozdzielenie logiki aplikacji (Model) od warstwy prezentacji (View), z pomocą komponentu ViewModel, który działa jako mediator. Dzięki temu programiści mogą łatwiej zarządzać kodem, testować poszczególne komponenty oraz wprowadzać zmiany w interfejsie użytkownika bez wpływu na logikę aplikacji. Przykładem zastosowania MVVM jest framework WPF (Windows Presentation Foundation), w którym dane są wiązane do kontrolek w interfejsie użytkownika, co pozwala na automatyczną aktualizację widoków w przypadku zmian w modelu. Standardy takie jak Data Binding w WPF oraz Reactive Programming w Xamarin i Avalonia, pokazują, jak MVVM ułatwia rozwój aplikacji poprzez separację odpowiedzialności, co prowadzi do większej przejrzystości kodu i łatwości w jego utrzymywaniu.

Pytanie 2

Po uruchomieniu poniższego kodu w języku C++ w konsoli pojawi się ciąg liczb:

int a = 1;
while (a++ < 6) {
    cout << a << " ";
}
A. 1 2 3 4 5
B. 1 2 3 4 5 6
C. 2 3 4 5 6 7
D. 2 3 4 5 6
Z tego co widzę, najczęstsze nieporozumienia związane z tym pytaniem wynikają z mylenia sposobu działania operatora postinkrementacji z preinkrementacją, a także niezrozumienia kolejności wykonania instrukcji w pętli. W tym przykładzie zapis a++ < 6 sprawia, że najpierw do warunku trafia obecna wartość a (sprawdzana jest 1 < 6), dopiero potem następuje zwiększenie a do 2. Wewnątrz pętli wypisywana jest już ta nowa wartość. To może być mylące, bo ktoś mógłby założyć, że najpierw następuje inkrementacja, a potem sprawdzenie warunku – tak by było przy ++a < 6, ale nie przy a++ < 6. Kolejna rzecz: wybierając odpowiedzi typu 1 2 3 4 5 6 lub 2 3 4 5 6 7, można nieświadomie przyjąć, że pętla wypisuje także wartości początkową lub końcową poza zakresem warunku, co w tym kodzie nie ma miejsca. Częstym błędem jest też założenie, że warunek a++ < 6 przepuszcza do wypisania wartość 6 lub nawet 7, ale w rzeczywistości przy a równym 6 warunek staje się fałszywy i pętla się kończy. Takie subtelności są bardzo istotne w codziennym programowaniu, szczególnie kiedy pracuje się z pętlami sterującymi wykonywaniem algorytmów czy przetwarzaniem danych w tablicach. Praktyka pokazuje, że przeoczenie różnic między post- i pre-inkrementacją prowadzi do bugów, które często trudno namierzyć, a ich efekty mogą wychodzić dopiero po dłuższym czasie. Moim zdaniem najlepiej przyjąć zasadę, by czytać kod spokojnie linijka po linijce i zwracać uwagę na to, co dzieje się z każdą zmienną w każdej iteracji. Uczy to logicznego myślenia i pozwala lepiej rozumieć mechanizmy języka – a to podstawa do pisania solidnego, przewidywalnego kodu.

Pytanie 3

Jakie wartości może przyjąć zmienna typu boolean?

A. trzy dowolne liczby naturalne
B. O oraz każdą liczbę całkowitą
C. true, false
D. 1, -1
Zmienna typu logicznego (boolowskiego) w językach programowania, takich jak C++, Java czy Python, może przyjmować tylko dwie wartości: true (prawda) oraz false (fałsz). Te wartości są fundamentalne w logice komputerowej, ponieważ umożliwiają podejmowanie decyzji oraz kontrolowanie przepływu programu poprzez struktury warunkowe, takie jak instrukcje if, while czy for. Na przykład, w języku Python, tworząc zmienną logiczną, możemy użyć operatorów porównania, aby określić, czy dwie wartości są równe: is_equal = (5 == 5), co ustawia is_equal na true. Zmienne logiczne są zdefiniowane w standardach programowania, takich jak IEEE 754 dla reprezentacji liczb zmiennoprzecinkowych, gdzie wartość logiczna jest kluczowa dla operacji porównawczych. Dobrze zrozumiana logika boolowska jest niezbędna dla programistów, ponieważ stanowi podstawę algorytmu decyzyjnego oraz wpływa na efektywność kodu.

Pytanie 4

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. bieżąca wartość pola jest wspólna dla wszystkich instancji klasy i nie może być zmieniana
C. pole jest związane z określoną instancją klasy i jego wartość jest unikalna tylko dla tej instancji
D. pole nie może być zmieniane w kodzie klasy
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 5

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

A. char liczba;
B. int liczba;
C. bool liczba;
D. float liczba;
W języku C++ zmienna typu całkowitego jest deklarowana za pomocą słowa kluczowego `int`. Przykładowa poprawna deklaracja to `int liczba;`, co oznacza, że `liczba` jest zmienną, która może przechowywać wartości całkowite, takie jak 1, 42 lub -15. Deklarowanie zmiennych w C++ pozwala na statyczne typowanie, co oznacza, że każda zmienna ma określony typ i nie może przechowywać wartości innego typu. Dzięki temu kod jest bardziej przejrzysty i mniej podatny na błędy związane z niezgodnością typów.

Pytanie 6

Pętla przedstawiona w zadaniu działa na zmiennej typu string o nazwie ciag. Jej celem jest:

int i = 0;
while (ciag[i] != 0)  {
    if (ciag[i] > 96 && ciag[i] < 123)  {
        ciag[i] = (ciag[i] - 32);
    }
    i++;
}
A. Zamienić w ciągu wielkie litery na małe.
B. Od każdego znaku w ciągu odjąć kod 32.
C. Od każdego znaku w ciągu, który nie jest równy 0, odjąć kod 32.
D. Zamienić w ciągu małe litery na wielkie.
Odejmowanie 32 od wszystkich znaków w napisie to trochę kiepski pomysł, bo to nie zawsze działa. Nie wszystkie znaki, takie jak cyfry czy symbole, mają swoje wielkie odpowiedniki, więc ich kod ASCII nie powinien być zmieniany. Kabel od wielkich liter na małe to zupełnie inna bajka – tutaj dodajemy 32 do kodu. Odejmowanie kodu tylko dla znaków różniących się od 0 pomija istotę operacji na literach, co może skutkować dziwnymi rezultatami. Z mojego doświadczenia wynika, że lepiej to przemyśleć przed wprowadzeniem w życie.

Pytanie 7

Która z właściwości przycisków typu Radio-button opisanych w przedstawionym fragmencie dokumentacji jest poprawna?

Radio-button label

... The label can be positioned before or after the radio-button by setting the labelPosition property to 'before' or 'after'.

Radio groups

Radio-buttons should typically be placed inside of an <mat-radio-group> unless the DOM structure would make that impossible ... The radio-group has a value property that reflects the currently selected radio-button inside of the group.

Źródło: https://material.angular.io/components/radio/overview

A. Przyciski radio-button są organizowane w elemencie o nazwie <radio-group>
B. Właściwość labelPosition może przyjmować jedną z dwóch opcji
C. Wartość właściwości value grupy radio przechowuje tekst etykiety dla każdego radio-button
D. Etykieta (label) może być umieszczona wyłącznie po przycisku radio-button
Właściwość labelPosition w przyciskach typu radio-button, szczególnie w popularnych bibliotekach jak Angular Material, naprawdę potrafi ułatwić życie programiście. Jej działanie sprowadza się do tego, że pozwala określić, czy etykieta powinna być wyświetlana przed, czy po elemencie radio. Można ustawić tę właściwość na 'before' albo 'after'. Nie brzmi skomplikowanie, ale znaczenie praktyczne jest ogromne – czasem projekt graficzny wymaga, by tekst pojawił się z lewej strony guzika, a czasem z prawej. Dobre praktyki UX też to uwzględniają, bo zgodność z oczekiwaniami użytkownika poprawia czytelność formularzy. Moim zdaniem, jeśli budujesz interfejs dla internautów z różnych środowisk kulturowych (np. z językiem pisanym od prawej do lewej), ta opcja jest wręcz niezbędna. Warto też pamiętać, że takie ustawienie można łatwo nadpisywać na poziomie pojedynczego przycisku, co daje dużą elastyczność. W większości poważnych frameworków webowych, np. Angularze, ta właściwość jest dokumentowana jako podstawowa, bo daje deweloperowi kontrolę bez grzebania w CSS-ach. Sam nie raz korzystałem z labelPosition, szczególnie w korporacyjnych projektach, gdzie musiałem spełniać szczegółowe wymagania projektantów – dzięki temu oszczędza się czas i nerwy.

Pytanie 8

Jakie wartości jest w stanie przechować zmienna o typie logicznym?

A. Tylko ciąg znaków
B. Jedną z dwóch opcji: true lub false
C. Wartość w reprezentacji binarnej
D. Dowolną liczbę rzeczywistą
Zmienna typu logicznego (boolean) może przechowywać jedną z dwóch wartości: 'true' lub 'false'. Są to podstawowe wartości wykorzystywane w operacjach warunkowych i pętlach, które decydują o przepływie sterowania w programach. Wartości logiczne są kluczowe w konstrukcjach takich jak 'if-else', pętlach 'while' oraz w porównaniach. W wielu językach programowania 'true' jest równoznaczne z 1, a 'false' z 0, co pozwala na łatwą integrację z typami całkowitymi. Typ boolean jest niezbędny w programowaniu, umożliwiając implementację decyzji, walidacji danych i automatyzacji procesów.

Pytanie 9

Co to jest Docker?

A. Narzędzie do automatyzacji procesu tworzenia dokumentacji
B. Platforma do tworzenia, wdrażania i uruchamiania aplikacji w kontenerach
C. System zarządzania bazami danych
D. Framework JavaScript do tworzenia aplikacji mobilnych
Docker to platforma, która umożliwia tworzenie, wdrażanie i uruchamianie aplikacji w kontenerach. Kontenery to lekkie, przenośne jednostki, które zawierają wszystko, co potrzebne do uruchomienia aplikacji, w tym kod źródłowy, biblioteki i zależności. Dzięki Dockerowi programiści mogą łatwo tworzyć środowiska, które są zgodne z produkcją, co zmniejsza ryzyko błędów związanych z różnicami między tymi środowiskami. Przykładowo, jeśli tworzysz aplikację webową, możesz użyć Dockera do uruchomienia bazy danych w kontenerze, co pozwala na łatwe zarządzanie jej wersjami oraz konfiguracją. Docker staje się standardem w wielu firmach i projektach open source, ponieważ umożliwia szybsze wdrażanie aplikacji oraz automatyzację wielu procesów. Dzięki konteneryzacji można również łatwo skalować aplikacje, co jest niezwykle ważne w przypadku rosnącego ruchu użytkowników.

Pytanie 10

Jaki będzie wynik działania poniższego kodu w języku Java?

String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(c));
A. true, false, false
B. true, false, true
C. true, true, true
D. false, false, true
Wyniki, które wskazują, że zarówno porównanie 'a == c', jak i 'a.equals(c)' powinny zwracać 'true', opierają się na błędnym zrozumieniu, jak działa porównywanie obiektów w Javie. Warto zrozumieć, że operator '==' sprawdza, czy dwie referencje wskazują na ten sam obiekt w pamięci. W przypadku zmiennych 'a' i 'b', ponieważ obie są literałami tego samego ciągu, JVM optymalizuje ich przechowywanie, co skutkuje, że obie referencje prowadzą do tego samego obiektu. Natomiast zmienna 'c', utworzona za pomocą 'new String()', to zupełnie inny obiekt, mimo że jego wartość jest taka sama jak w 'a'. W związku z tym porównanie 'a == c' zwraca false. Z kolei metoda 'equals()' jest zaprojektowana do porównania wartości, a nie referencji, co oznacza, że 'a.equals(c)' zwróci true, ponieważ obie zmienne mają tę samą zawartość. Zrozumienie tych zasad jest kluczowe, aby unikać typowych pułapek przy pracy z obiektami w Javie. Pamiętaj, aby zawsze preferować 'equals()' do porównywania stringów i innych obiektów, aby uzyskać prawidłowe wyniki.”

Pytanie 11

Jaką funkcję pełnią mechanizmy ciasteczek w aplikacjach internetowych?

A. Do zapisywania danych użytkownika na serwerze
B. Do przechowywania informacji w bazie danych
C. Do generowania dynamicznych interfejsów dla użytkowników
D. Do zapisywania danych użytkownika w przeglądarce
Mechanizm ciasteczek (cookies) w aplikacjach webowych służy do przechowywania danych użytkownika bezpośrednio w przeglądarce. Ciasteczka mogą przechowywać różnego rodzaju informacje, takie jak preferencje językowe, identyfikatory sesji czy dane logowania, co pozwala na personalizację doświadczenia użytkownika oraz śledzenie jego aktywności na stronie. Dzięki ciasteczkom aplikacje webowe mogą zapamiętać użytkownika i dostosować treści do jego potrzeb przy kolejnych wizytach. Cookies są nieodłącznym elementem zarządzania stanem w aplikacjach stateless, takich jak te oparte na protokole HTTP. Mogą być one również wykorzystywane w systemach reklamowych i analitycznych do monitorowania zachowań użytkowników. Prawidłowe zarządzanie ciasteczkami i stosowanie odpowiednich polityk prywatności są kluczowe dla zgodności z przepisami RODO oraz regulacjami dotyczącymi ochrony danych osobowych.

Pytanie 12

Jakie mogą być konsekwencje długotrwałego narażenia na hałas w pracy?

A. Obniżenie ostrości wzroku
B. Uszkodzenie słuchu i zmęczenie
C. Wzrost efektywności pracy
D. Choroby skórne
Długotrwały hałas w miejscu pracy może prowadzić do poważnych konsekwencji zdrowotnych, takich jak uszkodzenie słuchu oraz przewlekłe zmęczenie. Stała ekspozycja na hałas o wysokim natężeniu może powodować stopniową utratę słuchu, szumy uszne, a także zwiększać poziom stresu i obniżać koncentrację. Zmęczenie wynikające z hałasu wpływa negatywnie na produktywność i samopoczucie pracowników, prowadząc do spadku efektywności oraz wzrostu ryzyka popełniania błędów. W celu ochrony przed hałasem zaleca się stosowanie środków ochrony indywidualnej, takich jak nauszniki lub zatyczki do uszu, a także instalowanie ekranów dźwiękochłonnych i ograniczenie źródeł hałasu w środowisku pracy.

Pytanie 13

Jakie będą skutki wykonania podanego fragmentu kodu w języku C++?

vector <int> liczby;
for(int i=0; i<10; i++) {
    liczby.push_back(2*i);
}
A. Do tablicy liczby, na jej początku, dodawane są nowe wartości.
B. Do tablicy liczby, na jej końcu, dodawane są nowe wartości.
C. Z tablicy liczby usuwane są elementy, z każdym obiegiem pętli eliminowany jest element z jej końca.
D. Z tablicy liczby usuwane są elementy, z każdym obiegiem pętli eliminowany jest element z jej początku.
Analizując zaproponowane odpowiedzi, łatwo zauważyć kilka typowych nieporozumień, które często pojawiają się na etapie nauki pracy z kolekcjami w C++. Po pierwsze, wielu osobom myli się pojęcie 'dodawania na początku' z 'dodawaniem na końcu', zwłaszcza że niektóre struktury standardowe, jak listy dwukierunkowe (std::list), umożliwiają wygodne wstawianie na początku (push_front). Jednak w przypadku std::vector nie ma metody push_front, a push_back oznacza zawsze dodanie nowego elementu do końca wektora, co powoduje, że kolejność elementów jest zachowana zgodnie z kolejnością ich dodawania. Błędne jest także przekonanie, że za każdym przebiegiem pętli z wektora coś jest usuwane – takie operacje wymagałyby jawnego wywołania metod erase(), pop_back() lub pop_front(), których tutaj w ogóle nie zastosowano. To bardzo istotne, bo domyślnie wektor nie usuwa niczego sam z siebie. Równie często spotykanym błędem jest mylenie działania innych kolekcji, jak np. kolejki FIFO (gdzie pop_front rzeczywiście usuwa pierwszy element), z zachowaniem vectora, który domyślnie dodaje na końcu. Sporo osób wychodzi z założenia, że 'dynamiczna tablica' powinna się samoistnie przesuwać lub skracać – ale to nie jest prawda w C++. Warto zapamiętać, że vector w C++ jest stworzony głównie do efektywnego rozbudowywania od końca i to jest zgodne z koncepcją dynamicznego zarządzania pamięcią w nowoczesnych językach programowania. Każdy inny sposób użycia wymaga dodatkowego kodu. Z mojego punktu widzenia dobrze jest od razu wyrobić sobie nawyk rozróżniania, która operacja jest domyślnie dostępna w danym kontenerze. Brak tej wiedzy prowadzi do błędnych założeń co do działania kodu i generuje trudne do wychwycenia błędy logiczne.

Pytanie 14

Które z poniższych nie jest algorytmem sortowania?

A. Binary Search
B. Quick Sort
C. Bubble Sort
D. Merge Sort
Binary Search jest algorytmem, który służy do efektywnego przeszukiwania uporządkowanych zbiorów danych, a nie do sortowania. Działa na zasadzie dzielenia zbioru na pół i eliminowania połowy z nich w każdym kroku, co pozwala na szybkie znalezienie poszukiwanej wartości. Jest to przykład algorytmu o czasie działania O(log n), co sprawia, że jest znacznie szybszy od prostego przeszukiwania liniowego. Przykładowo, gdy mamy posortowaną tablicę liczb, Binary Search może być użyty do znalezienia konkretnej liczby, eliminując w każdym kroku połowę zbioru, aż do odnalezienia wartości lub stwierdzenia, że jej nie ma. W kontekście branżowym, Binary Search jest szeroko stosowany w różnych aplikacjach, gdzie wymagane jest szybkie przeszukiwanie danych, na przykład w bazach danych i aplikacjach wyszukiwania. Kluczowe jest zrozumienie różnicy między algorytmem przeszukiwania a algorytmem sortowania; sortowanie odnosi się do organizacji danych w określonym porządku, podczas gdy Binary Search koncentruje się na znajdowaniu elementów w już posortowanych zbiorach.

Pytanie 15

Co oznacza operator '===' w JavaScript?

A. Porównanie wartości i typów
B. Konkatenacja stringów
C. Porównanie wartości
D. Przypisanie wartości
Operator '===' w JavaScript jest używany do porównania wartości oraz ich typów. To znaczy, że aby dwa elementy uznano za równe, muszą mieć zarówno tę samą wartość, jak i ten sam typ. Przykładowo, porównanie liczby 5 i stringa '5' zwróci false, ponieważ różnią się typem. Używanie '===' jest zalecane w dobrych praktykach programistycznych, ponieważ eliminuje niejednoznaczności związane z równością luźną (operator '=='), która może prowadzić do nieprzewidywalnych wyników. Na przykład, '5' == 5 zwróci true, co może być mylące. Dlatego w sytuacjach, gdzie zależy nam na ścisłym porównaniu, powinno się zawsze stosować '===' dla jasności kodu i uniknięcia błędów. W kontekście profesjonalnego programowania, korzystanie z '===' zapewnia lepszą kontrolę typów danych, co jest kluczowe w większych projektach, gdzie błędy typów mogą prowadzić do poważnych problemów z debugowaniem i utrzymywaniem kodu.

Pytanie 16

Który z wymienionych kroków wchodzi w skład testowania aplikacji?

A. Opracowywanie interfejsu graficznego
B. Debugowanie kodu w celu znalezienia błędów
C. Kompilowanie aplikacji
D. Projektowanie bazy danych
Tworzenie bazy danych to istotny element budowy aplikacji, ale nie jest częścią procesu testowania, a raczej etapu projektowania i implementacji backendu. Tworzenie interfejsu graficznego (GUI) polega na projektowaniu wizualnej warstwy aplikacji, natomiast testowanie i debugowanie koncentrują się na poprawności kodu i logice działania. Kompilowanie aplikacji jest procesem tłumaczenia kodu źródłowego na język maszynowy, ale nie wykrywa błędów logicznych w taki sposób, jak robi to debugowanie.

Pytanie 17

Przedstawione w filmie działania wykorzystują narzędzie

A. debuggera analizującego wykonujący kod
B. kompilatora dla interfejsu graficznego
C. generatora kodu java
D. generatora GUI przekształcającego kod do języka XAML
Wybrana odpowiedź jest trafna, bo faktycznie narzędzie pokazane w filmie to generator GUI, który potrafi przekształcać kod do języka XAML. XAML (czyli Extensible Application Markup Language) jest powszechnie używany do deklaratywnego opisywania interfejsów użytkownika, na przykład w aplikacjach WPF czy UWP na platformie .NET. Jak dla mnie, korzystanie z takich generatorów to ogromna wygoda, bo pozwala błyskawicznie przenosić projekt graficzny do formatu czytelnego dla platformy Microsoftu. Z mojego doświadczenia, wiele zespołów programistycznych stosuje takie rozwiązania, żeby oszczędzić czas na ręcznym pisaniu XAML-a (co potrafi być naprawdę żmudne przy dużych projektach). Co ciekawe, takie narzędzia bardzo dobrze współpracują z designerskimi edytorami UI i potrafią zautomatyzować konwersję nawet z innych formatów graficznych, np. Sketch czy Adobe XD do XAML-a. Branżowe standardy zalecają, by wykorzystywać generatorów GUI właśnie do tego celu, bo minimalizuje to liczbę błędów, przyspiesza wdrożenie zmian i ułatwia współpracę między programistami a projektantami. Warto pamiętać, że XAML jest bardzo elastyczny i umożliwia potem ręczną edycję wygenerowanego kodu – czasem powstają drobne poprawki, ale ogólnie to naprawdę przydatne narzędzie. Ogólnie – jeśli tylko projektujesz UI pod .NET, to automatyczna konwersja do XAML-a to jest coś, co warto znać i wykorzystywać w praktyce.

Pytanie 18

W językach C++ bądź C# termin virtual można wykorzystywać w kontekście

A. metod klasy
B. atrybutów klasy
C. funkcji zaprzyjaźnionych
D. destruktorów
W kontekście języków C++ i C# pojęcie 'virtual' jest często błędnie kojarzone z różnymi składnikami klasy, takimi jak atrybuty czy funkcje zaprzyjaźnione. Jednakże, w praktyce i zgodnie ze standardami tych języków, nie istnieje możliwość oznaczenia atrybutów klasy (czyli jej pól, zmiennych członkowskich) jako wirtualnych – nie ma to sensu, ponieważ dziedziczenie i polimorfizm dotyczą zachowania, czyli metod, a nie danych. Wiele osób myli też funkcje zaprzyjaźnione z metodami klas tylko dlatego, że mają dostęp do prywatnych członków, ale 'friend' w C++ służy tylko do udzielania dodatkowych uprawnień, a nie do realizacji polimorfizmu – nie można więc użyć 'virtual' w takim kontekście. Jeśli chodzi o destruktory, to temat jest trochę bardziej złożony. W C++ destruktory rzeczywiście mogą być wirtualne i często powinny być, jeśli klasa ma dziedziczyć, żeby poprawnie usuwać obiekty przez wskaźniki do klasy bazowej. Jednak w C# wszystkie destruktory są niejako „wirtualne” z definicji i nie używa się tam słowa kluczowego 'virtual' przy destruktorach, bo zarządzanie pamięcią działa inaczej. Niestety, to też bywa źródłem nieporozumień. Całe zamieszanie bierze się z nieintuicyjnych różnic między tymi dwoma językami oraz z mylenia składników klasy z ich zachowaniem. Z mojego doświadczenia wynika, że najczęstszy błąd polega na traktowaniu 'virtual' jako czegoś, co można dodać „gdziekolwiek”, podczas gdy de facto jest to narzędzie skierowane ściśle do deklarowania i nadpisywania metod (funkcji członkowskich) klasy. Jeśli nie zrozumie się tej różnicy, łatwo później wpaść w pułapkę pisania nieczytelnego i nieefektywnego kodu. Warto więc trzymać się dobrych praktyk i nie kombinować tam, gdzie nie jest to przewidziane przez specyfikację języka.

Pytanie 19

Celem mechanizmu obietnic (ang. promises) w języku JavaScript jest

A. ulepszenie czytelności kodu synchronicznego
B. zastąpienie mechanizmu dziedziczenia w programowaniu obiektowym
C. zarządzanie funkcjonalnością związaną z kodem asynchronicznym
D. zarządzanie przechwytywaniem błędów aplikacji
Często można się pogubić, czym dokładnie są promises w JavaScript, zwłaszcza jeśli ktoś kojarzy je luźno z innymi mechanizmami programowania obiektowego czy obsługą błędów. Promises mają swoje korzenie w potrzebie efektywnego zarządzania asynchronicznością, czyli wykonywaniem operacji, które nie kończą się od razu, na przykład pobieraniem danych z sieci czy operacjami wejścia-wyjścia. To, że promises jakoś „ulepszają czytelność kodu synchronicznego”, jest trochę nadinterpretacją – bo one nie poprawiają kodu synchronicznego, tylko asynchroniczny czynią bardziej czytelnym. Dziedziczenie w programowaniu obiektowym, zarówno prototypowe, jak i klasyczne, to zupełnie inna para kaloszy – promises nie mają nic wspólnego z zastępowaniem tych mechanizmów, bo ich zadaniem nie jest kształtowanie struktury obiektów, a raczej kontrolowanie przepływu kodu w czasie. Zarządzanie przechwytywaniem błędów też nie jest głównym celem promises – choć rzeczywiście pozwalają na łatwiejszą obsługę błędów w kodzie asynchronicznym poprzez catch(), to jednak nie są uniwersalnym systemem zarządzania wyjątkami. Typowym błędem myślowym jest też mylenie promises z callbackami lub myślenie, że rozwiązują one wszystkie problemy związane z błędami – a to nie do końca prawda, bo promise jedynie porządkuje asynchroniczność i pozwala na prostsze reakcji na sukcesy i porażki asynchronicznych operacji. W praktyce promises to nie magiczna broń na wszystko, tylko bardzo sprytne narzędzie do ogarnięcia operacji nieblokujących w sposób czytelny, przewidywalny i zgodny ze współczesnymi standardami branżowymi.

Pytanie 20

Cytat zaprezentowany powyżej dotyczy metodyki RAD. Co oznacza ten skrót w języku polskim?

... (RAD) .... is a general term for adaptive software development approaches, and the name for James Martin's method of rapid development. In general, RAD approaches to software development put less emphasis on planning and more emphasis on an adaptive process. Prototypes are often used in addition to or sometimes even instead of design specifications.
Źródło: https://en.wikipedia.org/wiki Dostęp: 25.03.2021
A. szybki rozwój aplikacji
B. środowisko błyskawicznego programowania
C. środowisko do tworzenia aplikacji
D. zintegrowane środowisko deweloperskie
Wybór niepoprawnych odpowiedzi wynika z nieporozumienia dotyczącego znaczenia skrótu RAD. Pierwsza błędna odpowiedź środowisko rozwijania aplikacji nie odpowiada sednu metodyki RAD ponieważ odnosi się bardziej do ogólnego pojęcia platformy lub środowiska gdzie aplikacje są tworzone a nie do szybkiego procesu rozwoju. Nie oddaje to istoty metodyki która skupia się na skróceniu czasu cyklu życia aplikacji poprzez szybkie prototypowanie i wprowadzenie iteracyjnych zmian. Następnie środowisko szybkiego programowania również jest mylące ponieważ sugeruje zastosowanie narzędzi lub technologii które jedynie wspierają szybkie pisanie kodu a nie całego procesu projektowania testowania i wprowadzania do użytkowania. Zintegrowane środowisko programistyczne to termin odnoszący się do oprogramowania takiego jak IDE które oferuje narzędzia wspierające programistów w pisaniu testowaniu i debugowaniu kodu ale nie jest bezpośrednio związane z filozofią i technikami RAD. Typowym błędem myślowym jest skupienie się na pojedynczych etapach rozwoju oprogramowania a nie na całym procesie który metoda RAD opisuje jako całość łączącą szybkie tworzenie prototypów elastyczność i intensywną współpracę z klientem. Ważne jest zrozumienie że RAD to podejście systemowe mające na celu przyspieszenie dostarczania wartości klientom co nie jest osiągane przez samo szybkie kodowanie czy używanie zintegrowanych narzędzi programistycznych ale przez całościowe podejście do procesu tworzenia oprogramowania

Pytanie 21

Jakie jest poprawne określenie interfejsu (szablonu klasy) w języku Java?

interface IMyInterface {
    private: int a;
    IMyInterface() { a = 0; }
    void mth1();
}
Definicja 1
interface IMyInterface {
    private: int a;
    void mth1();
    int mth2() { return a; }
}
Definicja 2
interface IMyInterface {
    void mth1();
    int mth2() { return 0; }
}
Definicja 3
interface IMyInterface {
    void mth1();
    int mth2();
}
Definicja 4
A. Definicja 2
B. Definicja 3
C. Definicja 4
D. Definicja 1
W pierwszej definicji interfejsu obecność zmiennej prywatnej i konstruktora jest niezgodna z zasadami definiowania interfejsów w języku Java. Interfejsy nie mogą zawierać żadnych konstruktorów, ponieważ nie są klasami i nie można ich instancjonować. Dodatkowo, zmienne w interfejsach są domyślnie publiczne, statyczne i finalne, co oznacza, że nie mogą być prywatne jak w tej definicji. Druga definicja popełnia podobne błędy przez deklarowanie prywatnej zmiennej i implementację metody wewnątrz interfejsu, co przed Java 8 było niemożliwe. Trzecia definicja zawiera metodę z ciałem, co w kontekście starszych wersji Javy nie jest zgodne z zasadami, choć od Java 8 można deklarować metody domyślne z ciałem, jednak w tej sytuacji nie jest to poprawne bez specyfikacji default. Błędnie przyjęte podejścia do definicji interfejsów mogą wynikać z niezrozumienia, że interfejsy służą jedynie do deklarowania metod i ewentualnie statycznych finalnych zmiennych, nie zaś do implementacji logiki. Prawidłowe zrozumienie roli interfejsów jest kluczowe dla wykorzystania ich w tworzeniu elastycznego i rozszerzalnego kodu. Błędy te podkreślają potrzebę dbałości o zgodność ze specyfikacją języka oraz znajomość jego wersji i nowości wprowadzanych w kolejnych iteracjach.

Pytanie 22

Kod XAML zaprezentowany powyżej zostanie wyświetlony jako:

Ilustracja do pytania
A. A
B. D
C. C
D. B
Wybrałeś dokładnie taką odpowiedź, jaką powinien wskazać każdy, kto dobrze rozumie XAML i układ StackLayout. Zobacz, co tu się dzieje: dwa pola Entry wyświetlają się jedno pod drugim, co daje klasyczną strukturę formularza – najpierw pole "Imię", potem "Nazwisko". Dalej mamy StackLayout z orientacją poziomą (Horizontal), więc etykieta "Zgoda RODO" oraz przełącznik Switch pojawiają się obok siebie – to bardzo typowy sposób na prezentację zgody na coś w aplikacjach, bo nie ma sensu rozdzielać tego na dwie linie. Po nich pojawia się Slider z ustawionym Value na 0.5 i kolorami MinimumTrackColor oraz MaximumTrackColor, czyli dokładnie tak jak widać na obrazku – jeden kolor po lewej, drugi po prawej i kółko pośrodku. Na końcu jest Button "Zapisz". Moim zdaniem, taki układ to wręcz klasyka budowy prostych formularzy w aplikacjach mobilnych opartych na XAML. Swoją drogą, to świetny przykład, jak StackLayout pozwala na szybkie i czytelne układanie elementów na ekranie, bez zbędnego komplikowania interfejsu. W praktyce warto jeszcze pamiętać, że oddzielenie pól Entry podnosi czytelność, a stosowanie układów poziomych sprawdza się wtedy, gdy chcesz, żeby użytkownik od razu widział etykietę i jej kontrolkę. Widać tu też dbałość o kolory i spójność wizualną. Według mnie, warto od razu testować takie formularze na różnych urządzeniach, bo StackLayout zachowuje się przewidywalnie, ale warto mieć na uwadze responsywność – no i nie zapomnij, że Slider i Switch mają swoje domyślne wartości, które można łatwo sterować z kodu.

Pytanie 23

Jakie jest podstawowe założenie normalizacji krajowej?

A. Zwiększenie ilości regulacji prawnych
B. Ujednolicenie wymagań technicznych i poprawa bezpieczeństwa
C. Utrudnienie handlu międzynarodowego
D. Wzrost kosztów produkcji
Ujednolicenie wymagań technicznych i poprawa bezpieczeństwa to główne cele normalizacji krajowej. Normalizacja polega na opracowywaniu standardów, które są stosowane w różnych branżach w celu zapewnienia jakości, bezpieczeństwa i kompatybilności produktów oraz usług. Dzięki normalizacji producenci tworzą wyroby zgodne z określonymi normami, co zwiększa ich konkurencyjność na rynku krajowym i międzynarodowym. Wdrożenie jednolitych standardów wpływa także na bezpieczeństwo użytkowników, minimalizując ryzyko awarii lub niezgodności produktów.

Pytanie 24

Jaką strukturę danych stosuje się w algorytmie BFS (przeszukiwanie wszerz)?

A. Tablica
B. Graf
C. Kolejka
D. Zbiór
Stos jest używany w algorytmie DFS (przeszukiwanie w głąb), a nie w BFS, ponieważ DFS eksploruje możliwie najgłębiej dany graf, zanim wróci do poprzedniego poziomu. Lista jest używana jako struktura ogólnego przeznaczenia, ale nie jest podstawowym narzędziem w algorytmie BFS. Drzewa są strukturą danych, którą BFS może przeszukiwać, ale sama struktura drzewa nie jest narzędziem używanym w algorytmie BFS – to kolejka pełni tę funkcję, przechowując wierzchołki do odwiedzenia.

Pytanie 25

Która metoda w obrębie klasy jest uruchamiana automatycznie podczas tworzenia kopii obiektu?

A. Konstruktor kopiujący
B. Destruktor
C. Metoda zaprzyjaźniona
D. Metoda statyczna
Konstruktor kopiujący to taka specyficzna metoda w klasie, która działa, kiedy robimy nowy obiekt jako kopię już istniejącego. Dzięki temu możemy skopiować wartości pól z jednego obiektu do drugiego. To naprawdę ważne, zwłaszcza gdy mówimy o zarządzaniu pamięcią. Na przykład w C++ może to wyglądać tak: `Samochod(const Samochod &inny) { marka = inny.marka; przebieg = inny.przebieg; }`. Konstruktor kopiujący ma na celu uniknięcie problemów związanych z tzw. płytkim kopiowaniem, co może prowadzić do różnych błędów, jak wielokrotne zwolnienie tej samej pamięci. Generalnie mówiąc, jest to kluczowy mechanizm, który pomaga utrzymać bezpieczeństwo i poprawność działania naszej aplikacji.

Pytanie 26

Jakie narzędzie najlepiej sprawdza się w przekształcaniu liczby szesnastkowej na binarną?

A. Program do arkuszy kalkulacyjnych
B. Program do edycji tekstu
C. Aplikacja internetowa
D. Kalkulator programisty
Kalkulator programisty jest najbardziej odpowiednim narzędziem do konwersji liczby szesnastkowej na binarną ze względu na swoje wyspecjalizowane funkcje matematyczne i programistyczne. Narzędzia te umożliwiają użytkownikom łatwe przekształcanie różnych systemów liczbowych, w tym konwersji z systemu szesnastkowego (hex) na system binarny. Kalkulatory programistyczne często zawierają dedykowane opcje dla konwersji liczbowej, co pozwala na szybkie i dokładne uzyskanie wyników bez potrzeby stosowania skomplikowanych algorytmów lub wzorów. Na przykład, aby przekształcić liczbę szesnastkową '1A' na binarną, użytkownik wprowadza '1A' do kalkulatora, a wynik '00011010' zostaje automatycznie wygenerowany. Dodatkowo, wiele kalkulatorów programistycznych jest zgodnych z międzynarodowymi standardami, co zapewnia ich wiarygodność w obliczeniach. Warto również zauważyć, że kalkulatory programistyczne mogą obsługiwać konwersje z różnych systemów liczbowych, co czyni je wszechstronnym narzędziem w pracy z danymi cyfrowymi i kodowaniem. Dzięki temu, kalkulator programisty stanowi idealne rozwiązanie dla programistów i inżynierów, którzy regularnie pracują z różnymi formatami danych.

Pytanie 27

Zaprezentowany fragment kodu w języku C# tworzy hasło. Wskaż zdanie PRAWDZIWE dotyczące charakterystyki tego hasła:

var random = new Random();
string pulaZnakow = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";

int dlPuli = pulaZnakow.Length - 1;
char znak;
string wynik = "";

for(int i = 0; i < 8; i++)  {
    znak = pulaZnakow[random.Next(0, dlPuli)];
    wynik += znak;
}
A. Może zawierać małe i wielkie litery oraz cyfry
B. Ma co najmniej 8 znaków oraz zawiera małe i wielkie litery oraz cyfry
C. Jest maksymalnie 7-znakowe, co wynika z wartości zmiennej i
D. Może zawierać zarówno małe, jak i wielkie litery, cyfry oraz symbole
Analizując podany fragment kodu, widać, że hasło generowane jest losowo z puli znaków, która zawiera małe i wielkie litery alfabetu łacińskiego oraz cyfry od 0 do 9. Nie znajdują się tam żadne znaki specjalne ani symbole, więc hasło nie może ich zawierać – to ważne z praktycznego punktu widzenia, bo często spotyka się wymagania dotyczące obecności symboli w bezpiecznych hasłach. Kod wykorzystuje pętlę for, która wykonuje się dokładnie 8 razy, czyli hasło ma zawsze 8 znaków – ani mniej, ani więcej. Z mojego doświadczenia wynika, że taki sposób generowania haseł jest dość powszechny w prostych aplikacjach, np. przy automatycznym tworzeniu kont użytkowników. Jednak warto pamiętać, że im bardziej zróżnicowana pula znaków, tym lepsze zabezpieczenie – tutaj ograniczamy się tylko do liter i cyfr. Z praktycznego punktu widzenia, takie losowe hasło trudno odgadnąć ręcznie, ale jest dość przewidywalne, jeśli ktoś zna algorytm i nie ma dodatkowych zabezpieczeń (np. cryptographically secure random number generator). W standardach bezpieczeństwa, np. OWASP, zaleca się uwzględnianie symboli i unikanie prostego Random do generowania haseł, bo można go przewidzieć, ale do nauki i zastosowań testowych taki kod jest całkiem w porządku. Hasło więc może zawierać małe i wielkie litery oraz cyfry – dokładnie jak głosi prawidłowa odpowiedź.

Pytanie 28

Jakie są różnice między testami funkcjonalnymi a niefunkcjonalnymi?

A. Testy funkcjonalne oceniają zgodność działania aplikacji z założeniami, a niefunkcjonalne analizują aspekty wydajności, bezpieczeństwa i użyteczności
B. Testy funkcjonalne koncentrują się na interfejsie, a niefunkcjonalne na backendzie aplikacji
C. Testy funkcjonalne oceniają wydajność aplikacji, podczas gdy niefunkcjonalne weryfikują poprawność kodu
D. Testy funkcjonalne są realizowane tylko przez końcowych użytkowników, natomiast niefunkcjonalne przez programistów
Twierdzenie, że testy funkcjonalne sprawdzają wydajność aplikacji, a niefunkcjonalne poprawność kodu, jest błędne – testy funkcjonalne dotyczą zgodności aplikacji z wymaganiami, natomiast wydajność jest domeną testów niefunkcjonalnych. Testy funkcjonalne nie są przeprowadzane wyłącznie przez użytkowników końcowych – najczęściej są realizowane przez zespoły QA i testerów manualnych lub automatycznych. Podział testów na interfejsowe i backendowe nie jest synonimem podziału na testy funkcjonalne i niefunkcjonalne – oba typy mogą dotyczyć zarówno interfejsu, jak i zaplecza aplikacji.

Pytanie 29

Jakie jest podstawowe zadanie wykorzystania frameworka Node.js w aplikacjach internetowych?

A. Weryfikacja API
B. Zarządzanie aplikacjami serwerowymi i realizacja przetwarzania asynchronicznego
C. Budowanie aplikacji mobilnych
D. Kreowanie graficznego interfejsu użytkownika
Node.js to w zasadzie takie środowisko, które pozwala na uruchamianie JavaScriptu na serwerze. Dzięki temu można budować różne aplikacje serwerowe i radzić sobie z asynchronicznym przetwarzaniem. Fajnie, że Node.js może obsługiwać wiele połączeń jednocześnie, co sprawia, że nadaje się do aplikacji, które mają dużo użytkowników, jak czaty czy różne API. Jest to dość wydajne rozwiązanie dzięki architekturze opartej na zdarzeniach, więc nie zajmuje za dużo zasobów. Co ciekawe, używając Node.js, można pisać kod zarówno na serwerze, jak i na kliencie, co jest naprawdę dużą oszczędnością czasu.

Pytanie 30

Co to jest SPA (Single Page Application)?

A. Metoda projektowania interfejsu użytkownika dla aplikacji mobilnych
B. Technika optymalizacji kodu w aplikacjach JavaScript
C. Format pliku używany w aplikacjach do przetwarzania danych
D. Aplikacja webowa działająca na jednej stronie, dynamicznie aktualizująca treść bez przeładowywania całej strony
Single Page Application (SPA) to typ aplikacji internetowej, która działa na jednej stronie, umożliwiając dynamiczne ładowanie treści bez konieczności przeładowania całej witryny. W tradycyjnych aplikacjach webowych, każda interakcja użytkownika, która wymagała zmiany treści, wiązała się z odświeżeniem strony. W przypadku SPA, korzysta się z technologii takich jak AJAX, WebSockets czy API, co pozwala na asynchroniczne pobieranie danych z serwera. Przykłady SPA to popularne frameworki i biblioteki, takie jak React, Angular czy Vue.js. Dzięki tym technologiom, użytkownicy mogą doświadczyć płynniejszego i bardziej responsywnego interfejsu. Dobrą praktyką w projektowaniu SPA jest stosowanie wzorców projektowych, takich jak MVC (Model-View-Controller), co ułatwia zarządzanie kodem oraz jego modułowość. SPA są szczególnie przydatne w aplikacjach wymagających intensywnej interakcji, takich jak platformy e-commerce czy aplikacje społecznościowe, gdzie kluczowa jest szybkość i komfort użytkowania.

Pytanie 31

W przypadku przedstawionych kodów źródłowych, które są funkcjonalnie równoważne, wartość, która zostanie zapisana w zmiennej b po wykonaniu operacji, to

Python:C++ / C# / Java:
x = 5.96;
b = int(x);
double x = 5.96;
int b = (int)x;
A. 5.96
B. 596
C. 6
D. 5
Różnice między językami programowania w obszarze typów danych mogą czasem wprowadzać w błąd. W Twoim przypadku, patrząc na liczbę 5.96, można by pomyśleć, że różne języki zaokrąglają liczby zmiennoprzecinkowe różnie. Ale w praktyce, w większości języków, jak Python czy C++, konwersja liczby zmiennoprzecinkowej na całkowitą poprzez rzutowanie lub funkcję int() po prostu odcina część dziesiętną. Wartość w zmiennej b staje się 5, nawet jeśli 5.96 wygląda bardziej jak 6. Często ludzie mylą rzutowanie z funkcjami zaokrąglającymi, które działają na innej zasadzie. Żeby zaokrąglić do najbliższej liczby całkowitej użyj funkcji takich jak round() w Pythonie czy Math.round() w Javie. Rozumienie tych różnic jest istotne, żeby później nie mieć problemów z błędami logicznymi, zwłaszcza przy arytmetyce, gdzie precyzja ma znaczenie. Dobrze jest używać rzutowania tylko wtedy, kiedy utrata precyzji nie jest problemem, bo w niektórych zastosowaniach, na przykład w finansach, wybór między rzutowaniem a zaokrąglaniem może naprawdę zmienić wynik.

Pytanie 32

Które z poniższych nie jest narzędziem do zarządzania stanem w aplikacjach React?

A. Context API
B. Redux
C. Webpack
D. MobX
Wybierając odpowiedzi związane z zarządzaniem stanem, warto zaznaczyć, że Redux, MobX oraz Context API to popularne narzędzia wykorzystywane do efektywnego zarządzania stanem w aplikacjach zbudowanych w React. Redux jest biblioteką, która wprowadza wzorzec architektoniczny Flux, umożliwiając centralizację stanu aplikacji. Pozwala to na łatwiejsze śledzenie zmian stanu oraz ich przewidywalność. MobX, z drugiej strony, oferuje bardziej reaktywny i obiektowy model zarządzania stanem, gdzie zmiany stanu są automatycznie śledzone, co upraszcza kod i redukuje złożoność. Context API to natywne rozwiązanie w React, które umożliwia dzielenie się stanem między komponentami bez potrzeby przekazywania propsów przez wszystkie poziomy drzewa komponentów. Często nowi programiści mylą Webpack z narzędziami do zarządzania stanem, co wynika z jego kluczowej roli w ekosystemie React. W rzeczywistości, narzędzia do budowania, takie jak Webpack, koncentrują się głównie na kompilacji i optymalizacji zasobów, a nie na logice i zarządzaniu stanem aplikacji. Zrozumienie różnic między tymi narzędziami jest kluczowe dla prawidłowego projektowania aplikacji i efektywnego wykorzystania dostępnych technologii.

Pytanie 33

Jaki rodzaj testów można scharakteryzować przedstawionym opisem?

NazwaOpisCzynnościPo teście
Formularz osobowySprawdzenie odpowiedzi formularza na błędy użytkownika1. czy wpisano wszystkie wymagane pola?
2. czy e-mail zawiera znak @?
3. czy nr telefonu zawiera cyfry, zgodnie ze wzorcem?
4. czy jest zgoda na przetwarzanie danych?
Usunąć z bazy danych wpisane podczas testowania osoby
A. testy wydajnościowe
B. testy funkcjonalne
C. testy zgodności
D. testy jednostkowe
Dokładnie o takie testy tutaj chodzi! Testy funkcjonalne skupiają się na sprawdzaniu, czy system realizuje funkcje zgodnie z wymaganiami biznesowymi i oczekiwaniami użytkownika. W tym przypadku chodzi o formularz osobowy, który ma określone zasady walidacji – na przykład obowiązkowe pola, poprawny format e-maila czy numer telefonu zgodny ze wzorcem. Sprawdza się też, czy użytkownik wyraził zgodę na przetwarzanie danych. To wszystko to typowe przypadki testów funkcjonalnych, bo nie interesuje nas tu ani wydajność systemu, ani szczegóły implementacji kodu, tylko efekt w postaci poprawnego działania funkcji z punktu widzenia użytkownika. Moim zdaniem właśnie w takich testach najłatwiej złapać błędy, które są naprawdę uciążliwe dla użytkowników końcowych. Branżowe standardy, takie jak ISTQB, podkreślają, że testy funkcjonalne badają zachowanie systemu na podstawie specyfikacji, a nie sposobu realizacji. Praktyka pokazuje, że nawet proste formularze często zawierają bzdurne błędy (np. nie sprawdza się formatu maila albo nie wymaga zgody RODO), więc takie testy są wręcz niezbędne. Dodatkowo, dobrym zwyczajem jest po takich testach „posprzątać” po sobie dane testowe, żeby nie zaśmiecać bazy – to też jest element dobrze przeprowadzonego testowania funkcjonalnego.

Pytanie 34

Która z poniższych deklaracji w języku C++ poprawnie opisuje tablicę dwuwymiarową?

A. int matrix[3];
B. int matrix[3][3][3];
C. int matrix[3][3];
D. int matrix[];
Deklaracja 'int matrix[3];' tworzy jednowymiarową tablicę, która nie ma drugiego indeksu do odwoływania się do elementów. 'Int matrix[];' jest błędną deklaracją, ponieważ nie określa rozmiaru tablicy. 'Int matrix[3][3][3];' definiuje tablicę trójwymiarową, a pytanie dotyczyło tablicy dwuwymiarowej. Aby poprawnie zadeklarować tablicę dwuwymiarową, konieczne jest użycie dwóch indeksów, jak w przypadku 'int matrix[3][3];'.

Pytanie 35

Który z poniższych elementów jest częścią architektury PWA (Progressive Web App)?

A. Service Worker
B. DOM Renderer
C. Media Encoder
D. Virtual Machine
Wybór innych odpowiedzi może wynikać z nieporozumienia dotyczącego terminologii i funkcji różnych komponentów w architekturze aplikacji webowych. DOM Renderer, który jest odpowiedzialny za renderowanie struktury dokumentu HTML w przeglądarkach, nie ma bezpośredniego związku z architekturą PWA. Jego zadaniem jest prezentacja treści, ale nie wpływa na funkcjonalności offline czy zarządzanie zasobami. W kontekście PWA, kluczowe są aspekty zapewniające dostępność i wydajność aplikacji, a DOM Renderer nie odnosi się do tych wymagań. Virtual Machine, często kojarzona z technologiami takimi jak Java czy JavaScript (np. V8 w Google Chrome), jest odpowiedzialna za wykonywanie kodu, ale nie pełni roli w architekturze PWA, ponieważ nie zarządza ani nie optymalizuje interakcji sieciowych. Ostatni element, Media Encoder, to narzędzie do kodowania multimediów, które również nie ma zastosowania w kontekście PWA. Typowe błędy polegają na myleniu komponentów odpowiedzialnych za renderowanie i wykonywanie kodu z tymi, które mają na celu poprawę doświadczenia użytkownika w aplikacjach webowych. Zrozumienie roli Service Workera jest kluczowe dla efektywnego projektowania aplikacji, które zapewniają użytkownikom lepsze doświadczenie, szczególnie w warunkach ograniczonej dostępności sieci.

Pytanie 36

Programem służącym do monitorowania błędów oraz organizacji projektów jest:

A. Bugzilla
B. Git
C. Jasmine
D. Jira
Jira to narzędzie, które zdecydowanie wyróżnia się w kwestii zarządzania projektami programistycznymi oraz monitorowania błędów. Z mojego doświadczenia wynika, że praktycznie każda większa firma IT używa Jiry do śledzenia zgłoszeń, tzw. ticketów, które mogą dotyczyć zarówno zadań, jak i błędów do naprawienia. Co istotne, Jira pozwala na bardzo rozbudowaną konfigurację – można tworzyć workflow, automatyzować przypisania zadań, integrować ją z repozytoriami kodów (np. GitHub, Bitbucket), testami automatycznymi, a nawet narzędziami do continuous integration. Standardem branżowym jest prowadzenie rejestru błędów (bug tracker) i backlogu zadań właśnie w Jirze, bo wszystko odbywa się w jednym miejscu, a zespół ma przejrzysty widok postępów. Bardzo fajna jest opcja generowania raportów – łatwo można sprawdzić, ile błędów zostało naprawionych, ile czeka na poprawki czy jak poszczególni członkowie zespołu realizują swoje zadania. Jira jest też zgodna z metodykami Agile, np. Scrum czy Kanban, co dodatkowo ułatwia zarządzanie sprintami, planowanie i retrospektywy. Uważam, że znajomość tego narzędzia to podstawa dla każdego, kto myśli o pracy w branży IT na poważnie. Warto też wiedzieć, że Jira obsługuje zarówno małe zespoły, jak i międzynarodowe projekty, bo jest bardzo skalowalna i można ją dostosować praktycznie do każdego procesu.

Pytanie 37

Wskaż kod, który jest funkcjonalnie równoważny zaprezentowanemu poniżej:

switch(nrTel) {
    case 999: opis = "Pogotowie"; break;
    case 998: opis = "Straż"; break;
    case 997: opis = "Policja"; break;
    default: opis = "Inny numer";
}
Kod 1.
with nrTel {
    if (999) opis = "Pogotowie";
    if (998) opis = "Straż";
    if (997) opis = "Policja";
    else opis = "Inny numer";
}
Kod 2.
if (nrTel == 999)
    opis = "Pogotowie";
else if (nrTel == 998)
    opis = "Straż";
else if (nrTel == 997)
    opis = "Policja";
else opis = "Inny numer";
Kod 3.
if (nrTel == 999)
    opis = "Pogotowie";
if (nrTel == 998)
    opis = "Straż";
if (nrTel == 997)
    opis = "Policja";
else
    opis = "Inny numer";
Kod 4.
Opis =
    if (nrTel == 999) => "Pogotowie";
    else if (nrTel == 998) => "Straż";
    else if (nrTel == 997) => "Policja";
    else => "Inny numer";
A. Kod 4.
B. Kod 2.
C. Kod 1.
D. Kod 3.
W tym przypadku Kod 2 jest dokładnym odpowiednikiem funkcjonalnym dla przedstawionej instrukcji switch. To, co tu widać, to klasyczna zamiana konstrukcji switch-case na strukturę if-else if-else, co jest bardzo częstą praktyką w programowaniu, szczególnie w językach, które nie zawsze posiadają rozbudowaną wersję switch. Kod 2 najpierw sprawdza, czy nrTel to 999, jeśli tak – przypisuje "Pogotowie" i nie sprawdza dalszych warunków. Jeśli nie, przechodzi do kolejnego warunku, czyli nrTel == 998, potem 997, w końcu domyślnie daje "Inny numer". Dokładnie tak samo to działało w switchu – tylko jeden warunek się wykonuje i reszta jest ignorowana, co ma znaczenie np. gdybyśmy później rozbudowywali logikę. Takie podejście jest czytelne, uniwersalne i zgodne z dobrymi praktykami kodowania – łatwo to refaktoryzować, debugować i utrzymywać. W wielu firmowych projektach spotkałem się z preferencją dla if-else zamiast switcha, jeśli liczba przypadków nie jest ogromna, bo łatwiej potem dołożyć dodatkowe warunki (np. złożone, nie tylko proste porównanie wartości). Fajnie też wiedzieć, że takie zamiany to podstawa przy migracji kodu między różnymi językami – nie każdy język ma identycznie działający switch. Moim zdaniem, umiejętność takiego przełożenia to dobra baza do nauki algorytmiki i lepszego rozumienia logiki sterowania przepływem kodu.

Pytanie 38

W języku Java wyjątek ArrayIndexOutOfBoundsException występuje, gdy następuje próba dostępu do elementu tablicy, którego

A. indeks mieści się w zakresie od 0 do n-1, gdzie n oznacza rozmiar tablicy
B. wartość przewyższa jego indeks
C. wartość przekracza rozmiar tablicy
D. indeks jest równy lub większy od rozmiaru tablicy
Wyjątek ArrayIndexOutOfBoundsException w Javie to taki klasyk, na który łatwo się naciąć, zwłaszcza gdy operujesz na tablicach dynamicznie lub masz jakieś pętle i zapomnisz o poprawnych granicach. Ta odpowiedź jest prawidłowa, bo w języku Java indeksowanie tablic zaczyna się od 0, a ostatni poprawny indeks to zawsze rozmiar tablicy minus jeden. Jeśli próbujesz dostać się do elementu, którego indeks jest równy lub większy od rozmiaru tablicy, silnik uruchomieniowy Javy od razu rzuci ten wyjątek. Przykład? Masz tablicę int[] t = new int[5]; i próbujesz odwołać się do t[5] albo t[10] – nie zadziała, bo legalne są tylko indeksy 0, 1, 2, 3, 4. Moim zdaniem to jeden z tych wyjątków, które wyraźnie pokazują, jak ważne jest zabezpieczanie kodu i stosowanie praktyk takich jak sprawdzanie długości tablicy przed dostępem do jej elementów. W profesjonalnym kodzie, zwłaszcza komercyjnym, nie zostawia się takich rzeczy przypadkowi – często stosuje się pętle typu for (int i = 0; i < array.length; i++), żeby mieć pewność, że nigdzie nie wyjedziemy poza zakres. Dobra praktyka to też wykorzystywanie narzędzi jak testy jednostkowe, żeby wyłapywać takie błędy. Warto pamiętać, że ten wyjątek jest unchecked, czyli nie musisz go łapać w kodzie, ale dobrze jest rozumieć, że jego pojawienie się oznacza błąd w logice programu. Osobiście uważam, że jeśli ktoś raz się na tym przejedzie, to już zawsze sprawdza rozmiar tablicy przed dostępem – taka nauczka na całe życie programisty.

Pytanie 39

Jaki numer telefonu należy wybrać, aby skontaktować się z pogotowiem ratunkowym w Polsce?

A. 998
B. 112
C. 997
D. 113
Numer 112 to tzw. europejski numer alarmowy, który działa nie tylko w Polsce, ale i w całej Unii Europejskiej oraz kilku innych krajach. Z mojego doświadczenia wynika, że warto nawykowo korzystać właśnie z tego numeru, bo jest on uniwersalny i obsługiwany przez wszystkie sieci – zarówno stacjonarne, jak i komórkowe. W praktyce, dzwoniąc pod 112, łączymy się z centralą, która przekieruje nas do odpowiednich służb (pogotowie ratunkowe, policja, straż pożarna), w zależności od sytuacji. To ogromne ułatwienie, szczególnie gdy jesteśmy zestresowani albo w nieznanym miejscu. Moim zdaniem to też ważny aspekt, że osoby z zagranicy mogą łatwo uzyskać pomoc, bo 112 jest rozpoznawalny praktycznie wszędzie w Europie. Zgodnie z przepisami unijnymi, ten numer powinien być promowany jako podstawowy do wzywania pomocy w nagłych przypadkach – stąd jego obecność nawet na automatach telefonicznych czy instrukcjach bezpieczeństwa w zakładach pracy, szkołach, komunikacji miejskiej. Dodatkowo, jeśli nie wiemy, którą dokładnie służbę wezwać, operator 112 pomoże nam to ustalić i połączy z odpowiednim dyspozytorem. Osobiście uważam, że zapamiętanie tego numeru to podstawa, bo można uratować komuś życie – nawet przez przypadek, będąc świadkiem jakiegoś wypadku czy innego zdarzenia. Warto pamiętać, że 112 działa również, gdy telefon nie ma karty SIM (chociaż nie wszędzie to się sprawdza w praktyce, to z mojego rozeznania wynika, że w Polsce powinno zadziałać).

Pytanie 40

Co to jest GraphQL?

A. Biblioteka do tworzenia grafów i diagramów w aplikacjach webowych
B. System zarządzania bazami grafowymi
C. Język zapytań do API oraz środowisko wykonawcze do obsługi tych zapytań
D. Format danych podobny do JSON używany w komunikacji między aplikacjami
Wybór odpowiedzi, która sugeruje, że GraphQL jest biblioteką do tworzenia grafów i diagramów w aplikacjach webowych, jest mylący, ponieważ nie uwzględnia fundamentalnych cech i funkcji tego narzędzia. GraphQL nie jest narzędziem graficznym, lecz technologią służącą do efektywnego zarządzania zapytaniami w API. Odpowiedź wskazująca na system zarządzania bazami grafowymi również nie odzwierciedla rzeczywistości, ponieważ GraphQL nie jest systemem bazodanowym, lecz interfejsem do komunikacji z różnymi źródłami danych, które mogą być zrealizowane przy użyciu różnych baz danych, w tym relacyjnych, NoSQL czy grafowych. Ponadto, w przypadku odpowiedzi sugerującej, że GraphQL to format danych podobny do JSON, należy podkreślić, że choć GraphQL używa JSON do przesyłania danych, jego istotą jest definicja zapytań oraz struktura danych, a nie tylko ich format. Często mylone to jest z protokołami komunikacyjnymi, takimi jak REST, które również mogą wykorzystywać JSON, ale nie oferują takiej elastyczności w zakresie kształtowania odpowiedzi, jaką zapewnia GraphQL. Takie nieporozumienia mogą prowadzić do niewłaściwego zrozumienia architektury aplikacji oraz potencjalnych ograniczeń w wydajności i użyteczności implementacji API.