Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 20 stycznia 2026 17:25
  • Data zakończenia: 20 stycznia 2026 17:42

Egzamin zdany!

Wynik: 24/40 punktów (60,0%)

Wymagane minimum: 20 punktów (50%)

Pochwal się swoim wynikiem!
Szczegółowe wyniki:
Pytanie 1

Co to jest REST API?

A. Architektura API oparta o zasoby i standardowe operacje HTTP
B. Framework do testowania API
C. Biblioteka JavaScript do komunikacji z bazami danych
D. Protokół sieciowy do transferu danych binarnych
REST API (Representational State Transfer Application Programming Interface) to architektura API, która koncentruje się na zasobach i wykorzystuje standardowe operacje HTTP, takie jak GET, POST, PUT i DELETE. Dzięki tej architekturze każdy zasób, na przykład użytkownik czy produkt, jest reprezentowany przez unikalny identyfikator URL, co ułatwia dostęp i manipulację danymi. REST API jest szeroko stosowane w aplikacjach webowych i mobilnych, ponieważ pozwala na łatwą integrację różnych systemów oraz umożliwia wykorzystanie technologii takich jak JSON i XML do wymiany danych. Przykładem praktycznego zastosowania REST API może być aplikacja do zarządzania zadaniami, w której użytkownicy mogą tworzyć, edytować i usuwać zadania za pomocą odpowiednich zapytań HTTP. Dobrą praktyką przy projektowaniu REST API jest stosowanie odpowiednich statusów HTTP, takich jak 200 (OK), 201 (Created) czy 404 (Not Found), co ułatwia komunikację między klientem a serwerem oraz zwiększa transparentność działania API. Dodatkowo, REST API jest zgodne z zasadą bezstanowości, co oznacza, że każdy nowy request zawiera wszystkie informacje potrzebne do jego przetworzenia.

Pytanie 2

W zaprezentowanym kodzie ukazano jedno z fundamentalnych założeń programowania obiektowego. Czym ono jest?

public class Owoc {
}

public class Truskawka extends Owoc {
}

public class Jablko extends Owoc {
}
Ilustracja do pytania
A. abstrakcja
B. dziedziczenie
C. polimorfizm
D. hermetyzacja
To właśnie jest klasyczny przykład dziedziczenia w programowaniu obiektowym. W tym przypadku mamy bazową klasę 'Owoc', z której dziedziczą klasy 'Truskawka' oraz 'Jablko'. Dzięki temu możemy zdefiniować wspólne cechy i zachowania dla wszystkich owoców w jednej klasie, a potem rozszerzać je w bardziej szczegółowych klasach. Moim zdaniem to jedno z najwygodniejszych założeń OOP, bo pozwala pisać kod, który jest łatwiejszy do utrzymania i rozbudowy. Jeśli kiedyś dołożysz nową funkcjonalność do wszystkich owoców, nie musisz jej wrzucać oddzielnie do każdej odmiany, tylko wystarczy, że zrobisz to raz w klasie 'Owoc'. To bardzo zgodne ze standardami SOLID i ogólnie dobrą praktyką DRY (Don't Repeat Yourself). W realnych aplikacjach, np. systemach do zarządzania magazynem, dziedziczenie pozwala łatwo rozróżnić typy produktów, a jednocześnie trzymać wspólny kod w jednym miejscu. Warto też pamiętać, że dziedziczenie to podstawa do późniejszego korzystania z polimorfizmu. Jeśli chcesz, żeby jakieś metody działały różnie w zależności od konkretnego typu owocu, wystarczy je nadpisać w podklasach. W sumie – nie da się pisać sensownych aplikacji obiektowych bez znajomości dziedziczenia, bo to daje ogromną elastyczność i porządek w kodzie.

Pytanie 3

Jaką funkcję pełnią okna dialogowe niemodalne?

A. prezentowania komunikatów, które wymagają potwierdzenia, aby kontynuować działanie aplikacji
B. wstrzymywania działania aplikacji w czasie wprowadzania oraz zatwierdzania danych
C. zarządzania stanem aplikacji za pomocą systemów menu
D. zarządzania ustawieniami aplikacji, jako okno, które pozostaje widoczne na ekranie przez cały czas trwania aplikacji
Okna dialogowe niemodalne, czasem zwane też oknami narzędziowymi albo pomocniczymi, to bardzo praktyczny element interfejsu użytkownika. To, co wyróżnia je spośród innych typów okien, to fakt, że użytkownik może korzystać równocześnie zarówno z tego okna, jak i z głównej aplikacji. Nie blokuje ono działania programu – wszystko jest dostępne w tym samym czasie. Najczęściej takie okna służą do zarządzania ustawieniami aplikacji albo wywoływania funkcji, które użytkownik może modyfikować na bieżąco, bez konieczności zamykania tego okna po każdej zmianie. Przykład z życia: paleta warstw w programach graficznych (np. GIMP czy Photoshop) albo okno stylów w edytorze tekstu. Dla mnie osobiście, taki model pracy jest dużo wygodniejszy niż korzystanie z okien modalnych, bo pozwala płynnie zmieniać ustawienia bez przerywania pracy. Dobrą praktyką w branży jest, żeby okna niemodalne nie zasłaniały kluczowych elementów interfejsu i były jasno oznaczone, by użytkownik wiedział, że może je w każdej chwili zamknąć, nie tracąc postępów. Takie podejście jest wręcz rekomendowane w wytycznych projektowania UX publikowanych przez Apple czy Microsoft (np. Human Interface Guidelines). Okna niemodalne są szczególnie ważne w aplikacjach wymagających ciągłego dostępu do narzędzi lub parametrów, np. edytorach grafiki, IDE czy programach CAD. Warto o tym pamiętać, projektując bardziej złożone systemy.

Pytanie 4

Jakie są kluczowe etapy realizacji projektu programistycznego?

A. Projektowanie, testowanie, aktualizacja, implementacja
B. Planowanie, projektowanie, debugowanie, konserwacja
C. Planowanie, analiza, implementacja, wdrożenie
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 5

Jak nazywa się proces znajdowania i usuwania błędów w kodzie?

A. Interpretowanie
B. Debugowanie
C. Kompensowanie
D. Kompilowanie
Debugowanie to niezwykle istotny etap w procesie tworzenia oprogramowania, polegający na identyfikowaniu i eliminowaniu błędów w kodzie źródłowym. Jest to proces, który wymaga zrozumienia logiki programu oraz umiejętności analitycznych, aby skutecznie odnaleźć przyczynę problemu i ją usunąć. Debugowanie jest kluczowe dla zapewnienia, że aplikacja działa zgodnie z zamierzeniami i jest wolna od błędów, które mogłyby wpłynąć na jej funkcjonalność lub stabilność. W praktyce debugowanie może obejmować różne techniki, takie jak użycie narzędzi do śledzenia wykonania kodu, analizę logów czy testowanie jednostkowe. Programiści często korzystają z dedykowanych środowisk programistycznych (IDE), które oferują funkcje ułatwiające debugowanie, takie jak punkty przerwań czy inspekcja zmiennych. Dobrym przykładem jest Visual Studio, które umożliwia śledzenie wartości zmiennych w czasie rzeczywistym. Debugowanie jest również częścią dobrych praktyk programistycznych, które zakładają regularne testowanie i kontrolę jakości kodu. Dzięki temu możliwe jest nie tylko eliminowanie błędów, ale także poprawa wydajności i bezpieczeństwa aplikacji.

Pytanie 6

Jaką strukturę danych można zrealizować, korzystając jedynie z wymienionych poniżej metod:

push(arg) – dodaje element
pop() – usuwa ostatnio dodany element
peek() – zwraca ostatnio dodany element bez usuwania
isEmpty() – sprawdza czy istnieją dane w strukturze
A. tablica
B. drzewo binarne
C. stos
D. kolejka
Stos to jedna z najbardziej podstawowych i jednocześnie użytecznych struktur danych. Wszystkie wymienione metody - push, pop, peek oraz isEmpty - są klasycznymi operacjami definiującymi właśnie stos (czyli tzw. LIFO, czyli Last-In-First-Out). Oznacza to, że ostatni element, który został dodany do stosu, będzie pierwszym usuniętym. Z mojego doświadczenia wynika, że stosy są bardzo często wykorzystywane w praktyce, na przykład przy realizacji algorytmów rekurencyjnych (zarówno w kodzie, jak i na niższym poziomie, jak stos wywołań funkcji w pamięci programu), co jest zgodne ze standardami języków programowania, takich jak C, Java czy Python. W praktycznych zastosowaniach stosów używa się m.in. przy sprawdzaniu poprawności nawiasów w wyrażeniach matematycznych, przy parsowaniu kodu, cofnięciach operacji w edytorach tekstu czy realizacji algorytmu przeszukiwania w głąb (DFS). Co ciekawe, stos można łatwo zaimplementować zarówno na tablicach dynamicznych, jak i na listach jednokierunkowych. Dobre praktyki branżowe zalecają, aby stos wykorzystywać zawsze tam, gdzie potrzebny jest szybki dostęp do ostatnio dodanego elementu i nie zachodzi potrzeba dostępu w inny sposób. Moim zdaniem, zrozumienie działania stosu to fundament dla każdego, kto serio podchodzi do programowania i algorytmiki.

Pytanie 7

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

class MojaKlasa
{
    private static int licznik;
    ...
A. pole jest związane z określoną instancją klasy i jego wartość jest unikalna tylko dla tej instancji
B. pole nie może być zmieniane w kodzie klasy
C. bieżąca wartość pola jest wspólna dla wszystkich instancji klasy
D. bieżąca wartość pola jest wspólna dla wszystkich instancji klasy i nie może być zmieniana
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 8

Którego nagłówka używamy w C++ do obsługi plików?

A. <stdio.h>
B. <fstream>
C. <iostream>
D. <fileio.h>
'<stdio.h>' to nagłówek biblioteki C, a nie C++, i jest używany do standardowych operacji wejścia i wyjścia, ale nie jest przeznaczony do pracy z plikami w stylu obiektowym. '<fileio.h>' to nieistniejący standardowy nagłówek C++ – nazwa ta może wprowadzać w błąd. '<iostream>' to biblioteka standardowa służąca do obsługi strumieni wejścia/wyjścia w konsoli (np. 'cin' i 'cout'), ale nie jest używana do pracy z plikami. Tylko 'fstream' oferuje narzędzia dedykowane do obsługi plików na dysku w języku C++.

Pytanie 9

W jakim modelu Cyklu Życia Projektu Informatycznego znajduje się etap analizy ryzyka?

A. W spiralnym
B. W modelu Fry’ego
C. W modelu z prototypem
D. W kaskadowym
Model spiralny to taki nietypowy sposób prowadzenia projektów informatycznych, gdzie ryzyko traktuje się całkiem poważnie i systemowo. Główna różnica, moim zdaniem, w porównaniu do klasycznego modelu kaskadowego czy prototypowego, polega na tym, że każda pętla spirali zaczyna się właśnie od identyfikacji i analizy ryzyka. To nie jest tylko jakaś teoria – w praktyce, na przykład w dużych projektach bankowych czy medycznych, zanim zespół zabierze się za kodowanie czy projektowanie, musi rozpoznać potencjalne zagrożenia, np. możliwe opóźnienia, niedoszacowanie kosztów, czy brak interoperacyjności systemów. Model ten mocno wpisuje się w dobre praktyki zarządzania projektami IT, bo umożliwia adaptację w trakcie realizacji, a nie dopiero na samym końcu, gdy czasami już za późno na zmiany. Według Boehma, twórcy tego modelu, analiza ryzyka jest krytyczna, bo pozwala wcześnie wykryć błędy i unikać kosztownych pomyłek. To też łączy się z zasadą iteracyjności – każda nowa faza bazuje na wnioskach z poprzedniej, co zwiększa szansę na sukces projektu. Z mojego doświadczenia wynika, że tam, gdzie analiza ryzyka jest na poważnie traktowana, projekty rzadziej zaliczają spektakularne wpadki, a zespoły są lepiej przygotowane na niespodzianki. No i szczerze mówiąc, sam model spiralny jest często bardziej przyjazny, bo pozwala na eksperymentowanie przy jednoczesnym zabezpieczeniu projektu przed katastrofą.

Pytanie 10

Jakie z wymienionych czynności można zrealizować przy pomocy składnika statycznego danej klasy?

A. Umożliwienie dzielenia pól klasy pomiędzy zaprzyjaźnione klasy
B. Tworzenie prywatnych kopii pól dla każdej instancji
C. Zachowanie wartości wspólnych dla wszystkich instancji klasy
D. Wywołanie destruktora klasy bez jej usuwania
Składnik statyczny klasy przechowuje wartości wspólne dla wszystkich instancji danej klasy. Oznacza to, że niezależnie od liczby utworzonych obiektów, istnieje tylko jedna kopia składowej statycznej, która jest współdzielona przez wszystkie instancje. Składowe statyczne są często wykorzystywane do przechowywania liczników, stałych wartości lub danych konfiguracyjnych. Metody statyczne mogą być wywoływane bezpośrednio na klasie, bez konieczności tworzenia obiektu, co czyni je niezwykle użytecznymi w przypadku funkcji narzędziowych.

Pytanie 11

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, 3, 5]
B. [2, 4]
C. 2,4
D. [1, 2, 3, 4, 5]
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 12

Aby zdefiniować zmienną, która będzie działała jako licznik instancji danej klasy, należy wprowadzenie takiego zmiennej poprzedzić słowem kluczowym

A. register
B. virtual
C. static
D. operator
Słowo kluczowe static jest absolutnie podstawą, jeśli chodzi o definiowanie zmiennych, które mają być współdzielone przez wszystkie instancje danej klasy. Gdy w klasie utworzysz zmienną statyczną, nie jest ona powiązana z żadnym konkretnym obiektem, tylko istnieje jedna taka zmienna dla całej klasy, niezależnie od liczby utworzonych obiektów. To niesamowicie przydatne, np. właśnie przy liczeniu instancji – wystarczy inkrementować taką zmienną w konstruktorze. W C++ czy Javie jest to standardowy sposób na śledzenie, ile obiektów danego typu zostało utworzonych. Z mojej perspektywy, korzystanie ze static to nie tylko wygoda, ale też sygnał dla innych programistów, że dana wartość jest globalna w kontekście klasy, a nie obiektu. Przykład praktyczny: jeżeli masz klasę Samochód i chcesz wiedzieć, ile samochodów zostało już utworzonych, to deklarujesz static int licznik; i za każdym razem, gdy konstruktor się odpala, robisz licznik++. Takie podejście jest bardzo czytelne i od razu wiadomo, o co chodzi. Warto też pamiętać, że static może być używany nie tylko do liczenia instancji, ale też do przechowywania różnych konfiguracji czy referencji do wspólnych zasobów. Zdecydowanie jest to jedna z lepszych praktyk, szczególnie kiedy program zaczyna rosnąć i zależy nam na porządku w kodzie.

Pytanie 13

Co to jest lazy loading?

A. Metoda przechowywania danych w pamięci podręcznej przeglądarki
B. Proces opóźnionego ładowania bibliotek JavaScript
C. Technika optymalizacji polegająca na ładowaniu zasobów dopiero wtedy, gdy są potrzebne
D. Algorytm kompresji obrazów w aplikacjach webowych
Odpowiedź wskazująca na technikę optymalizacji polegającą na ładowaniu zasobów dopiero wtedy, gdy są one potrzebne, jest prawidłowa, ponieważ lazy loading skutecznie zwiększa wydajność aplikacji webowych. Ta metoda minimalizuje ilość danych przesyłanych na początku ładowania strony, co znacząco poprawia czas ładowania oraz doświadczenie użytkownika. Przykładowo, w przypadku stron z dużą ilością obrazów, lazy loading zapewnia, że grafiki są pobierane tylko wtedy, gdy zbliżają się do obszaru widocznego w przeglądarce. To podejście jest zgodne z najlepszymi praktykami optymalizacji wydajności, jak określone w dokumentach Web Performance Optimization. W praktyce często implementuje się lazy loading za pomocą różnych bibliotek JavaScript, takich jak Intersection Observer API, co pozwala na efektywne zarządzanie zasobami oraz ich asynchroniczne ładowanie. Dzięki temu aplikacje mogą działać bardziej responsywnie, co jest kluczowe w czasie, gdy użytkownicy oczekują szybkiej oraz płynnej interakcji ze stronami internetowymi.

Pytanie 14

Co to jest PWA (Progressive Web App)?

A. System zarządzania treścią dla stron internetowych
B. Aplikacja webowa działająca jak natywna aplikacja mobilna
C. Framework do tworzenia aplikacji mobilnych
D. Biblioteka graficzna do tworzenia animacji
Jednym z powszechnych nieporozumień jest mylenie Progressive Web App z frameworkami do tworzenia aplikacji mobilnych, takimi jak React Native czy Flutter. Te frameworki pozwalają na tworzenie natywnych aplikacji, które działają na platformach mobilnych i wykorzystują ich natywne API, podczas gdy PWA jest technologią webową, która działa w przeglądarkach internetowych, niezależnie od systemu operacyjnego urządzenia. Ponadto, niektóre osoby mogą myśleć, że PWA to system zarządzania treścią (CMS), co jest błędem. CMS, jak WordPress czy Joomla, skupiają się na tworzeniu i zarządzaniu treścią stron internetowych, natomiast PWA są aplikacjami zaprojektowanymi dla użytkowników, które wykorzystują technologię webową do zapewnienia natywnego doświadczenia. Inne odpowiedzi sugerują, że PWA to biblioteka graficzna, co również jest mylną interpretacją. PWA nie jest narzędziem do tworzenia animacji, ale raczej kompletnym podejściem do budowy aplikacji internetowych, które mogą działać offline i oferować natywne funkcjonalności. Kluczowym błędem myślowym jest brak zrozumienia, że PWA nie polega na technologiach służących do tworzenia aplikacji mobilnych, lecz na wykorzystaniu możliwości nowoczesnych przeglądarek w celu dostarczenia użytkownikom aplikacji działającej płynnie i efektywnie, z poprawioną dostępnością i użytecznością.

Pytanie 15

Jaką wartość ma zmienna b po wykonaniu poniższego kodu?

int a = 1, b = 20, c = 3;
while (a <= 10) {
    b = b - c;
    a += 2;
}
A. 20
B. 5
C. 2
D. 11
Powszechnym błędem w rozwiązywaniu tego typu zadań jest nieuwzględnienie wszystkich kroków pętli oraz niepoprawne obliczenie liczby iteracji. Można łatwo przeoczyć fakt jak często pętla się wykonuje i w jaki sposób zmieniają się wartości zmiennych. W przypadku przedstawionego kodu zmienna a początkowo wynosi 1 i zwiększa się o 2 w każdej iteracji aż do przekroczenia wartości 10. To oznacza że pętla wykona się pięć razy. Każdy przebieg pętli zmniejsza wartość b o 3 z powodu operacji b = b - c gdzie c jest równe 3. Jeśli nie uwzględni się wszystkich pięciu iteracji można błędnie wywnioskować inną wartość końcową b. Poprawne zrozumienie działania pętli while i operacji arytmetycznych w niej zawartych jest kluczowe w programowaniu. Takie pomyłki pokazują znaczenie czytelności i precyzji w analizie kodu oraz przypominają o konieczności dokładnego śledzenia zmian w zmiennych w czasie trwania pętli aby poprawnie przewidzieć wynik końcowy. Kluczowym standardem w branży jest testowanie kodu i ręczne śledzenie jego działania zwłaszcza w kontekście algorytmów iteracyjnych co pozwala na uniknięcie błędnych założeń i wyników.

Pytanie 16

Jakie znaczenie ma przystosowanie interfejsu użytkownika do różnych platform?

A. Umożliwia skoncentrowanie się wyłącznie na funkcjonalności aplikacji
B. Gwarantuje optymalne korzystanie z aplikacji na każdym urządzeniu
C. Usuwa konieczność testowania na różnych platformach
D. Pozwala na unifikację kodu niezależnie od używanej platformy
Dostosowanie interfejsu do różnych urządzeń to naprawdę ważna sprawa, żeby wszystko działało jak należy. Aplikacje, które dobrze się przystosowują do różnych ekranów czy systemów, dają lepsze doświadczenie użytkownikom. Użycie takich technik jak responsywny design czy elastyczne układy, jak flexbox czy grid, to super pomysł. Dzięki temu elementy interfejsu same się skalują, a aplikacja wygląda spójnie na telefonach, tabletach i komputerach. Nie ma nic gorszego niż chaotyczny interfejs na różnych urządzeniach, więc to naprawdę kluczowa kwestia.

Pytanie 17

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. Z tablicy liczby usuwane są elementy, z każdym obiegiem pętli eliminowany jest element z jej końca.
B. Do tablicy liczby, na jej końcu, dodawane są nowe wartości.
C. Do tablicy liczby, na jej początku, dodawane są nowe wartości.
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 18

Jakie są kluczowe zasady WCAG 2.0?

A. Elastyczna, prosta, przejrzysta, trwała
B. Ewolucyjna, interaktywna, efektywna
C. Dostosowana, błyskawiczna, mobilna, dostępna
D. Percepcyjna, operacyjna, zrozumiała, solidna
Zasady WCAG 2.0, czyli Wytycznych dotyczących dostępności treści internetowych, skupiają się na zapewnieniu, że strony internetowe są dostępne dla wszystkich użytkowników, niezależnie od ich zdolności. Główne zasady to percepcyjna, operacyjna, zrozumiała i solidna. Percepcyjna oznacza, że ​​wszystkie elementy na stronie muszą być przedstawione w sposób, który umożliwia ich percepcję przez różne zmysły, takie jak wzrok i słuch. Na przykład, tekst alternatywny dla obrazów pozwala osobom niewidomym zrozumieć zawartość wizualną. Operacyjna dotyczy interakcji użytkownika z treścią; nawigacja powinna być intuicyjna, a elementy interaktywne łatwo osiągalne. Zrozumiała oznacza, że ​​treść powinna być zrozumiała dla wszystkich użytkowników, co można osiągnąć poprzez prosty język i jasne instrukcje. Solidna koncentruje się na tym, aby treść była wystarczająco elastyczna, aby działała w różnych przeglądarkach i urządzeniach, co jest kluczowe w dobie różnorodności technologii. Przykładem wdrożenia tych zasad może być wykorzystanie ARIA (Accessible Rich Internet Applications), które wspomagają dostępność dynamicznych treści w aplikacjach internetowych.

Pytanie 19

Jaką technologię stosuje się do powiązania aplikacji internetowej z systemem baz danych?

A. HTTP
B. SQL
C. CSS
D. JavaScript
SQL, czyli język do zarządzania danymi, to mega ważna rzecz, jeśli chodzi o relacyjne bazy danych. Dzięki niemu można tworzyć, modyfikować, a nawet usuwać tabele. To taki most, który łączy aplikacje webowe z bazą danych. Dzięki SQL programiści mogą łatwo przechowywać i przetwarzać różne informacje na serwerze. Przykłady? Można generować listy produktów, ogarniać użytkowników czy analizować dane z transakcji. Właściwie bez SQL-a nie dałoby się zbudować solidnych aplikacji, na przykład tych, które działają na MySQL, PostgreSQL czy Microsoft SQL Server. Chociaż pewnie o tym wiesz, ale warto to zaznaczyć.

Pytanie 20

Który z algorytmów ma złożoność O(n²)?

A. Bubble Sort
B. Binary Search
C. Dijkstra
D. Merge Sort
Bubble Sort to algorytm o złożoności O(n²), co oznacza, że jego czas wykonania rośnie kwadratowo wraz ze wzrostem liczby elementów wejściowych. Algorytm porównuje sąsiadujące elementy i zamienia je miejscami, jeśli są w złej kolejności. Proces ten powtarza się wielokrotnie, aż do uzyskania pełnego posortowania tablicy. Ze względu na swoją prostotę, Bubble Sort jest często wykorzystywany do nauki podstaw algorytmiki, ale w praktyce rzadko stosuje się go do sortowania dużych zbiorów danych, ponieważ jest nieefektywny w porównaniu do bardziej zaawansowanych algorytmów, takich jak QuickSort czy Merge Sort.

Pytanie 21

Jaką cechą odznacza się framework w porównaniu do biblioteki?

A. Framework stanowi zbiór funkcji, które programista ma możliwość wykorzystania
B. Framework zapewnia API do szerszego zestawu funkcji
C. Framework oferuje funkcje użyteczne w konkretnej dziedzinie problemu
D. Framework określa strukturę aplikacji i zapewnia jej fundament
Biblioteka to zestaw funkcji i klas, które programista może wykorzystywać według własnego uznania, ale to on decyduje o strukturze aplikacji. API dostarcza zestaw metod do komunikacji z innymi aplikacjami, ale nie narzuca architektury. Framework to coś więcej niż zbiór funkcji – określa cały proces tworzenia aplikacji, czego nie można powiedzieć o zwykłej bibliotece lub narzędziach użytkowych.

Pytanie 22

Która z poniższych technologii jest używana do tworzenia interfejsów użytkownika w aplikacjach React?

A. XML
B. JSX
C. YAML
D. Markdown
JSX, czyli JavaScript XML, jest rozbudowanym rozszerzeniem składni JavaScript, które pozwala na pisanie kodu, który przypomina HTML. JSX jest kluczowym elementem w budowaniu interfejsów użytkownika w aplikacjach React, ponieważ łączy logikę z prezentacją. Dzięki JSX można tworzyć komponenty React w sposób bardziej intuicyjny i czytelny, co przyspiesza proces tworzenia aplikacji. Na przykład, zamiast używać funkcji `React.createElement()`, można po prostu zapisać komponent w formie znaczników, co sprawia, że kod jest bardziej zrozumiały. Dodatkowo, JSX umożliwia wstawianie kodu JavaScript bezpośrednio w znacznikach, co pozwala na dynamiczne renderowanie treści. Praktyka korzystania z JSX stała się standardem w ekosystemie React, ponieważ ułatwia zarządzanie stanem i właściwościami komponentów, co jest zgodne z najlepszymi praktykami branżowymi.

Pytanie 23

Co to jest Redux?

A. Framework do tworzenia aplikacji mobilnych
B. Biblioteka do zarządzania stanem aplikacji w JavaScript
C. System kontroli wersji dla projektów JavaScript
D. Narzędzie do optymalizacji wydajności aplikacji React
Chociaż odpowiedzi związane z frameworkami do tworzenia aplikacji mobilnych, narzędziami do optymalizacji wydajności czy systemami kontroli wersji mogą być interesujące, nie są one związane z funkcją, jaką pełni Redux. Frameworki do tworzenia aplikacji mobilnych, takie jak React Native, pozwalają na rozwijanie aplikacji mobilnych z użyciem JavaScript, ale nie zarządzają one stanem aplikacji w sposób, w jaki robi to Redux. Optymalizacja wydajności aplikacji React nie jest bezpośrednią funkcją Redux; chociaż biblioteka ta może pośrednio przyczynić się do lepszej wydajności przez poprawne zarządzanie stanem, nie jest narzędziem służącym do optymalizacji. Z kolei systemy kontroli wersji, takie jak Git, służą do zarządzania historią zmian w kodzie źródłowym aplikacji, a nie do zarządzania stanem wykonawczej logiki aplikacji. Wybór niewłaściwego narzędzia wynika często z braku zrozumienia ich funkcji oraz zastosowania w procesie tworzenia aplikacji. Aby skutecznie zarządzać stanem w aplikacji, kluczowe jest zrozumienie różnic między tymi narzędziami oraz ich zastosowaniem w architekturze aplikacji, co jest fundamentalnym elementem współczesnego rozwijania oprogramowania.

Pytanie 24

W przedstawionym filmie ukazano kreator interfejsu użytkownika, dla którego automatycznie powstaje

A. kod XML
B. kod Java
C. obsługa przycisku ekranu dotykowego
D. obsługa wciśniętego przycisku
Często można się pomylić, sądząc, że narzędzia do projektowania interfejsów użytkownika generują od razu kod w takich językach jak Java czy implementują obsługę konkretnych zdarzeń, np. wciśnięcia przycisku. Z mojego doświadczenia wynika, że to jeden z najczęstszych błędów myślowych na początku nauki programowania. W praktyce, narzędzia typu drag&drop koncentrują się na warstwie prezentacyjnej – opisują, jak mają wyglądać poszczególne elementy, ale nie zajmują się logiką działania. Kod Java albo inny kod źródłowy odpowiedzialny za obsługę zdarzeń czy funkcjonalności aplikacji musi być dopisany ręcznie przez programistę. Automatyczne generowanie kodu logicznego przez edytory graficzne jest raczej niezalecane, bo prowadzi do trudnego w utrzymaniu kodu i sprawia, że aplikacja traci na przejrzystości. Jeśli chodzi o obsługę wciśnięcia przycisku czy przycisku ekranu dotykowego, to są to akcje, które definiuje się później w kodzie źródłowym – na przykład poprzez implementację listenerów w kodzie Java w Androidzie albo przez bindingi w innych frameworkach. Te narzędzia mają za zadanie generować opis struktury interfejsu, a nie jego zachowanie. Często spotyka się też przekonanie, że to właśnie kod Java stanowi podstawę aplikacji – oczywiście to prawda, ale nie w kontekście automatycznego generowania przez narzędzia graficzne; one skupiają się na XML, który jest dużo bardziej uniwersalny do takich celów. Moim zdaniem najlepszą praktyką jest wyraźne oddzielenie warstwy prezentacji (np. XML) od logiki biznesowej i ręcznego kodowania zdarzeń, bo to pozwala na wygodne rozwijanie i utrzymywanie aplikacji, szczególnie w większych zespołach.

Pytanie 25

Jakie stwierdzenie najlepiej tłumaczy cel podziału programu na funkcje (metody)?

A. Eliminuje potrzebę korzystania ze zmiennych globalnych
B. Gwarantuje automatyczną kompilację programu
C. Umożliwia skrócenie kodu przez eliminację wszelkich komentarzy
D. Ułatwia proces debugowania oraz ponowne wykorzystanie fragmentów kodu
Dzielenie programu na funkcje (lub metody) jest jedną z kluczowych zasad programowania strukturalnego i obiektowego. Funkcje pozwalają na podzielenie dużych bloków kodu na mniejsze, łatwiejsze do zarządzania i ponownego wykorzystania fragmenty. Dzięki temu kod jest bardziej czytelny, zrozumiały i łatwiejszy do testowania. Ułatwia to także proces debugowania, ponieważ błędy można izolować w konkretnych funkcjach, zamiast przeszukiwać cały program. Ponadto funkcje umożliwiają wielokrotne używanie tego samego fragmentu kodu, co zwiększa efektywność i eliminuje konieczność powielania kodu, zmniejszając ryzyko błędów.

Pytanie 26

Które z wymienionych poniżej błędów podczas wykonywania programu można obsłużyć poprzez zastosowanie wyjątków?

A. Niekompatybilność typów danych w kodzie
B. Błąd kompilacyjny
C. Błąd w składni
D. Błąd dzielenia przez zero
W języku C++ wyjątki pozwalają na obsługę błędów wykonania, takich jak dzielenie przez zero. Jest to klasyczny przykład błędu, który może prowadzić do nieprzewidywalnych rezultatów lub awarii programu. Dzięki użyciu wyjątków można zapobiec katastrofalnym skutkom takich błędów, przekierowując sterowanie do odpowiedniego bloku 'catch', gdzie można podjąć działania naprawcze lub zakończyć program w kontrolowany sposób. Obsługa błędów takich jak dzielenie przez zero jest kluczowa w programowaniu niskopoziomowym i aplikacjach wymagających wysokiej niezawodności.

Pytanie 27

Jakie określenie w programowaniu obiektowym odnosi się do "zmiennej klasy"?

A. Metoda
B. Konstruktor
C. Pole
D. Obiekt
Obiekt to instancja klasy, która posiada swoje pola i metody, ale sam w sobie nie jest zmienną klasy – jest to jednostka przechowująca dane i wykonująca operacje. Metoda to funkcja należąca do klasy, która definiuje zachowanie obiektu, ale różni się od pola, które przechowuje dane. Konstruktor to specjalna metoda klasy, która jest wywoływana podczas tworzenia obiektu i służy do inicjalizacji jego pól, ale sam w sobie nie jest zmienną klasy – raczej definiuje, jak te zmienne są ustawiane podczas tworzenia obiektu.

Pytanie 28

Jak oddziaływanie monotonnego środowiska pracy może wpłynąć na organizm człowieka?

A. Wzrost poziomu motywacji
B. Obniżenie koncentracji oraz zwiększone ryzyko popełniania błędów
C. Poprawa kondycji fizycznej
D. Zwiększenie odporności na stres
Kiedy w pracy ciągle powtarzamy te same czynności, to może nas to naprawdę zniechęcać. Zauważyłem, że takie monotonne środowisko potrafi sprawić, że gorzej się skupiamy i łatwiej popełniamy błędy. Jeśli pracownicy cały czas robią to samo bez żadnych zmian, to szybko tracą zapał i nie są zadowoleni z tego, co robią. Moim zdaniem, warto czasem zmieniać zadania, żeby wprowadzić trochę świeżości i wyzwań. Dobrze jest też organizować przerwy, bo to pomaga nabrać energii oraz zadbać o fajną atmosferę w pracy.

Pytanie 29

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

A. Zwiększenie wartości zmiennej o 1
B. Porównanie dwóch wartości
C. Przypisanie wartości do zmiennej
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 30

Którą konwencję nazewnictwa najczęściej stosuje się w JavaScript?

A. snake_case
B. PascalCase
C. camelCase
D. kebab-case
Wybór konwencji nazewnictwa ma kluczowe znaczenie dla czytelności i utrzymania kodu, a błędne podejście do tego tematu może prowadzić do poważnych nieporozumień. Snake_case, który polega na oddzielaniu słów za pomocą podkreślników (np. `user_name`), jest popularny w językach takich jak Python, ale nie jest powszechnie akceptowany w JavaScript. Użycie tej konwencji w JavaScript może skutkować niekonsekwencjami w kodzie, zwłaszcza gdy współpracuje się z innymi programistami, którzy mogą oczekiwać stosowania camelCase jako standardu. Z kolei PascalCase, w którym każde słowo zaczyna się dużą literą, jest zazwyczaj używany w kontekście nazywania klas (np. `UserProfile`). Choć jest to przydatne, nie jest to konwencja dla zmiennych czy funkcji, co może prowadzić do niejasności, jeśli nie stosuje się jej zgodnie z ogólnie przyjętymi zasadami. Kebab-case, będący inną formą separacji słów przy pomocy myślników (np. `user-name`), jest najczęściej stosowany w nazwach URL i nie jest zgodny z konwencjami JavaScript. Dlatego stosowanie tych nieodpowiednich konwencji może prowadzić do trudności w utrzymaniu kodu, a także może wpływać na błędy w współpracy z innymi narzędziami i bibliotekami, które oczekują zgodności z camelCase.

Pytanie 31

Która z wymienionych właściwości odnosi się do klasy pochodnej?

A. Nie ma możliwości dodawania nowych metod
B. Dziedziczy atrybuty i metody z klasy bazowej
C. Jest automatycznie usuwana po zakończeniu działania programu
D. Nie może być zastosowana w strukturze dziedziczenia
Cechą klasy pochodnej jest dziedziczenie pól i metod z klasy bazowej, co oznacza, że klasa pochodna automatycznie uzyskuje dostęp do wszystkich publicznych i chronionych składowych klasy nadrzędnej. Dzięki temu programista może rozwijać i modyfikować funkcjonalność istniejących klas, tworząc bardziej wyspecjalizowane obiekty. Dziedziczenie to kluczowy mechanizm umożliwiający wielokrotne użycie kodu, co prowadzi do zmniejszenia duplikacji i zwiększenia efektywności w zarządzaniu projektem. Klasa pochodna może również nadpisywać metody klasy bazowej, dostosowując ich działanie do swoich specyficznych potrzeb.

Pytanie 32

Wskaż język programowania, który pozwala na stworzenie aplikacji mobilnej w środowisku Android Studio?

A. Java
B. Objective-C
C. Swift
D. C++
Objective-C, język stworzony głównie dla systemów Apple, nie jest odpowiedni dla aplikacji na Androida. Jest to język obiektowy, który opiera się na C i wprowadza dynamiczne właściwości, jednak jego użycie jest ograniczone do platform iOS, co sprawia, że nie może być używany w Android Studio. Kolejnym językiem, C++, to język ogólnego przeznaczenia, który jest używany w wielu dziedzinach, w tym w programowaniu systemowym oraz w grach. Choć możliwe jest tworzenie aplikacji na Androida w C++, zwykle wykorzystuje się go w połączeniu z JNI (Java Native Interface), co może wprowadzać złożoność i wymagać dodatkowej konfiguracji. C++ nie jest językiem preferowanym dla większości aplikacji mobilnych na Androida, ponieważ Android Studio jest zoptymalizowane pod kątem Javy. Z kolei Swift, nowoczesny język programowania od Apple, jest stworzony dla iOS i macOS, co sprawia, że jego użycie w kontekście aplikacji Android jest całkowicie nieodpowiednie. Swift jest językiem wysokiego poziomu, który wspiera bezpieczne programowanie, ale nie ma żadnego wsparcia ani integracji z Android Studio. W sumie, wszystkie wymienione języki są niewłaściwe w kontekście tworzenia aplikacji na Androida, gdzie najskuteczniejszym i najbardziej optymalnym rozwiązaniem pozostaje Java.

Pytanie 33

W programie stworzonym w języku C++ trzeba zadeklarować zmienną, która będzie przechowywać wartość rzeczywistą. Jakiego typu powinna być ta zmienna?

A. numeric
B. double
C. number
D. int
Intuicyjnie można by pomyśleć, że każda zmienna liczbową da się zadeklarować przez int, bo przecież to najprostszy i najpopularniejszy typ w języku C++. Jednak int przechowuje wyłącznie liczby całkowite – nie pozwala na zapis ułamków czy wartości dziesiętnych. To bardzo częsty błąd początkujących programistów, którzy próbują przechować 7.5 w int i są zaskoczeni, że wynik zawsze jest zaokrąglany w dół. Równie problematyczne są próby użycia typów, które wyglądają na sensowne, ale w rzeczywistości nie istnieją w C++. Przykłady to number i numeric – brzmią profesjonalnie, można je spotkać w innych językach (np. number w JavaScript), ale C++ nie przewiduje takich deklaracji. Kompilator po prostu zgłosi błąd i nie skompiluje programu. Z mojego doświadczenia, wielu uczniów daje się nabrać na te angielskie słówka, bo wydają się logiczne. Tymczasem C++ ma ścisłe zasady i ogranicza się do konkretnych typów jak int, float, double czy long double. Jeśli chodzi o double, to jest to oficjalnie wspierany przez standard ISO typ do zmiennych rzeczywistych, stosowany wszędzie tam, gdzie float nie daje wystarczającej precyzji. Warto też zauważyć, że korzystanie z nieistniejących typów prowadzi do błędów kompilacji, co jest nie tylko stratą czasu, ale i może utrudnić dalszą naukę programowania, bo utrwala złe nawyki. Podsumowując, jeśli chcesz przechowywać liczby rzeczywiste w C++, musisz użyć double lub ewentualnie float, a nie int, number czy numeric – te ostatnie po prostu w tym języku nie działają.

Pytanie 34

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

A. atrybutów klasy
B. destruktorów
C. funkcji zaprzyjaźnionych
D. metod klasy
Słowo kluczowe 'virtual' w C++ i C# służy przede wszystkim do deklarowania metod w klasach, które mogą być nadpisywane przez klasy pochodne. Dzięki temu mechanizmowi możliwa jest polimorfizm, czyli jedna z najważniejszych cech programowania obiektowego. Przykład z życia: gdy masz klasę bazową 'Zwierze' z wirtualną metodą 'DajGlos()', to możesz nadpisać tę metodę w klasach potomnych, takich jak 'Pies' czy 'Kot', i każdy z tych obiektów zareaguje inaczej po wywołaniu tej samej funkcji. To jest bardzo przydatne na co dzień, szczególnie gdy projektujesz rozbudowane systemy, w których klasy dziedziczą po sobie zachowania i interfejsy. Moim zdaniem, w C# sprawa jest trochę bardziej uporządkowana niż w C++, bo tam wszystko z tym 'virtual' i 'override' jest jasno określone. W C++ można się czasem nieźle pomylić, jeśli się zapomni o 'virtual', zwłaszcza przy złożonych hierarchiach dziedziczenia. Dobrą praktyką jest zawsze dodawać 'virtual' do tych metod w klasach, które przewidujesz jako bazowe, nawet jeśli na początku nie planujesz dziedziczenia. To z czasem bardzo ułatwia utrzymanie i rozwijanie kodu. Jeszcze taka ciekawostka – w C++ także destruktory mogą być wirtualne i czasem o tym się zapomina, ale na tym poziomie podstawowym, to właśnie metody klasy są tym, do czego 'virtual' najczęściej się stosuje.

Pytanie 35

Jakie jest główne zadanie ochrony danych osobowych?

A. Zabezpieczenie danych osobowych przed nieautoryzowanym dostępem i ich wykorzystaniem
B. Gwarantowanie anonimowości dla internautów
C. Utrudnianie działalności organom ścigania
D. Udostępnianie danych osobowych w celach marketingowych
Ochrona danych osobowych przed nieuprawnionym dostępem i wykorzystaniem to podstawowy cel ochrony danych osobowych. Zasady ochrony prywatności, takie jak RODO (GDPR), zapewniają użytkownikom prawo do kontroli nad swoimi danymi i decydowania, kto może je przetwarzać. Firmy i organizacje muszą wdrażać środki techniczne oraz organizacyjne, aby zabezpieczyć dane przed wyciekiem, kradzieżą i nadużyciami. Przestrzeganie tych zasad nie tylko chroni jednostki, ale również buduje zaufanie klientów do przedsiębiorstw.

Pytanie 36

Jakie obliczenia można wykonać za pomocą poniższego algorytmu, który operuje na dodatnich liczbach całkowitych?

Ilustracja do pytania
A. sumę cyfr wprowadzonej liczby
B. największy wspólny dzielnik wprowadzonej liczby
C. liczbę cyfr w wprowadzonej liczbie
D. sumę wprowadzonych liczb
Analizując algorytm przedstawiony na schemacie, łatwo zauważyć, że nie wykonuje on ani sumowania cyfr, ani nie oblicza największego wspólnego dzielnika, ani nie sumuje wprowadzonych liczb. W praktyce mylenie tych operacji wynika często z pobieżnego czytania algorytmu lub automatycznego kojarzenia słowa „wynik” z sumą. Jednak podstawą analizy algorytmów zawsze powinno być zwracanie uwagi na konkretne instrukcje i sposób przetwarzania danych. W tym przypadku liczba jest dzielona przez 10 w każdej iteracji pętli, a licznik jest zwiększany o jeden za każdym razem, gdy to się dzieje. Nie ma tu żadnego dodawania poszczególnych cyfr, co wyklucza sumowanie cyfr. Nie pojawia się przetwarzanie wielu różnych liczb, więc niemożliwe jest sumowanie wprowadzonych liczb – algorytm pracuje wyłącznie na jednej wartości podanej na wejściu. Narzędzie do obliczania największego wspólnego dzielnika musiałoby operować na dwóch liczbach i wykorzystywać inne operacje, jak reszta z dzielenia. Typowym błędem jest też utożsamianie każdej pętli z operacją sumowania lub łączenia danych, co w tym przypadku nie ma uzasadnienia merytorycznego. Kluczowe jest przy analizie algorytmów zwracanie uwagi na to, jakie operacje są wykonywane w każdej iteracji i czy pojawia się obsługa wielu wartości, czy tylko jednej. Z mojego doświadczenia wynika, że takie drobne błędy myślowe prowadzą często do fałszywych wniosków, dlatego warto dokładnie czytać algorytm krok po kroku i analizować, do czego rzeczywiście prowadzą poszczególne instrukcje. W tym przypadku algorytm po prostu liczy liczbę dziesiętnych „pozycji” w liczbie aż do jej wyzerowania, co odpowiada liczbie cyfr, a nie żadnej z pozostałych interpretacji.

Pytanie 37

Na jakim etapie cyklu życia projektu tworzony jest szczegółowy opis wymagań funkcjonalnych oraz niefunkcjonalnych?

A. Planowanie
B. Weryfikacja
C. Wdrożenie
D. Analiza
Etap analizy to kluczowy moment w cyklu życia projektu, gdy powstaje szczegółowy opis wymagań funkcjonalnych i niefunkcjonalnych. W praktyce, właśnie wtedy zbierane są wszelkie informacje od interesariuszy – klient opowiada, czego oczekuje, a zespół projektowy zadaje mnóstwo pytań, by naprawdę zrozumieć potrzeby. Moim zdaniem to najważniejsza faza, bo jeśli coś pójdzie nie tak na tym etapie, to cała reszta projektu może się sypnąć. Analiza wymagań to nie tylko spisanie kilku zdań – tu trzeba dokładnie określić, co system ma robić (czyli funkcjonalności, np. użytkownik może dodać produkt do koszyka), oraz jakie ma mieć cechy pozafunkcjonalne, jak wydajność czy bezpieczeństwo. Dobre praktyki, jak np. BABOK czy normy ISO/IEC 29148, podkreślają, że precyzyjna analiza wymagań pozwala uniknąć kosztownych poprawek na późniejszych etapach. W rzeczywistych projektach IT korzysta się często z narzędzi typu diagramy przypadków użycia, user stories albo specyfikacje wymagań – wszystko po to, żeby nie było niejasności. Uczciwie powiem, że im więcej czasu i uwagi poświęci się na analizę, tym mniej niespodzianek pojawi się dalej. Warto to mieć na uwadze.

Pytanie 38

Programista pragnie wybrać algorytm, który najszybciej przetwarza dane w jego aplikacji. Na podstawie złożoności obliczeniowej przedstawionej w tabeli, należy wskazać algorytm numer

Algorytm 1O(n²)
Algorytm 2O(n!)
Algorytm 3O(n³)
Algorytm 4O(n)
Algorytm 5O(n²)
A. 1 lub 5
B. 3
C. 2 lub 3
D. 4
Wybierając algorytm o najniższej złożoności obliczeniowej, zawsze warto patrzeć na oznaczenia w notacji dużego O. O(n) oznacza, że czas wykonywania algorytmu rośnie liniowo wraz z rozmiarem danych wejściowych. To zdecydowanie najlepszy wynik z dostępnych, szczególnie jeśli porównać do O(n²), O(n³) albo już totalnie niepraktycznego przy większych n: O(n!). Dlatego Algorytm 4, który ma złożoność O(n), to najrozsądniejszy wybór, jeśli zależy nam na szybkości działania programu. Z mojego doświadczenia, właśnie takie algorytmy są wykorzystywane np. do przetwarzania dużych zbiorów danych w aplikacjach webowych albo w sytuacjach, gdzie liczy się czas odpowiedzi dla użytkownika końcowego. W branży IT, jeśli tylko można zejść poniżej złożoności kwadratowej – raczej zawsze warto to zrobić. Oczywiście, sama złożoność to nie wszystko – czasem prostszy, liniowy algorytm może mieć duże stałe ukryte w implementacji, ale w praktyce O(n) to standard optymalny. Warto też pamiętać, że w rekrutacjach często padają pytania o takie porównania złożoności, bo to podstawowa wiedza każdego programisty. Takie podejście pozwala budować skalowalne systemy, które nie „duszą się” przy większej ilości danych. Moim zdaniem, to jedna z tych rzeczy, które naprawdę się przydają w codziennej pracy.

Pytanie 39

Użycie modyfikatora abstract w definicji metody w klasie wskazuje, że

A. dziedziczenie po tej klasie jest niedozwolone
B. klasa ta stanowi podstawę dla innych klas
C. klasy pochodne nie mogą implementować tej metody
D. trzeba zaimplementować tę metodę w tej klasie
Modyfikator abstract w definicji metody jasno wskazuje, że dana klasa jest przeznaczona do dalszego dziedziczenia i stanowi coś w rodzaju szablonu dla innych klas. W praktyce – jeśli w klasie pojawia się choć jedna metoda abstract, cała klasa musi być także oznaczona jako abstract. To taki sygnał: hej, tej klasy nie da się użyć bezpośrednio, ale możesz po niej dziedziczyć i dopiero tam zaimplementować szczegóły. Moim zdaniem to bardzo wygodne, bo pozwala z góry narzucić kontrakt na klasy pochodne – mają dostarczyć własne wersje abstrakcyjnych metod. W wielu językach obiektowych, jak C# czy Java, stosowanie klas abstrakcyjnych jest powszechną praktyką przy projektowaniu rozbudowanych aplikacji, gdzie ważne jest rozdzielenie ogólnej logiki od szczegółowych implementacji. Daje to sporą elastyczność i chroni przed przypadkowymi błędami, kiedy ktoś próbowałby utworzyć obiekt klasy, która nie ma pełnej funkcjonalności. Często spotyka się to np. przy projektowaniu hierarchii typu Zwierzę → Pies/Kot, gdzie klasa Zwierzę jest abstrakcyjna i zawiera np. metodę abstract WydajDźwięk(). Dzięki temu każde konkretne zwierzę musi zaimplementować własną wersję tej metody, a całość kodu jest czytelniejsza i łatwiej ją rozwijać. Zdecydowanie warto poznać ten mechanizm, bo to fundament nowoczesnego programowania obiektowego i coś, co codziennie przydaje się w pracy programisty.

Pytanie 40

1 terabajt (TB) to ile gigabajtów (GB)?

A. 512
B. 1000
C. 2048
D. 1024
No to fajnie, że trafiłeś w temat! 1 terabajt (TB) to 1024 gigabajty (GB), co wynika z systemu binarnego, który w IT jest najczęściej używany. Trochę technicznie mówiąc, 1 TB to tak naprawdę 2^40 bajtów, co daje nam ogromną liczbę – dokładnie 1 099 511 627 776 bajtów. Jak podzielisz to przez 1 073 741 824 bajtów, które to są 1 GB, to wyjdzie 1024 GB. Warto wiedzieć, że w świecie komputerów i systemów operacyjnych operujemy głównie na tym systemie binarnym. Ale uwaga, bo producenci dysków często podają pojemności w systemie dziesiętnym, i wtedy 1 TB to jakby 1 000 GB. To może wprowadzać zamieszanie, więc dobrze jest sprawdzać specyfikacje i mieć to na uwadze, żeby nie było nieporozumień. Większość systemów, jak Windows czy Linux, działa w tym binarnym, więc warto to znać, gdyż to ułatwia pracę zarówno użytkownikom, jak i fachowcom z branży IT.