Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 29 kwietnia 2026 10:16
  • Data zakończenia: 29 kwietnia 2026 10:35

Egzamin niezdany

Wynik: 18/40 punktów (45,0%)

Wymagane minimum: 20 punktów (50%)

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

Do stworzenia zbioru danych potrzebnego do uruchomienia algorytmu sortowania bąbelkowego tablicy, wymagane są przynajmniej następujące typy:

A. jeden tablicowy, jeden liczbowy do nadzorowania pętli, dwa do zamiany miejscami elementów
B. jeden tablicowy, dwa liczbowe do nadzorowania pętli, jeden do zamiany miejscami elementów
C. dwa tablicowe, dwa do zamiany miejscami elementów
D. dwa tablicowe, jeden liczbowy do nadzorowania pętli
Analizując temat tworzenia zbioru danych do sortowania bąbelkowego, nietrudno zauważyć kilka typowych nieporozumień. Spotykam się z nimi dość często, szczególnie u początkujących. Przede wszystkim, używanie jedynie jednego indeksu liczbowego do sterowania pętlą to stanowczo za mało – bubble sort opiera się przecież na dwóch przebiegach przez tablicę: zewnętrznym i wewnętrznym. Jedna zmienna sterująca nie jest w stanie ogarnąć tego mechanizmu, bo tracimy kontrolę nad porównywaniem odpowiednich elementów. Z drugiej strony, stosowanie dwóch tablic do sortowania tego samego zbioru to zupełnie niepotrzebne komplikacje i nieefektywność pamięciowa. Algorytm sortowania bąbelkowego sortuje 'in-place', czyli bez przenoszenia danych między różnymi tablicami – całość odbywa się w jednej strukturze danych. Często pojawia się też przekonanie, że do zamiany elementów trzeba dwóch oddzielnych zmiennych, co jest trochę błędnym tropem. Do zamiany miejscami wystarcza jedna zmienna tymczasowa; bardziej rozbudowane podejścia niepotrzebnie zaśmiecają kod. Pewną pułapką jest także myślenie, że liczba zmiennych sterujących pętlami można ograniczyć – w praktyce dla pełnej kontroli i zachowania standardów potrzebujemy dwóch liczbowych indeksów. Wśród branżowych dobrych praktyk przyjęło się nie tylko używanie minimum niezbędnych zmiennych, ale także dbanie o czytelność kodu i unikanie zbędnych komplikacji – bo to ułatwia późniejsze utrzymanie i zrozumienie algorytmu, zwłaszcza gdy kod przekazywany jest dalej. Moim zdaniem, te nieporozumienia wynikają z chęci uproszczenia algorytmu lub braku doświadczenia z klasycznymi, zagnieżdżonymi pętlami. Warto poświęcić chwilę, żeby prześledzić działanie sortowania bąbelkowego krok po kroku na kartce – wtedy od razu widać, ile i jakich zmiennych naprawdę potrzeba, żeby całość działała sprawnie i zgodnie ze sztuką programowania.

Pytanie 2

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

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

Pytanie 3

Jaki framework jest powszechnie wykorzystywany do rozwijania aplikacji desktopowych w języku C++?

A. Node.js
B. WPF
C. Flutter
D. Qt
Node.js to środowisko uruchomieniowe dla języka JavaScript, przeznaczone do tworzenia aplikacji serwerowych i skryptów backendowych, a nie aplikacji desktopowych. WPF (Windows Presentation Foundation) jest frameworkiem dla języka C#, a nie C++. Flutter to framework stworzony przez Google, który służy do budowy aplikacji mobilnych i webowych, wykorzystując język Dart, co sprawia, że nie jest narzędziem pierwszego wyboru dla programistów C++.

Pytanie 4

Co oznacza pojęcie MVP w kontekście projektowania aplikacji?

A. Multiple Value Platform - platforma wspierająca wiele typów wartości danych
B. Minimum Viable Product - produkt o minimalnej funkcjonalności zdolny do działania
C. Most Valuable Program - program uznany za najbardziej wartościowy w organizacji
D. Mobile Virtual Platform - platforma do testowania aplikacji mobilnych
Mimo że inne odpowiedzi mogą wydawać się interesujące, żadna z nich nie odnosi się do kluczowego pojęcia Minimum Viable Product, które jest fundamentalne w projektowaniu aplikacji. Multiple Value Platform sugeruje, że system jest w stanie obsługiwać różne typy danych, co jest ważne w kontekście integracji systemów, ale nie odnosi się bezpośrednio do strategii wprowadzania produktów. Most Valuable Program wskazuje na programy szczególnie cenione w organizacji, co jest terminem zupełnie odwrotnym do idei MVP, która koncentruje się na minimalnych funkcjonalnościach, a nie na wartości programu. Z kolei Mobile Virtual Platform, chociaż może wydawać się zbliżonym konceptem, odnosi się do środowisk wirtualnych używanych do testowania aplikacji mobilnych, co nie ma związku z procesem definiowania minimalnej wersji produktu na rynku. Kluczowym błędem jest zrozumienie, że MVP nie jest tylko o zredukowanej wersji produktu; to strategiczny sposób na wprowadzenie innowacji, który umożliwia naukę i adaptację, a nie tylko skupienie się na poszczególnych funkcjach czy platformach. Takie nieporozumienie może prowadzić do niewłaściwego podejścia do projektowania i wprowadzania produktów na rynek, co w dłuższej perspektywie może znacząco wpłynąć na sukces projektu.

Pytanie 5

Jaki framework umożliwia tworzenie interaktywnych interfejsów użytkownika w języku TypeScript?

A. jQuery
B. Angular
C. Django
D. ASP.NET Core
Angular to popularny framework oparty na TypeScript, który umożliwia tworzenie dynamicznych i rozbudowanych interfejsów użytkownika. Jest rozwijany przez Google i używany do budowy aplikacji typu Single Page Applications (SPA), które cechują się płynnością działania i interaktywnością. Angular oferuje bogaty ekosystem narzędzi wspierających programistów, takich jak Angular CLI, który pozwala na szybkie generowanie komponentów, serwisów i modułów. Wsparcie dla TypeScript oznacza, że Angular pozwala na wykorzystywanie typów, interfejsów oraz zaawansowanych narzędzi do refaktoryzacji kodu, co przekłada się na większą czytelność i bezpieczeństwo aplikacji. Dzięki modularnej architekturze Angular wspiera tworzenie aplikacji, które są łatwe w utrzymaniu i skalowaniu. Jego dwukierunkowe wiązanie danych (two-way data binding) oraz możliwość dynamicznej aktualizacji widoków czynią go jednym z liderów na rynku frameworków frontendowych.

Pytanie 6

Jaką jednostkę zaleca się stosować przy projektowaniu interfejsu aplikacji?

A. dp
B. px
C. mm
D. pt
No i właśnie, dp (density-independent pixels) to taki trochę złoty standard przy projektowaniu interfejsów na Androida. W praktyce chodzi o to, żeby elementy UI wyglądały podobnie na różnych urządzeniach – niezależnie czy ktoś ma ekran gęsty jak sito, czy telefon z bardzo dużymi pikselami. Używanie dp pozwala unikać sytuacji, gdzie tekst albo przyciski na jednym urządzeniu są czytelne i wygodne w obsłudze, a na innym są mikroskopijne lub przeciwnie – przesadnie wielkie. Oczywiście, wszystko to wynika z tego, że piksele na różnych ekranach mają inną fizyczną wielkość – tzw. density. Stosując dp, projektanci mogą być pewni, że rozmiary będą proporcjonalnie takie same niezależnie od sprzętu. Sam system Android automatycznie przelicza dp na odpowiednią liczbę pikseli na danym urządzeniu. To bardzo wygodne! Moim zdaniem każdy, kto zaczyna projektować aplikacje mobilne, powinien od razu przyzwyczajać się do pracy z dp, bo to po prostu ułatwia życie i ogranicza potem poprawki. To też zgodne z oficjalnymi wytycznymi Google – praktycznie każda dokumentacja do Material Design kładzie na to nacisk. Warto jeszcze pamiętać, że inne jednostki jak px, pt czy mm mogą się sprawdzić w wyjątkowych sytuacjach, ale raczej tylko wtedy, gdy faktycznie zależy nam na absolutnych rozmiarach – a to w UI mobilnym prawie się nie zdarza.

Pytanie 7

Jakie narzędzie jest wykorzystywane do zgłaszania błędów w projektach IT?

A. Photoshop
B. Git
C. JIRA
D. Blender
JIRA to jedno z najczęściej wykorzystywanych narzędzi do zarządzania projektami i raportowania błędów w projektach informatycznych. JIRA umożliwia śledzenie błędów, zarządzanie zadaniami oraz efektywne monitorowanie postępów prac nad projektem. Dzięki integracji z innymi narzędziami, takimi jak Confluence czy Bitbucket, JIRA stanowi kompleksowe rozwiązanie wspierające zespoły deweloperskie. Raportowanie błędów w JIRA pozwala na łatwe przypisywanie ich do odpowiednich członków zespołu, dodawanie załączników i komentarzy oraz monitorowanie statusu danego problemu, co usprawnia proces zarządzania jakością oprogramowania.

Pytanie 8

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

int x = 5;
int y = 10;
Console.WriteLine($"Suma {x} i {y} wynosi {x + y}");
A. Suma 5 i 10 wynosi 15
B. Suma 5 i 10 wynosi x + y
C. Suma x i y wynosi 15
D. Error: niewłaściwa składnia
Kod w języku C# wykonuje operację dodawania dwóch zmiennych, x i y, oraz wyświetla wynik w sformatowanym ciągu tekstowym. Poprawna odpowiedź to 'Suma 5 i 10 wynosi 15', ponieważ zmienna x ma wartość 5, a zmienna y ma wartość 10. Kiedy dodajemy te dwie liczby, otrzymujemy 15. Warto zwrócić uwagę na wykorzystanie interpolacji ciągów, co jest istotnym elementem w nowoczesnym C#. Umożliwia to w prosty sposób łączyć tekst z wartościami zmiennych, co zwiększa czytelność kodu. Interpolacja jest szczególnie przydatna w kontekście generowania komunikatów użytkownika i raportów. Przykład zastosowania może obejmować aplikacje, które prezentują wyniki obliczeń lub statystyki, gdzie ważne jest, aby w przyjazny sposób przedstawiać dane. Dobre praktyki programistyczne sugerują, aby unikać twardego kodowania wartości zamiast tego używać zmiennych, co ułatwia późniejsze modyfikacje i utrzymanie kodu.

Pytanie 9

W metodach klasy GoldCustomer dostępne są tylko pola

public class Customer {
    public string Name;
    protected int Id;
    private int Age;
}
public class GoldCustomer: Customer {
    private GoldPoints: int;
}
A. GoldPoints, Name, Id, Age
B. GoldPoints
C. GoldPoints, Name, Id
D. GoldPoints, Name
W tym pytaniu nietrudno pomylić się, bo różnice między public, protected i private czasem wydają się nieintuicyjne – szczególnie jak ktoś dopiero zaczyna przygodę z C#. Najczęstszy błąd to założenie, że wszystkie pola klasy bazowej są automatycznie dostępne w klasach pochodnych. Tak jednak nie jest. Publiczne pole (takie jak Name) będzie widoczne absolutnie wszędzie – także w GoldCustomer. Protected (Id) daje dostęp tylko klasie bazowej i pochodnym, co jest bardzo wygodne przy dziedziczeniu, bo pozwala korzystać z ważnych danych bez upubliczniania ich na zewnątrz. Natomiast private (Age) jest dostępne wyłącznie w ramach klasy, w której zostało zadeklarowane – żadna klasa pochodna nie może go bezpośrednio użyć. W praktyce programistycznej wiele osób myli protected z public, przez co zdarza się, że do protected próbują się dostać spoza klasy dziedziczącej – i wtedy pojawia się frustracja. Z kolei pole GoldPoints zostało zadeklarowane bezpośrednio w GoldCustomer i dzięki temu jest dostępne tylko w tej klasie – nawet inne klasy dziedziczące po GoldCustomer nie będą miały do niego dostępu. Jeśli chodzi o Age, wielu początkujących (i nie tylko!) zakłada, że dziedziczenie daje pełen dostęp do wszystkiego z klasy bazowej, ale to nieprawda – private jest całkowicie zamknięte. Z technicznego punktu widzenia, zrozumienie tej różnicy pozwala nie tylko lepiej projektować własne klasy, ale i unikać błędów, które potem trudno wyłapać, zwłaszcza w większych projektach. Tak więc, praktyka pokazuje, że najbezpieczniejsze jest świadome korzystanie z modyfikatorów dostępu – pomaga to zachować porządek i minimalizuje ryzyko przypadkowych błędów podczas rozwoju aplikacji.

Pytanie 10

Co należy do zadań interpretera?

A. przekładanie kodu na kod maszynowy
B. wykonanie skryptu instrukcja po instrukcji
C. ulepszanie większej części kodu, aby przyspieszyć jego wykonanie
D. sprawdzanie składni całego programu przed jego uruchomieniem
Często spotykam się z myleniem interpretera z kompilatorem i optymalizatorami kodu, co prowadzi do błędnych wyobrażeń o jego działaniu. Zacznijmy od podstaw: przekładanie kodu źródłowego na kod maszynowy to domena kompilatorów, które analizują cały program, optymalizują go i generują plik wykonywalny, który można uruchomić niezależnie od środowiska. Interpreter natomiast nie zajmuje się takim tłumaczeniem, tylko odczytuje kod i wykonuje go na bieżąco, bez zapisywania gotowego programu w formie binarnej. Kolejna kwestia to ulepszanie kodu w celu przyspieszenia jego wykonania – to zadanie specjalistycznych narzędzi optymalizujących, często wbudowanych w kompilatory. Interpreter rzadko kiedy ingeruje w optymalizację kodu, bo jego głównym zadaniem jest wierne odtworzenie logiki programu krok po kroku, a nie poprawianie jego wydajności. Jeżeli chodzi o sprawdzanie składni całego programu przed uruchomieniem, to znów domena kompilatorów – interpreter najczęściej wykrywa błędy dopiero w momencie, gdy dociera do konkretnej instrukcji podczas wykonywania skryptu. To właśnie sprawia, że łatwiej eksperymentować, ale też czasem trudniej jest znaleźć błędy, które ujawniają się dopiero w trakcie działania aplikacji. W mojej ocenie te nieporozumienia wynikają z utożsamiania terminów używanych w teorii kompilacji – warto rozróżniać narzędzia na podstawie ich faktycznej roli w cyklu życia programu. Praktyka pokazuje, że zrozumienie różnicy pomiędzy interpretacją a kompilacją jest kluczowe przy wyborze technologii do realizacji konkretnego projektu. Jeżeli zależy nam na szybkim prototypowaniu lub pracy z kodem interaktywnym – interpreter jest świetny, ale nie będzie generował kodu maszynowego ani zaawansowanie go optymalizował.

Pytanie 11

Jakie jest podstawowe zadanie firewalla w systemie komputerowym?

A. Ochrona danych na poziomie aplikacji internetowych
B. Zapobieganie wyciekom informacji na skutek awarii systemu
C. Zarządzanie ruchem sieciowym i blokowanie nieautoryzowanego dostępu
D. Szyfrowanie danych przesyłanych w sieci
Firewall to taki strażnik w sieci, który decyduje, co może wejść lub wyjść z naszego systemu. Główną jego rolą jest właśnie zarządzanie ruchem sieciowym – analizuje każde połączenie, każdy pakiet danych i na podstawie ustalonych reguł pozwala albo blokuje ruch. Z mojego doświadczenia wynika, że bez firewalla w firmowej sieci to jak zostawić otwarte drzwi na oścież, serio. To narzędzie nie tylko zatrzymuje nieautoryzowany dostęp z zewnątrz, ale czasem też może blokować ryzykowne próby połączeń wychodzących – na przykład, gdy jakiś wirus próbuje kontaktować się z serwerem złodziei danych. W praktyce najczęściej spotkasz firewalle sprzętowe w routerach firmowych oraz programowe na komputerach i serwerach. Branżowo przyjmuje się, że firewall działa na poziomie sieci (warstwa 3 i 4 modelu OSI), co jest najlepszym miejscem, żeby odsiać niepożądany ruch zanim w ogóle dotrze do cennych serwisów. Ważne jest też, że dobrze skonfigurowany firewall to podstawa każdej strategii bezpieczeństwa, zgodnie z normami ISO/IEC 27001. W sumie, moim zdaniem żaden admin nie wyobraża sobie bez niego sensownej ochrony sieci – to absolutna podstawa.

Pytanie 12

Jakie jest przeznaczenie polecenia "git merge"?

A. Do pobierania aktualizacji zdalnego repozytorium
B. Do usuwania zmian w repozytorium
C. Do zakładania nowego repozytorium
D. Do łączenia zmian z różnych gałęzi
Polecenie "git merge" służy w Git do łączenia zmian z różnych gałęzi. Kiedy pracujemy w zespole i każdy programista rozwija swój fragment kodu na osobnej gałęzi, w pewnym momencie trzeba te zmiany zebrać do kupy, żeby powstała jedna, wspólna wersja projektu. Tu właśnie pojawia się "merge" – pozwala w prosty sposób dołączyć zmiany z jednej gałęzi do drugiej, najczęściej z feature branch do develop albo main. Praktycznie rzecz biorąc, to polecenie sprawdza się zawsze wtedy, gdy chcemy zintegrować efekty pracy kilku osób lub wersje rozwojowe z główną linią kodu. Moim zdaniem, korzystanie z "git merge" to w zasadzie codzienność w projektach zespołowych, bo prawie nikt już nie pracuje tylko na jednej gałęzi. Warto też pamiętać, że merge może czasem prowadzić do konfliktów, jeśli te same fragmenty plików były zmieniane równolegle – wtedy trzeba ręcznie rozwiązać te rozbieżności. W praktyce, dobrą praktyką jest regularne mergowanie, żeby uniknąć lawiny konfliktów na koniec sprintu. Dla mnie "merge" to narzędzie absolutnie kluczowe, bez którego ciężko sobie wyobrazić sensowną pracę z Gitem. No i jeszcze – to nie to samo co "rebase", chociaż oba służą do integracji zmian, ale w różny sposób. Merge zostawia historię połączeń, co ułatwia śledzenie zmian w większych projektach.

Pytanie 13

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

console.log(typeof null);
console.log(typeof undefined);
console.log(typeof []);
console.log(typeof NaN);
A. null, undefined, array, number
B. object, undefined, object, number
C. null, undefined, object, NaN
D. object, undefined, array, number
Typowe błędy związane z błędnymi odpowiedziami wynikają często z mylnych koncepcji dotyczących typów danych w JavaScript. Warto zauważyć, że odpowiedź sugerująca, że null jest typem 'null' nie jest zgodna z rzeczywistością. Null nie jest odrębnym typem, lecz jest klasyfikowany jako obiekt, co jest wynikają z tego, że w JavaScript wszystko jest obiektowe z wyjątkiem prostych typów. Również opinia, że NaN powinien być uznawany za typ 'NaN' jest myląca. NaN jest specjalnym przypadkiem liczby, co można zobaczyć przy użyciu typeof. Tablica z kolei nie ma własnego typu w JavaScript, jest traktowana jako obiekt. To jest powód, dla którego typeof zwraca 'object' dla tablic. Niezrozumienie tych zasad prowadzi do błędnych konkluzji i może wpływać na jakość kodu. W praktyce powinno się zawsze stosować typeof do sprawdzania typów zmiennych, co zapewnia lepszą kontrolę nad danymi i eliminuje potencjalne błędy podczas wykonywania operacji na różnych typach. Warto zwracać uwagę na te aspekty, ponieważ wpływają one na wydajność i stabilność aplikacji.

Pytanie 14

Który z wymienionych algorytmów najczęściej wykorzystuje rekurencję?

A. Obliczanie liczb Fibonacciego
B. Wyszukiwanie liniowe
C. Sortowanie bąbelkowe
D. Sortowanie przez wstawianie
Sortowanie bąbelkowe to algorytm iteracyjny, który działa na zasadzie porównywania sąsiednich elementów tablicy i zamiany ich miejscami. Nie korzysta on z rekurencji, ponieważ jego struktura nie wymaga podziału problemu na mniejsze części. Wyszukiwanie liniowe to prosty algorytm iteracyjny, który przeszukuje kolejne elementy tablicy i nie wykorzystuje rekurencji. Sortowanie przez wstawianie również jest algorytmem iteracyjnym, który działa na zasadzie wstawiania kolejnych elementów w odpowiednie miejsca i nie wymaga wywoływania funkcji rekurencyjnych.

Pytanie 15

Ile kilobajtów (KB) znajduje się w jednym megabajcie (MB)?

A. 1024
B. 1000
C. 10
D. 100
Odpowiedzi, które wskazują na wartości 10, 100 i 1000 kilobajtów jako równowartość 1 megabajta, są błędne z perspektywy standardów komputerowych. Wartość 10 KB jest zdecydowanie zbyt mała, aby mogła odpowiadać wielkości 1 MB, which is a fundamental misunderstanding of data measurement. Tego rodzaju konwersja wprowadza w błąd, ponieważ nie uwzględnia potęg liczby 2, które są kluczowe w kontekście binarnego systemu liczenia. Z kolei 100 KB również nie jest właściwe, ponieważ jest to zaledwie 1/10 megabajta, co jest dalekie od rzeczywistej konwersji. Ponadto, traktowanie 1000 KB jako równowartości 1 MB jest nawiązaniem do systemu dziesiętnego, który jest używany przez niektóre branże, ale nie jest to standardowe podejście w obliczeniach komputerowych. Z technicznego punktu widzenia, przyjęcie, że 1 MB to 1000 KB, może prowadzić do błędnych obliczeń oraz problemów z zarządzaniem danymi w systemach operacyjnych, które stosują binarny system pomiaru pamięci. Dlatego kluczowe jest, aby zrozumieć różnice między tymi systemami, aby uniknąć nieporozumień w zakresie pojemności danych.

Pytanie 16

W zaprezentowanym kodzie stworzono abstrakcyjną klasę Figura oraz klasę Prostokąt, która po niej dziedziczy, zawierającą określone pola i konstruktory. Wskaż najprostszą implementację sekcji /* metody klasy */ dla klasy Prostokąt

Ilustracja do pytania
A. Kod 2
B. Kod 4
C. Kod 3
D. Kod 1
Kod 1 jest prawidłowy ponieważ zapewnia implementację abstrakcyjnych metod Pole i Obwod z klasy Figura co jest wymagane dla każdej klasy dziedziczącej po klasie abstrakcyjnej W Javie kiedy klasa dziedziczy po klasie abstrakcyjnej musi zaimplementować wszystkie jej abstrakcyjne metody Kod 1 definiuje metodę Pole która oblicza pole prostokąta jako iloczyn długości boków a i b oraz metodę Obwod która oblicza obwód jako sumę dwóch razy długości a i dwóch razy długości b Jest to zgodne z konwencjami programowania obiektowego które promują enkapsulację i polimorfizm Kod odnosi się bezpośrednio do konkretnego zastosowania jakim jest obliczanie parametrów prostokąta co jest częstym przypadkiem w programowaniu graficznym oraz w aplikacjach matematycznych Implementacja metod w ten sposób zapewnia prostotę oraz czytelność kodu co jest zgodne z dobrymi praktykami w inżynierii oprogramowania Ponadto dzięki poprawnej implementacji można z powodzeniem rozszerzać funkcjonalność obiektową programu umożliwiając jego łatwiejsze modyfikowanie i rozwijanie w przyszłości

Pytanie 17

Jakie są kluczowe etapy resuscytacji krążeniowo-oddechowej?

A. 20 uciśnięć klatki piersiowej na przemian z 5 wdechami ratowniczymi
B. 30 wdechów ratowniczych bez uciśnięć
C. 30 uciśnięć klatki piersiowej na przemian z 2 wdechami ratowniczymi
D. 10 uciśnięć klatki piersiowej bez wdechów
30 uciśnięć klatki piersiowej na przemian z 2 wdechami ratowniczymi to standardowy protokół resuscytacji krążeniowo-oddechowej (RKO) zgodny z wytycznymi Europejskiej Rady Resuscytacji (ERC). Uciśnięcia wykonywane są na głębokość około 5-6 cm w tempie 100-120 uciśnięć na minutę. Po 30 uciśnięciach wykonuje się 2 wdechy ratownicze, które powinny być wykonywane z odpowiednią siłą, aby unieść klatkę piersiową poszkodowanego. Taka sekwencja jest podstawą pierwszej pomocy i może uratować życie osoby, u której doszło do zatrzymania akcji serca. Resuscytację należy kontynuować do momentu przybycia służb ratunkowych lub odzyskania przytomności przez poszkodowanego.

Pytanie 18

Przedstawione w filmie działania wykorzystują narzędzie

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

Pytanie 19

W sekcji, która odpowiada za obsługę wyjątku wygenerowanego przez aplikację, należy to zdefiniować

A. catch
B. throw
C. finally
D. try
Sekcja catch jest dokładnie tą częścią bloku obsługi wyjątków, która przechwytuje wyjątki wygenerowane w sekcji try. Moim zdaniem to podstawowa rzecz, którą musi znać każdy programista, bo obsługa wyjątków to codzienność, zwłaszcza jak pracuje się z zewnętrznymi bibliotekami czy systemami operacyjnymi. W praktyce catch pozwala nam napisać kod, który zareaguje na konkretne typy błędów, np. wyświetli komunikat użytkownikowi albo zapisze log do pliku. Warto też pamiętać o dobrych praktykach – nie łap wszystkich wyjątków jednym ogólnym catch, bo łatwo wtedy ukryć poważniejsze błędy. Lepiej tworzyć osobne sekcje catch dla różnych typów wyjątków. Przykład z życia: kiedy czytasz plik z dysku, może wystąpić FileNotFoundException lub IOException – można wtedy każdy z tych przypadków obsłużyć osobno. Standardy programowania, zwłaszcza w językach takich jak Java czy C#, wyraźnie zalecają stosowanie catch do obsługi określonych i przewidywalnych wyjątków, a nie do łapania wszystkiego na ślepo. Fajnie też podkreślić, że w niektórych językach catch może przyjmować różne formy, np. except w Pythonie, ale logika pozostaje podobna. Cały blok try-catch sprawia, że program jest bardziej odporny na nieoczekiwane sytuacje – dla mnie to podstawa solidnego kodu.

Pytanie 20

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

Co to jest debouncing w JavaScript?

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

Pytanie 22

Które z wymienionych stwierdzeń najcelniej opisuje proces uruchamiania aplikacji?

A. Wykonywanie programu na podstawie przetłumaczonego kodu maszynowego
B. Generowanie pliku źródłowego
C. Tłumaczenie kodu źródłowego na język pośredni
D. Przetwarzanie kodu źródłowego przez kompilator
Uruchomienie programu to naprawdę ważny moment, bo w tym czasie procesor zaczyna działać na kodzie maszynowym. Ten kod powstaje podczas kompilacji, która zamienia kod źródłowy na coś, co komputer rozumie. W tym etapie program trafia do pamięci, a także przygotowywane są różne dane do działania. Tak więc, to jest kluczowy krok w całej historii programu, bo decyduje, jak dobrze będzie działać.

Pytanie 23

Diagram Gantta, który został zaprezentowany, odnosi się do projektu IT. Przyjmując, że każdy członek zespołu posiada odpowiednie kompetencje do realizacji każdego z zadań, a każde zadanie może być przypisane tylko jednej osobie, która poświęca na nie pełen dzień pracy, to minimalna liczba osób w zespole wynosi

Ilustracja do pytania
A. 2 osoby
B. 5 osób
C. 4 osoby
D. 1 osobę
Diagram Gantta to narzędzie wizualne używane do planowania i zarządzania projektami. Pokazuje harmonogram zadań w czasie. Na przedstawionym diagramie mamy pięć zadań projektowych: Projekt aplikacji Grafika Strona WWW Aplikacja front-end i Aplikacja back-end. Aby określić minimalną liczbę osób potrzebnych do realizacji projektu należy zidentyfikować które zadania mogą być realizowane równocześnie. Z diagramu wynika że w pierwszym tygodniu (1.02 - 7.02) realizowane są zadania Projekt aplikacji i Grafika które wymagają dwóch osób. W kolejnych tygodniach zadania są ułożone tak by unikać nakładania się co oznacza że w każdej kolejnej fazie projektu można kontynuować prace przydzielając jedną osobę do każdego zadania. Dlatego minimalna liczba osób wymagana do realizacji tego projektu to dwie. Taki sposób planowania jest zgodny z zasadami efektywnego zarządzania zasobami w projektach informatycznych co pozwala na optymalne wykorzystanie czasu i umiejętności zespołu. Zastosowanie metody diagramu Gantta jest powszechną praktyką w branży IT pozwalającą na lepsze zobrazowanie zależności i potrzeb kadrowych w projektach.

Pytanie 24

Który z poniższych nie jest typem danych w języku JavaScript?

A. Boolean
B. Integer
C. Object
D. String
Wybór typów danych, takich jak Boolean, String i Object, jest prawidłowy w kontekście JavaScript, ponieważ wszystkie te typy są integralnymi elementami tego języka. Boolean reprezentuje dwie wartości: true i false, co jest niezbędne do tworzenia warunków i logiki w kodzie. Z kolei typ String służy do przechowywania tekstu, co jest kluczowe w każdej aplikacji webowej, umożliwiając manipulację danymi tekstowymi. Przykładowo, można korzystać z metod takich jak `toUpperCase()` czy `substring()`, aby przetwarzać napisy. Typ Object, z kolei, to bardziej złożona struktura, która może przechowywać wiele par klucz-wartość, co pozwala na modelowanie bardziej złożonych danych, takich jak obiekty użytkowników, produkty, czy cokolwiek, co wymaga złożonej struktury danych. Typowe błędy myślowe, które prowadzą do nieprawidłowych wniosków dotyczących typów danych, mogą wynikać z braku zrozumienia różnicy między typami w różnych językach programowania. Na przykład, w językach takich jak Java czy C#, Integer jest odrębnym typem, co może prowadzić do myślenia, że JavaScript działa w podobny sposób. W rzeczywistości jednak, JavaScript zapewnia uproszczoną i bardziej elastyczną obsługę typów numerycznych, a zrozumienie tych różnic jest kluczowe dla efektywnego programowania w tym języku.

Pytanie 25

Który z wymienionych procesów NIE jest częścią etapu kompilacji?

A. Weryfikacja błędów składniowych
B. Optymalizacja kodu
C. Analiza działania programu w czasie rzeczywistym
D. Tłumaczenie kodu źródłowego na język maszynowy
Optymalizacja kodu to integralna część kompilacji, mająca na celu zwiększenie wydajności programu poprzez usunięcie zbędnych instrukcji i usprawnienie algorytmów. Tłumaczenie kodu źródłowego na język maszynowy jest głównym zadaniem kompilatora, który generuje plik wykonywalny. Weryfikacja błędów składniowych jest jednym z pierwszych etapów kompilacji, mającym na celu upewnienie się, że kod jest poprawny pod względem składni, zanim zostanie przekształcony na kod maszynowy.

Pytanie 26

Co oznacza skrót CSRF w kontekście bezpieczeństwa aplikacji webowych?

A. Cascading Style Rendering Form
B. Client-Side Rendering Framework
C. Cross-Site Response Filter
D. Cross-Site Request Forgery
Skrót CSRF najczęściej mylony jest z innymi terminami w obszarze rozwoju aplikacji webowych, co może prowadzić do nieporozumień. Przykładowo, Client-Side Rendering Framework jest koncepcją odnoszącą się do sposobu renderowania stron internetowych, gdzie wiele logiki aplikacji wykonuje się po stronie klienta. Nie ma to jednak nic wspólnego z problematyką powiązaną z bezpieczeństwem. Cross-Site Response Filter sugeruje, że istnieje mechanizm filtrujący odpowiedzi między różnymi witrynami, co również nie ma podstaw w rzeczywistości. Tego typu pomysły świadczą o braku zrozumienia, jak działają ataki w środowisku webowym oraz jakie mechanizmy są potrzebne do ich obrony. Cascading Style Rendering Form nie ma nic wspólnego z bezpieczeństwem aplikacji, a raczej dotyczy stylizacji i prezentacji strony, co nie jest odpowiednim kontekstem. Często ludzie mylą te pojęcia, nie zdając sobie sprawy z ryzyk, jakie niesie niewłaściwe zabezpieczenie aplikacji. Zrozumienie, czym jest CSRF, jest kluczowe, aby unikać błędów w projektowaniu i implementacji rozwiązań webowych, które mogą doprowadzić do poważnych luk w bezpieczeństwie.

Pytanie 27

Jaka będzie wartość zmiennej x po wykonaniu poniższego kodu?

let x = 0;
for (let i = 0; i < 10; i++) {
  if (i % 2 === 0) continue;
  x += i;
}
A. 30
B. 45
C. 20
D. 25
Wartości 45, 30 i 20 uznawane za odpowiedzi na pytanie są wynikiem błędnych założeń dotyczących działania pętli oraz sposobu sumowania wartości. Niektórzy mogą pomyśleć, że wszystkie liczby od 0 do 9 powinny być sumowane, co prowadzi do błędnego wyniku. Zrozumienie tego, jak działa instrukcja continue, jest kluczowe. Instrukcja ta sprawia, że aktualna iteracja pętli jest przerywana w momencie, gdy i jest parzyste, co skutkuje pominięciem tych wartości w sumie. To istotny aspekt, ponieważ nie ma możliwości dodania parzystych liczb do zmiennej x. Kolejną pomyłką jest błędne obliczanie sumy nieparzystych liczb. Zamiast prawidłowego wyniku 25, niektórzy mogą zyskać liczbę 45, co sugeruje, że do sumy dodano również parzyste liczby, co jest niezgodne z logiką pętli. Podobnie, suma 30 pojawia się, gdy ktoś myśli, że bierze tylko niektóre liczby, ale źle oblicza ich sumę. Ostatecznie 20 również nie znajduje uzasadnienia, ponieważ w najlepszym przypadku można uzyskać sumę tylko niektórych nieparzystych liczb, co w rzeczywistości nie jest zgodne z kodem przedstawionym w pytaniu. Warto nauczyć się analizować kod na poziomie instrukcji i zrozumieć, jakie elementy są sumowane, a jakie są pomijane. Umożliwi to unikanie takich potknięć w przyszłości.

Pytanie 28

Który aspekt projektu aplikacji jest kluczowy dla zabezpieczenia danych użytkowników?

A. Koncentracja na wyglądzie interfejsu użytkownika
B. Pominięcie testowania aplikacji w etapie produkcji
C. Tworzenie prostych formularzy do rejestracji
D. Zastosowanie zaawansowanych systemów ochrony
Stosowanie zaawansowanych mechanizmów bezpieczeństwa jest kluczowe dla ochrony danych użytkowników w aplikacjach. Wdrożenie technologii takich jak szyfrowanie, autoryzacja dwuskładnikowa (2FA), firewalle oraz regularne testy penetracyjne pozwala na minimalizację ryzyka ataków i naruszeń danych. Mechanizmy te nie tylko zabezpieczają dane, ale również budują zaufanie użytkowników do aplikacji, co jest niezwykle istotne w branżach takich jak bankowość, medycyna czy e-commerce.

Pytanie 29

W pokazanych fragmentach kodu zdefiniowano funkcję o nazwie fun1. W tej funkcji należy zaimplementować obsługę. Fragment kodu interfejsu użytkownika (XAML):

<RadioButton Content="opcja1" />
<RadioButton Content="opcja2" />
<Button Content="OK" Width=75 Click="fun1"/>
Fragment kodu logiki programu (C#):
private void fun1(object sender, RoutedEventArgs e) { ... }
A. aplikacji po wystąpieniu zdarzenia utraty fokusu przez pole opcji
B. naciśnięcia przycisku zatwierdzającego dialog
C. usunięcia kontrolek z pamięci RAM
D. inicjacji elementów interfejsu użytkownika
Obsługa zdarzeń związanych z przyciskami zatwierdzającymi dialogi jest kluczową częścią interakcji użytkownika z aplikacją. W wielu środowiskach programistycznych, takich jak JavaScript, C# czy Java, przyciski te wywołują funkcje obsługi zdarzeń (event handlers), które mogą walidować dane, przetwarzać informacje lub wykonywać inne działania po naciśnięciu przycisku. Implementacja funkcji obsługującej przycisk jest nieodzowna w aplikacjach graficznych, gdzie interakcja z użytkownikiem wymaga dynamicznego reagowania na jego działania. Dzięki temu aplikacje stają się bardziej interaktywne i responsywne, co zwiększa komfort użytkownika i poprawia ogólną użyteczność oprogramowania.

Pytanie 30

Jakie jest główne zadanie ochrony danych osobowych?

A. Utrudnianie działalności organom ścigania
B. Udostępnianie danych osobowych w celach marketingowych
C. Gwarantowanie anonimowości dla internautów
D. Zabezpieczenie danych osobowych przed nieautoryzowanym dostępem i ich wykorzystaniem
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 31

Prezentowana metoda jest realizacją algorytmu

public static String fun1(String str) {
    String output = " ";
    for (var i = (str.length()-1); i >= 0; i--)
        output += str.charAt(i);
    return output;
}
A. sortującego ciąg od znaku o najniższym kodzie ASCII do znaku o najwyższym kodzie
B. odwracającego ciąg
C. sprawdzającego, czy dany ciąg jest palindromem
D. wyszukującego literę w ciągu
Kod przedstawiony w zadaniu nie realizuje ani wyszukiwania konkretnej litery w ciągu, ani nie sprawdza, czy tekst jest palindromem, ani też nie sortuje znaków po kodzie ASCII. Często spotyka się mylenie tych koncepcji z prostym odwracaniem tekstu, bo wszystkie operacje dotyczą łańcuchów znaków, jednak ich logika jest zupełnie inna. Przykładowo, sprawdzanie palindromu najczęściej polega na porównywaniu znaków od początku i końca tekstu, aż do środka – nie wymaga to budowania nowego odwróconego tekstu, tylko ew. jednej pętli z warunkami. Jeśli chodzi o wyszukiwanie litery, tam szukamy, czy dany znak występuje w ciągu – sprawdza się to za pomocą pętli i instrukcji warunkowej, ale nie tworzy się nowego łańcucha, tylko ewentualnie zwraca pozycję znaku lub informację o jego obecności. Sortowanie znaków w napisie według kodu ASCII wymagałoby innego podejścia – należałoby przenieść znaki do np. tablicy znaków, użyć algorytmu sortowania (chociażby Arrays.sort()), a potem złożyć łańcuch z posortowanych znaków. W tym kodzie nie ma żadnych operacji porównywania kodów znaków ani przestawiania ich miejscami zgodnie z wartościami ASCII. Typowym błędem jest też sugerowanie się samą obecnością pętli i manipulacji na Stringu bez dokładnego prześledzenia, co dzieje się w każdej iteracji. Metoda fun1 po prostu dokleja kolejne znaki od końca oryginalnego napisu do nowego łańcucha, co wyraźnie wskazuje na typowo szkolny algorytm odwracania ciągu. To podejście jest bardzo przydatne do nauki podstaw przetwarzania tekstów i zrozumienia, jak można budować nowe napisy na bazie istniejących danych, ale nie spełnia żadnej z wymienionych innych funkcjonalności.

Pytanie 32

W jakiej fazie cyklu życia projektu informatycznego następuje integracja oraz testowanie wszystkich modułów systemu?

A. Etap implementacji
B. Faza wdrożenia
C. Etap planowania
D. Faza analizy
Planowanie to faza początkowa, w której określane są cele projektu, harmonogram i zasoby, ale nie jest to etap integracji systemu. Analiza skupia się na zbieraniu wymagań i definiowaniu specyfikacji technicznej, ale nie obejmuje łączenia modułów ani testowania gotowego produktu. Wdrożenie to końcowy etap cyklu życia projektu, który następuje po pełnej integracji i testowaniu – polega na uruchomieniu systemu w środowisku produkcyjnym i udostępnieniu go użytkownikom końcowym.

Pytanie 33

Jakie są różnice pomiędzy środowiskiem RAD a klasycznym IDE w kontekście aplikacji webowych?

A. RAD funkcjonuje tylko w systemach Windows
B. RAD koncentruje się wyłącznie na budowie frontendu aplikacji
C. RAD nie wspiera żadnych języków backendowych
D. RAD umożliwia szybsze prototypowanie i rozwój aplikacji dzięki narzędziom wizualnym
RAD nie ogranicza się jedynie do tworzenia frontendu aplikacji – obejmuje cały proces budowy aplikacji, zarówno frontend, jak i backend. Twierdzenie, że RAD działa tylko w systemach Windows, jest błędne, ponieważ wiele narzędzi RAD (np. OutSystems, Mendix) działa w środowisku wieloplatformowym. RAD obsługuje języki backendowe i umożliwia pełną integrację z serwerami, bazami danych oraz API, co czyni go kompleksowym rozwiązaniem do tworzenia aplikacji webowych.

Pytanie 34

Jakie znaczenie ma polimorfizm w programowaniu obiektowym?

A. Umożliwia jednej metodzie działać w różnorodny sposób w zależności od klasy, do której należy
B. Pozwala na tworzenie obiektów z wielu różnych klas równocześnie
C. Ogranicza dostęp do atrybutów klasy
D. Dzieli program na klasy oraz obiekty
Polimorfizm to zdolność obiektów do używania tej samej metody lub interfejsu, ale z różnymi implementacjami, w zależności od klasy obiektu. Dzięki polimorfizmowi można wywołać metodę `obiekt.wyswietl()`, która zachowuje się inaczej w klasie `Samochod` i inaczej w klasie `Motocykl`, mimo że nazwa metody pozostaje taka sama. Polimorfizm ułatwia rozbudowę aplikacji, ponieważ nowe klasy mogą być dodawane bez modyfikacji istniejącego kodu, co zwiększa elastyczność i rozszerzalność programu. Jest to jedna z najważniejszych zasad programowania obiektowego, obok dziedziczenia i hermetyzacji.

Pytanie 35

Przykład wywołania funkcji zamien w języku C++ może wyglądać w następujący sposób:

void zamien(int *a, int *b) {
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}
A. zamien(*a, *b); // a, b - zmienne całkowite
B. zamien(12, 34)
C. zamien(m, n); // m, n - zmienne całkowite
D. zamien(&a, &b); // a, b - zmienne całkowite
Patrząc na inne podane propozycje, łatwo zauważyć, że każda z nich zawiera typowy błąd związany z mechaniką przekazywania danych do funkcji w C++. Dużo osób na początku myśli, że można po prostu przekazać liczby bezpośrednio, jak w zamien(12, 34), ale to mija się z celem, bo funkcja oczekuje wskaźników, czyli adresów zmiennych, które mają być zamienione. Przekazanie samych wartości (czy to literałów, czy konkretnych zmiennych) skutkuje tym, że funkcja pracuje na kopiach tych wartości, a nie na oryginalnych danych. Taki kod się nawet nie skompiluje, bo kompilator jasno wymaga wskaźników jako argumentów. Z kolei zamien(*a, *b) też jest mylące, bo tu przekazujemy już nie wskaźniki, ale wartości, na które one wskazują. To znowu powoduje, że funkcja dostaje kopie, a nie adresy, więc nie może zmienić oryginałów. Bardzo łatwo tu pomylić dereferencję z przekazaniem wskaźnika – moim zdaniem to jeden z najczęstszych błędów początkujących, bo na pierwszy rzut oka wydaje się logiczne, że skoro funkcja operuje na wskaźnikach, to wystarczy podać gwiazdkę. No ale niestety, to jest właśnie ta typowa pułapka. Podobnie zamien(m, n) wygląda jak klasyczne wywołanie funkcji, ale znowu – przekazujemy wartości, nie adresy, więc zamiana zachodzi tylko na kopiach i nie widać efektu poza funkcją. W praktyce taki kod nie spełnia celu, dla którego ktoś napisał funkcję operującą na wskaźnikach. Takie nieporozumienia wynikają często z nieznajomości podstaw przekazywania parametrów w C++. Programowanie niskopoziomowe jest pod tym względem wymagające, bo trzeba zawsze wiedzieć, czy manipuluje się oryginałem czy tylko tymczasową kopią, a to różnica zasadnicza. Z mojego doświadczenia wynika, że najlepiej uczyć się przez praktykę: napisać prostą funkcję, przekazać różne typy argumentów i samemu zobaczyć, co się dzieje z ich wartościami po powrocie z funkcji. To bardzo szybko wyjaśnia, dlaczego przekazywanie wskaźników lub referencji jest tak ważne w sytuacjach, gdy chcemy faktycznie wpłynąć na dane przekazane do funkcji. Warto też podkreślić, że kompilator nie pozwoli na wywołanie funkcji z niezgodnym typem argumentu – i to jest jedna z tych rzeczy, które ratują przed większą katastrofą w działającym programie.

Pytanie 36

Jaki będzie wynik działania poniższego kodu JavaScript?

function foo() { console.log(a); var a = 1; console.log(a); } foo();
A. ReferenceError, 1
B. undefined, undefined
C. undefined, 1
D. 1, 1
Wynik działania podanego kodu to 'undefined, 1', co jest zgodne z zasadami hoisting w JavaScript. Kiedy funkcja 'foo' jest wywoływana, zmienna 'a' jest zadeklarowana przy użyciu 'var'. Zgodnie z zasadą hoisting, deklaracja zmiennej jest przenoszona na początek funkcji, ale przypisanie wartości następuje w miejscu, gdzie znajduje się kod. Dlatego, podczas pierwszego wywołania 'console.log(a)', 'a' nie ma jeszcze przypisanej wartości, co skutkuje wyświetleniem 'undefined'. Następnie, po przypisaniu '1' do 'a', w drugim 'console.log(a)' zmienna ta już ma wartość, więc wyświetlane jest '1'. Zrozumienie hoisting jest kluczowe dla programistów, ponieważ może wpływać na logikę działania kodu i prowadzić do błędów, jeśli nie jest odpowiednio uwzględnione. W praktyce powinno się unikać korzystania z hoisting, preferując inicjalizację zmiennych na początku funkcji, co zwiększa czytelność i utrzymanie kodu.

Pytanie 37

Do implementacji w aplikacji jednokierunkowej funkcji skrótu, zwanej funkcją haszującą, można wykorzystać algorytm

A. DES
B. RSA
C. AES
D. MD5
Wiele osób myli funkcje szyfrujące z funkcjami skrótu i to jest dość powszechny błąd – spotkałem się z tym wielokrotnie podczas różnych zajęć czy projektów. Algorytmy takie jak DES, AES czy RSA to klasyczne przykłady szyfrów, czyli narzędzi do szyfrowania i odszyfrowywania danych, a nie do generowania skrótu. DES i AES to algorytmy szyfrowania symetrycznego, w których ten sam klucz jest używany zarówno do szyfrowania, jak i odszyfrowywania. RSA z kolei jest przykładem szyfrowania asymetrycznego – opiera się na parze kluczy: publicznym i prywatnym. Różnica jest fundamentalna: szyfrowanie zawsze daje możliwość odzyskania oryginalnych danych przy posiadaniu właściwego klucza, natomiast funkcja skrótu ma być jednokierunkowa, czyli nie ma (w praktyce) sposobu, by z hasha odzyskać oryginał. Stosowanie DES, AES czy RSA wszędzie tam, gdzie chodzi wyłącznie o weryfikację integralności albo podpisanie niewielkiego fragmentu danych, jest nieefektywne, niezgodne z dobrymi praktykami i standardami (np. NIST czy ISO/IEC 27001). Co więcej, taka pomyłka może prowadzić do poważnych błędów w zabezpieczeniach aplikacji. Przykład: szyfrując hasło zamiast haszować, narażamy się na jego łatwe odzyskanie przez atakującego, jeśli wycieknie klucz. Funkcje skrótu (np. MD5, SHA-256) są do tego stworzone – nie pozwalają odtworzyć wejścia, dają szybkie porównania. Warto rozumieć te różnice, bo w praktyce branżowej od tego zależy bezpieczeństwo całych systemów. Moim zdaniem, zaskakująco często nawet doświadczeni programiści się tutaj mylą, zwłaszcza jeśli nie zajmują się na co dzień bezpieczeństwem IT.

Pytanie 38

Jakie jest rozwiązanie dla dodawania binarnego liczb 1011 oraz 110?

A. 11001
B. 11101
C. 10101
D. 10001
Dodawanie binarne to podstawowa operacja w systemie liczbowym, który używa tylko dwóch cyfr: 0 i 1. W przypadku dodawania liczb binarnych, proces ten przypomina dodawanie w systemie dziesiętnym, jednak z pewnymi różnicami ze względu na ograniczony zestaw cyfr. Gdy dodajemy liczby 1011 i 110, należy ustawić je w kolumnach, podobnie jak w dodawaniu dziesiętnym. Zaczynamy od najmniej znaczącej cyfry. W pierwszej kolumnie mamy 1 + 0, co daje 1. W drugiej kolumnie mamy 1 + 1, co daje 0, ale musimy przenieść 1 do następnej kolumny (przeniesienie jest kluczowym elementem w dodawaniu binarnym). W trzeciej kolumnie dodajemy 1 (przeniesienie) + 0 + 1, co daje 0 i przenosimy 1 do następnej kolumny. W czwartej kolumnie dodajemy przeniesienie 1 + 1 (z liczby 1011), co daje 10 w systemie binarnym, co oznacza 0 i przeniesienie 1. Końcowym wynikiem dodawania daje 10001 w systemie binarnym. To podejście jest zgodne z zasadami arytmetyki binarnej, które są fundamentem działania komputerów i systemów cyfrowych, w których operacje na danych są realizowane w systemie binarnym.

Pytanie 39

Wykorzystując jeden z dwóch zaprezentowanych sposobów inkrementacji w językach z rodziny C lub Java, można zauważyć, że
Zapis pierwszy:

b = a++;
Zapis drugi:
b = ++a;
A. Drugi zapis nie jest zgodny ze składnią, co doprowadzi do błędów kompilacji.
B. Wartość zmiennej b będzie wyższa po użyciu drugiego zapisu w porównaniu do pierwszego.
C. Bez względu na zastosowany sposób, w zmiennej b zawsze uzyskamy ten sam rezultat.
D. Tylko przy użyciu pierwszego zapisu zmienna a zostanie zwiększona o 1.
Drugi zapis nie jest niezgodny ze składnią – zarówno preinkrementacja, jak i postinkrementacja są w pełni zgodne z zasadami języka i nie powodują błędów kompilacji. Niezależnie od wybranego zapisu, zmienna zostanie zwiększona, lecz kluczowa różnica polega na tym, kiedy dokładnie to następuje. Twierdzenie, że w każdym przypadku wynik będzie taki sam, jest błędne – różnice pojawiają się podczas użycia tych operatorów w bardziej złożonych wyrażeniach. Zapis pierwszy (preinkrementacja) nie jest jedynym sposobem na zwiększenie wartości zmiennej, chociaż w wielu sytuacjach jest preferowany ze względu na efektywność.

Pytanie 40

Podstawowym celem środowisk IDE takich jak: IntelliJ IDEA, Eclipse, NetBeans jest programowanie w języku:

A. C++
B. Python
C. Java
D. C#
IDE, czyli Zintegrowane Środowiska Programistyczne, takie jak IntelliJ IDEA, Eclipse czy NetBeans, od lat są uznawane za najważniejsze narzędzia do tworzenia aplikacji w języku Java. Te środowiska zostały od podstaw zaprojektowane właśnie z myślą o programistach Javy – wspierają typowe projekty Java SE, Java EE czy nawet JavaFX. Moim zdaniem, ich integracja z narzędziami takimi jak Maven, Gradle, testami jednostkowymi JUnit albo debuggerami Javy to prawdziwy game-changer. Na co dzień korzysta się tam z podpowiedzi składni, automatycznego refaktoringu, generatorów kodu i systemów kontroli wersji. Przykładowo, większość firm w Polsce, które tworzą oprogramowanie korporacyjne, wybiera właśnie te IDE do pracy z Java Spring Boot czy Hibernate. Nawet podczas nauki w technikum często pierwsze projekty Java robi się właśnie w Eclipse albo IntelliJ. Pewnie, można dorzucić pluginy do innych języków, ale to Java jest sercem tych środowisk i to dla niej są one najbardziej zaawansowane, zgodnie z najlepszymi wzorcami branżowymi. Jak patrzę na ogłoszenia o pracę, to praktycznie każda oferta na programistę Java zakłada znajomość choć jednego z tych IDE. To jasno pokazuje, że ich podstawowym celem jest ułatwienie i przyspieszenie tworzenia oprogramowania właśnie w tym języku.