Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 30 marca 2026 02:17
  • Data zakończenia: 30 marca 2026 02:35

Egzamin zdany!

Wynik: 27/40 punktów (67,5%)

Wymagane minimum: 20 punktów (50%)

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

Co to jest wzorzec projektowy Singleton?

A. Wzorzec zapewniający istnienie tylko jednej instancji klasy w całej aplikacji
B. Metoda zabezpieczania aplikacji przed atakami typu SQL Injection
C. Wzorzec do zarządzania komunikacją między komponentami aplikacji
D. Technika optymalizacji kodu poprzez minimalizację liczby obiektów
Wzorzec projektowy Singleton to jeden z fundamentalnych wzorców, który zapewnia, że w trakcie działania aplikacji istnieje tylko jedna instancja danej klasy. Przydaje się to w sytuacjach, gdy musimy zarządzać zasobami, które nie powinny być wielokrotnie instancjonowane, na przykład połączenia z bazą danych czy logika globalnych ustawień. Implementacja tego wzorca zakłada zastosowanie prywatnego konstruktora oraz metody statycznej, która odpowiada za utworzenie instancji. Przykładem zastosowania Singletona mogą być klasy zarządzające konfiguracją aplikacji, gdzie zmiana w jednym miejscu może wpłynąć na cały system. Często jest on krytykowany za to, że wprowadza globalny stan, co może prowadzić do trudności w testowaniu i zarządzaniu stanem aplikacji. Dlatego ważne jest, aby stosować go świadomie i tam, gdzie rzeczywiście przynosi korzyści, zgodnie z najlepszymi praktykami inżynieryjnymi.

Pytanie 2

Przedstawiony na filmie kod napisany w języku C++ nie kompiluje się. Co należy zmienić w tym kodzie, aby proces kompilacji wykonał się bez błędów?

A. zadeklarować zmienną sprawdz przed jej wykorzystaniem w linii 11
B. dodać deklarację funkcji sprawdz przed funkcją main
C. poprawnie zapisać warunek w instrukcji if w linii 11, np. sprawdz(x)==true
D. naprawić błąd w funkcji sprawdz, który polega na braku nawiasów {} w pętli for
Wielu początkujących programistów skupia się na szczegółach składniowych lub drobiazgach logicznych, kiedy pojawia się błąd kompilacji w C++. Jednak często przyczyną jest coś bardzo podstawowego, jak brak deklaracji funkcji przed jej użyciem. Jeśli chodzi o zapis warunku w instrukcji 'if', to kompilator nie zgłasza błędu, gdy używamy wyrażenia typu 'if (sprawdz(x))' – to całkowicie poprawna składnia, a dopisywanie '==true' jest redundantne i nie wnosi niczego nowego. Bardzo często widzę, że ktoś skupia się na tym, żeby warunek koniecznie porównywać do true, ale tak naprawdę to kwestia stylu, nie poprawności. Pozostawienie nawiasów klamrowych w pętli for jest oczywiście dobrą praktyką, ale ich brak nie zawsze generuje błąd kompilacji, jeśli pętla ma tylko jedną instrukcję. Kompilator C++ potrafi to rozpoznać i nie zgłasza błędu – sprowadza się to bardziej do czytelności i unikania błędów logicznych niż do samej poprawności kompilacji. Odpowiedź dotycząca deklarowania zmiennej 'sprawdz' to już nieporozumienie – 'sprawdz' to funkcja, a nie zmienna, więc nie deklarujemy jej w ten sposób. Ten błąd pokazuje, jak łatwo pomylić pojęcia w językach programowania, zwłaszcza jeśli dopiero zaczynamy przygodę z kodowaniem. Główna zasada, którą warto tu zapamiętać, to: każda funkcja używana przed jej zdefiniowaniem musi być zadeklarowana – to właśnie tego brakuje w typowym przykładzie z pytania. Bez deklaracji kompilator nie wie, jaką sygnaturę ma funkcja, a to skutkuje błędem już na poziomie kompilacji. Z mojego doświadczenia wynika, że takie drobne rzeczy potrafią skutecznie utrudnić życie, dlatego warto czytać komunikaty kompilatora i znać podstawowe zasady działania języka C++.

Pytanie 3

Podaj wspólną cechę wszystkich kontrolek umieszczonych w ramce

<Label Text="5" BackgroundColor="Blue" TextColor="Tan" isVisible="True" />
<Stepper BackgroundColor="Blue" Value="5" isVisible="True" />
<Entry TextColor="Tan" BackgroundColor="Blue" Placeholder="5" />
<Slider ThumbColor="Tan" BackgroundColor="Blue" Value="5" isVisible="False" />
A. są w nich ustawione te same wartości domyślne
B. mają tło w tym samym kolorze
C. mają identyczny kolor czcionki
D. wszystkie są widoczne
W tym przypadku wskazałeś/aś, że wszystkie kontrolki mają tło w tym samym kolorze, i to jest faktycznie prawidłowa odpowiedź. Gdy spojrzymy na definicje: Label ma BackgroundColor="Blue", Stepper także BackgroundColor="Blue", Entry również BackgroundColor="Blue", a Slider—no właśnie—też BackgroundColor="Blue". To pokazuje, że niezależnie od typu kontrolki, wszystkie mają ustawione tło na dokładnie ten sam kolor. W praktyce bardzo często spotyka się wymóg zachowania spójności wizualnej interfejsu, szczególnie w aplikacjach profesjonalnych czy korporacyjnych. Ustalanie wspólnego BackgroundColor jest jednym z najprostszych kroków ku temu, by UI wyglądało porządnie i było czytelne dla użytkownika końcowego. Moim zdaniem, kiedy projektuje się cały ekran lub jakąś sekcję UI, warto od razu narzucić style lub korzystać z szablonów (np. Styles w XAML czy resourcach), żeby uniknąć przypadkowych rozbieżności kolorystycznych, które potem tylko irytują i programistów, i użytkowników. W branży jest to uznawane za dobrą praktykę – jednolity background ułatwia szybkie ogarnięcie, które elementy należą do jednej grupy funkcjonalnej. Poza tym, kolor tła bywa często wykorzystywany do komunikowania stanu albo priorytetu (np. alerty na czerwono itp.), więc to naprawdę ważne, żeby takie detale były przemyślane i konsekwentnie stosowane. No i jeszcze taka ciekawostka: nie wszystkie kontrolki domyślnie wyświetlają tło, więc czasem trzeba to jawnie ustawić, żeby efekt był taki sam na każdej platformie.

Pytanie 4

Jakie czynności należy wykonać, aby zrealizować zdarzenie kliknięcia na przycisk w aplikacji desktopowej?

A. Zmienić plik XAML
B. Utworzyć metodę w systemie menu
C. Zaprojektować nowy dialog modalny
D. Powiązać zdarzenie kliknięcia z odpowiednią metodą w kodzie
Podłączenie zdarzenia kliknięcia do odpowiedniej metody w kodzie to podstawowy krok w obsłudze interakcji użytkownika z przyciskiem w aplikacjach desktopowych. W środowiskach takich jak WPF (Windows Presentation Foundation), WinForms czy Qt, każda kontrolka (np. przycisk) może posiadać przypisaną metodę, która zostanie wywołana w momencie kliknięcia. Dzięki temu możliwe jest wykonywanie operacji, takich jak otwieranie nowych okien, przetwarzanie danych lub aktualizacja interfejsu użytkownika. Prawidłowa implementacja zdarzeń jest kluczowa dla funkcjonalności aplikacji i umożliwia dynamiczne reagowanie na działania użytkownika. W środowiskach takich jak Visual Studio, proces ten jest intuicyjny i często realizowany przez mechanizm 'kliknij i przeciągnij', a następnie przypisanie kodu do wygenerowanego szkieletu funkcji.

Pytanie 5

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. 4
D. 2 lub 3
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 6

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

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

Pytanie 7

Jakie kwestie związane z percepcją są uwzględnione w rekomendacjach standardu WCAG 2.0?

A. umożliwienia interakcji między elementami użytkownika za pomocą klawiatury
B. zapewnienia odpowiedniego czasu na zapoznanie się i przetworzenie informacji
C. jasności i dokładności w dostarczonych treściach na stronie
D. prezentacji elementów interfejsu użytkownika
Odpowiedzi odnoszące się do zapewnienia odpowiedniego czasu na zapoznanie się z informacjami, umożliwienia interakcji poprzez klawiaturę czy jasności i dokładności treści są ważne w kontekście dostępności stron, ale nie dotyczą bezpośrednio percepcji według standardu WCAG 2.0. Często zdarza się, że osoby uczące się mylą pojęcia percepcji z innymi zasadami WCAG, na przykład zrozumiałością (understandable) czy funkcjonalnością (operable). Percepcja w WCAG skupia się na tym, jak treści są postrzegane przez zmysły – głównie wzrok i słuch, ale czasem też dotyk, gdy mowa np. o wyświetlaczach brajlowskich. Zapewnienie odpowiedniego czasu i interakcji klawiaturą to typowe wymagania dla użytkowników z ograniczeniami motorycznymi, i chociaż są one bardzo istotne, to WCAG klasyfikuje je w innych kategoriach niż percepcja. Jasność i dokładność treści to cecha istotna dla zrozumiałości, jednak nie gwarantuje, że użytkownik w ogóle tę treść zauważy lub rozpozna – do tego potrzebna jest właśnie prawidłowa prezentacja elementów interfejsu. Tu najczęściej pojawia się błąd myślowy: zakłada się, że jak coś jest napisane jasno, to każdy to zobaczy i zrozumie, ale wielu użytkowników ma problemy z odbiorem samych wizualnych aspektów strony. WCAG 2.0 podkreśla, żeby nie polegać tylko na jednym kanale percepcji, np. kolorze, dźwięku czy obrazie. Dopiero dbałość o prezentację elementów interfejsu – kontrast, czytelność, alternatywy tekstowe – sprawia, że strona jest dostępna percepcyjnie. Warto zapamiętać, że kategorie WCAG są celowo podzielone właśnie w ten sposób, aby każda istotna kwestia była rozpatrywana osobno i nie mieszana z innymi.

Pytanie 8

Wskaź kod, który spowoduje wyświetlenie okna dialogowego przedstawionego na ilustracji. Dla uproszczenia kodu, zrezygnowano z atrybutów znaczników

Ilustracja do pytania
A. kod 1
B. kod 3
C. kod 4
D. kod 2
Odpowiedź, którą wybrałeś, to kod 2, i nie ma co do tego wątpliwości. Dobrze, że zauważyłeś wszystkie elementy, które były w oknie dialogowym. W tym kodzie masz TextBox na górze, który pozwala na wpisanie tekstu. Dwa CheckBoxy po lewej stronie to te typowe pola wyboru, które też były widoczne. Po prawej stronie masz trzy RadioButtony, które tworzą grupę przycisków - to jest właśnie to, co powinno być. Na dole widoczny jest przycisk Button z napisem Test, co też jest zgodne z obrazkiem. Takie rozmieszczenie to klucz do stworzenia dobrego interfejsu. Wiesz, w praktyce w wielu aplikacjach używa się właśnie tych elementów do prostych formularzy. Jeżeli rozumiesz, jak te komponenty działają i jak je ze sobą łączyć, to naprawdę dobrze ci to pójdzie w przyszłości w tworzeniu ładnych i funkcjonalnych interfejsów.

Pytanie 9

Jaki modyfikator dostępu umożliwia dostęp do pól klasy tylko za pomocą jej metod?

A. Private
B. Protected
C. Public
D. Static
Modyfikator `private` w językach takich jak C++, Java i C# pozwala na ograniczenie dostępu do pól i metod klasy, umożliwiając ich wykorzystanie wyłącznie w obrębie tej samej klasy. Pola `private` są ukryte przed innymi klasami i mogą być modyfikowane lub odczytywane jedynie poprzez metody publiczne (gettery i settery). Przykład w C++: `class Konto { private: double saldo; public: void ustawSaldo(double s) { saldo = s; } }`. Dzięki temu mechanizmowi dane są chronione przed nieautoryzowanymi zmianami, co zwiększa bezpieczeństwo aplikacji i minimalizuje ryzyko błędów.

Pytanie 10

Jakie narzędzie można wykorzystać do tworzenia aplikacji mobilnych typu cross-platform w C#?

A. środowisko Android Studio
B. środowisko XCode
C. platformę React Native
D. platformę Xamarin
Xamarin to potężna platforma do tworzenia aplikacji mobilnych typu cross-platform w języku C#. Dzięki wykorzystaniu technologii .NET, deweloperzy mogą pisać kod raz, a następnie wdrażać go na różnych systemach operacyjnych, takich jak iOS i Android. Xamarin umożliwia korzystanie z natywnych interfejsów użytkownika oraz dostęp do funkcji urządzeń mobilnych, co zapewnia dużą wydajność i płynność działania aplikacji. Przykładowo, aplikacja stworzona w Xamarinie może korzystać z natywnych komponentów UI, co pozwala na zachowanie specyficznych dla platformy wzorców interakcji oraz UX. Dzięki wsparciu dla C# i .NET, deweloperzy mogą również łatwo integrować istniejące biblioteki oraz korzystać z ekosystemu .NET, co znacząco przyspiesza proces deweloperski. Warto również zaznaczyć, że Xamarin jest zgodny z wieloma standardami, co ułatwia współpracę w zespołach projektowych oraz utrzymanie kodu na dłuższą metę.

Pytanie 11

Jakie narzędzie można wykorzystać do stworzenia mobilnej aplikacji cross-platform w języku C#?

A. środowisko XCode
B. platformę Xamarin
C. środowisko Android Studio
D. bibliotekę React Native
Platforma Xamarin to naprawdę ciekawe narzędzie, które pozwala tworzyć aplikacje mobilne na różne platformy (np. Android, iOS) przy użyciu języka C#. Z mojego doświadczenia wynika, że Xamarin jest bardzo ceniony wśród programistów, którzy już znają .NET, bo w zasadzie pozwala używać tej samej logiki biznesowej w kodzie na wszystkie ważne systemy mobilne. To znacznie przyspiesza pracę, bo nie musisz oddzielnie pisać aplikacji na iOS i Androida, tylko duża część kodu jest współdzielona – zwłaszcza modele danych, logika, a nawet część interfejsu jeśli korzystasz z Xamarin.Forms. Przykładowo, budując prostą aplikację do zarządzania zadaniami, można stworzyć praktycznie cały kod w C#, a potem tylko lekko dostosować szczegóły UI pod każdą platformę. Co ważne, Xamarin udostępnia dostęp do natywnych API każdego systemu przez tzw. bindings, więc nie jesteś ograniczony do najprostszych scenariuszy. Microsoft mocno wspiera to rozwiązanie, a jego integracja z Visual Studio jest naprawdę wygodna. Moim zdaniem, jeśli ktoś zna C# i chce robić mobilki, to Xamarin jest jednym z rozsądniejszych wyborów. Oczywiście, obecnie coraz większą popularność zdobywa .NET MAUI, czyli następca Xamarin.Forms, który idzie jeszcze dalej i oferuje wsparcie również dla desktopów. Ale w praktyce, znajomość Xamarina to wciąż bardzo przydatna rzecz.

Pytanie 12

Co to jest REST API?

A. Architektura API oparta o zasoby i standardowe operacje HTTP
B. Framework do testowania API
C. Protokół sieciowy do transferu danych binarnych
D. Biblioteka JavaScript do komunikacji z bazami danych
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 13

Którą funkcję w C++ można zastosować do dynamicznego przydzielania pamięci dla tablicy?

A. free()
B. sizeof()
C. delete[]
D. malloc()
Funkcja 'free()' służy do zwalniania pamięci zaalokowanej dynamicznie przez 'malloc()', ale nie alokuje pamięci. Funkcja 'sizeof()' zwraca rozmiar typu lub obiektu, ale nie alokuje pamięci dynamicznie – jest wykorzystywana do określania ilości pamięci potrzebnej dla danego typu. 'Delete[]' jest operatorem w C++, który usuwa tablicę dynamicznie zaalokowaną przy użyciu 'new[]', ale nie alokuje pamięci – jest to mechanizm zwalniania pamięci, a nie jej przydzielania.

Pytanie 14

Jakie znaczenie ma termin "przesłanianie metody" w kontekście programowania obiektowego?

A. Tworzenie nowej metody w klasie bazowej
B. Zastosowanie tej samej nazwy metody w klasie bazowej i pochodnej, ale z inną implementacją w klasie pochodnej
C. Zmiana metody prywatnej na metodę publiczną
D. Przenoszenie metod z jednej klasy do drugiej
Definiowanie nowej metody w klasie bazowej to zwykła deklaracja metody i nie jest to przesłanianie. Zamiana metody prywatnej na publiczną to zmiana modyfikatora dostępu, a nie przesłanianie. Kopiowanie metod z jednej klasy do innej nie jest związane z przesłanianiem – kopiowanie kodu narusza zasadę DRY (Don't Repeat Yourself) i jest rzadko stosowane w dobrze zaprojektowanych aplikacjach obiektowych.

Pytanie 15

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

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

Pytanie 16

Co to jest lazy loading w kontekście aplikacji webowych?

A. Metoda kompresji obrazów na stronach internetowych
B. Strategia optymalizacji, która opóźnia ładowanie zasobów do momentu, gdy są faktycznie potrzebne
C. Narzędzie do testowania wydajności ładowania strony
D. Technika przechowywania danych w pamięci podręcznej przeglądarki
Lazy loading to technika optymalizacji wydajności, która polega na opóźnieniu ładowania zasobów, takich jak obrazy, filmy czy skrypty, do momentu, gdy są one rzeczywiście potrzebne. Dzięki temu zwiększa się szybkość ładowania strony, co jest szczególnie ważne w kontekście doświadczeń użytkowników i SEO. Przykładem zastosowania lazy loading może być strona z długą listą produktów, gdzie obrazy dla produktów znajdujących się poza ekranem są ładowane dopiero, gdy użytkownik przewinie stronę w dół. Praktyka ta nie tylko poprawia czas reakcji strony, lecz także redukuje zużycie pasma, co jest korzystne dla użytkowników na urządzeniach mobilnych. Stosując lazy loading, warto pamiętać o dobrych praktykach, takich jak użycie odpowiednich bibliotek JavaScript, które wspierają tę technikę, oraz zapewnienie odpowiednich fallbacków dla starszych przeglądarek. Wprowadzenie lazy loading jest zgodne z zaleceniami optymalizacji wydajności publikowanymi przez Google, które podkreślają znaczenie ładowania tylko niezbędnych zasobów i poprawę UX.

Pytanie 17

Zamieszczony kawałek kodu w języku C# tworzy hasło. Wskaż prawdziwe stwierdzenie dotyczące cech tego hasła?

var random = new Random();
string pulaZnakow =
    "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int dlPuli = pulaZnakow.Length - 1;
char znak;
string wynik = "";

for(int i = 0; i < 8; i++)  {
    znak = pulaZnakow[random.Next(0, dlPuli)];
    wynik += znak;
}
A. Ma maksymalną długość 7 znaków, co ustala zmienna i.
B. Może zawierać małe oraz wielkie litery, cyfry i znaki specjalne.
C. Ma 8 znaków lub więcej i zawiera małe oraz wielkie litery, a także cyfry.
D. Może zawierać małe i wielkie litery oraz cyfry.
Fragment programu w języku C# generuje hasło, które zawiera małe i wielkie litery oraz cyfry. W kodzie widzimy, że zmienna pulaZnakow zawiera wszystkie małe litery alfabetu, wszystkie wielkie litery oraz cyfry od 0 do 9. Zmienna dlPuli przechowuje długość ciągu znaków, co umożliwia losowe wybieranie znaków z pełnego zakresu dostępnych znaków. W pętli for odbywa się iteracja 8 razy, co oznacza, że każde generowane hasło ma długość 8 znaków. Każdy znak jest losowo wybierany z puli, co zapewnia różnorodność i brak uprzedzeń w doborze znaków. Warto również zwrócić uwagę na praktyczne użycie klasy Random, która jest standardem w przypadkowej generacji danych w C#. Takie podejście jest zgodne z najlepszymi praktykami, gdzie hasła powinny mieć różnorodne znaki, co zwiększa ich siłę i trudność złamania. Dobrym pomysłem jest również dodanie symboli specjalnych dla jeszcze większego bezpieczeństwa, co można łatwo zaimplementować modyfikując pule dostępnych znaków.

Pytanie 18

W zamieszczonym fragmencie kodu Java wskaż nazwę zmiennej, która może przechować wartość 'T'.

int zm1;
float zm2;
char zm3;
boolean zm4;
A. zm1
B. zm4
C. zm2
D. zm3
Poprawnie wskazana została zmienna 'zm3', której typ to 'char'. To właśnie zmienne typu 'char' w Javie służą do przechowywania pojedynczych znaków, takich jak na przykład litera 'T'. Zmienna 'char' przechowuje znak jako wartość liczbową zgodnie z kodowaniem Unicode, co pozwala na obsługę szerokiego zakresu znaków z różnych alfabetów. W praktyce często spotyka się sytuacje, gdzie potrzebujemy przechować czy odczytać pojedynczy znak – np. literę przy przetwarzaniu tekstu, analizowaniu plików, czy nawet w prostych grach tekstowych, gdzie np. sterowanie postacią opiera się o pojedyncze litery wciskane na klawiaturze. Moim zdaniem dobre zrozumienie typu 'char' to podstawa, bo łatwo pomylić go z typem 'String', który przechowuje jednak całe ciągi znaków, a nie pojedyncze znaki. Z punktu widzenia dobrych praktyk, zawsze warto dobierać możliwie najwęższy typ danych do zadania – jeżeli chcemy przechować jedną literę, typ 'char' jest po prostu najefektywniejszy. Nawiasem mówiąc, w Javie znak umieszczamy w pojedynczych apostrofach (np. 'T'), co jednoznacznie odróżnia je od tekstów (podwójne cudzysłowy). Osobiście zdarzało mi się kiedyś pomylić te typy i potem szukać błędów, więc warto zapamiętać tę różnicę. Warto też wiedzieć, że typ 'char' przydaje się np. do operacji na znakach w tablicach, przy konwersjach kodów ASCII czy nawet szyfrowaniu prostych tekstów. Zdecydowanie jest to typ, którego nie można pominąć w nauce Javy.

Pytanie 19

Kiedy w programie występuje problem z działaniem, a programista musi zweryfikować wartości znajdujące się w zmiennych w momencie działania aplikacji, to w tym celu należy zastosować

A. interpreter
B. wirtualną maszynę
C. debugger
D. analizator składni
W praktyce programistycznej bardzo łatwo pomylić narzędzia służące do różnych celów, zwłaszcza gdy ktoś dopiero zaczyna swoją przygodę z kodowaniem. Analizator składni to narzędzie wykorzystywane głównie przez kompilatory i interpretery do sprawdzania poprawności gramatycznej kodu źródłowego – pozwala wyłapać błędy na etapie pisania programu, ale nie daje możliwości sprawdzenia, co dokładnie dzieje się „w środku” działającej aplikacji. Stosowanie analizatora składni nie pomoże więc zweryfikować dynamicznych wartości zmiennych w trakcie działania programu. Wirtualna maszyna natomiast to środowisko uruchomieniowe, które umożliwia wykonywanie kodu niezależnie od konkretnej platformy sprzętowej czy systemu operacyjnego (przykład to JVM dla Javy). Chociaż często daje ona pewne narzędzia diagnostyczne, to jej głównym zadaniem nie jest debugowanie kodu ani szczegółowy podgląd zmiennych w czasie rzeczywistym. Interpreter z kolei wykonuje kod linia po linii, ale nie oferuje sam z siebie rozbudowanych opcji diagnostycznych i śledzenia zmiennych, chyba że jest rozbudowany o dodatkowe narzędzia debugujące. Często spotykanym błędem jest mylenie funkcji interpretera czy środowiska uruchomieniowego z narzędziami do debugowania – to nie to samo. Moim zdaniem, żeby skutecznie tropić błędy, trzeba właśnie sięgnąć po debugger, bo to on daje te precyzyjne narzędzia kontroli i podglądu, bez których analiza działania programu „na żywo” byłaby bardzo niewygodna. Warto pamiętać, że dobre praktyki programistyczne zawsze zalecają korzystanie ze specjalistycznych narzędzi do debugowania, bo to po prostu najbardziej efektywna ścieżka szukania błędów.

Pytanie 20

Jakie ma znaczenie "operacja wejścia" w kontekście programowania?

A. Wprowadzanie nowych funkcji do aplikacji
B. Przekazywanie danych do programu z zewnętrznych źródeł
C. Naprawianie błędów w kodzie aplikacji
D. Zmiana wartości zmiennych globalnych
Operacja wejścia w programowaniu polega na przekazywaniu danych do programu z zewnętrznego źródła, takiego jak klawiatura, plik lub strumień danych. W języku C++ typowym przykładem operacji wejścia jest `cin >> zmienna;`, która pobiera dane od użytkownika i przypisuje je do zmiennej. Operacje wejścia są niezbędne w interaktywnych aplikacjach, które wymagają danych od użytkownika w czasie rzeczywistym, umożliwiając dynamiczne przetwarzanie informacji.

Pytanie 21

Jaki będzie rezultat operacji logicznej AND dla wartości binarnych 1010 oraz 1100?

A. 1000
B. 1010
C. 1100
D. 1110
Wszystkie inne proponowane odpowiedzi są nieprawidłowe z różnych powodów. Odpowiedź 1110 jest niepoprawna, ponieważ wynikiem operacji AND nie może być 1 na pozycji bitu, gdzie przynajmniej jeden z porównywanych bitów wynosi 0. W tej operacji, gdy bierzemy pod uwagę drugi i trzeci bit, oba są odpowiednio 0 i 1, co daje wynik 0, a nie 1. Kolejna nieprawidłowość dotyczy odpowiedzi 1100. W tej odpowiedzi otrzymujemy 1 w pierwszym i drugim bicie, co jest sprzeczne z zasadą operacji AND, gdzie jeden z porównywanych bitów również musi być 0. W związku z tym, operacja AND dla tych bitów powinna również zwrócić 0 w tych pozycjach. Ostatnią niepoprawną odpowiedzią jest 1010. Choć ta liczba jest jedną z operowanych i rzeczywiście zawiera bity 1 i 0, wynik operacji AND nie powinien być równy któremuś z oryginalnych operandów, ale rezultatem zgodnym z zasadami logiki binarnej. To pokazuje, że niektóre odpowiedzi mogą zawierać bity, które są zgodne z jednym z operandów, jednak nie są wynikiem właściwej operacji AND. W kontekście systemów logicznych oraz algorytmów cyfrowych, zrozumienie tych zasad jest kluczowe dla prawidłowego manipulowania danymi i projektowania układów cyfrowych.

Pytanie 22

Z jakiego obiektu można skorzystać, aby stworzyć kontrolkę wskazaną strzałką na ilustracji?

Ilustracja do pytania
A. Windows - dla biblioteki WPF; JFrame - dla biblioteki Swing
B. Box - dla biblioteki WPF; JField - dla biblioteki Swing
C. Text - dla biblioteki WPF; JText - dla biblioteki Swing
D. TextBox - dla biblioteki WPF; JTextField - dla biblioteki Swing
Wybrałeś dokładnie to, co w praktyce programisty jest najważniejsze, czyli TextBox dla WPF i JTextField dla Swinga. Te dwa komponenty to absolutna podstawa, jeśli chodzi o pola do wprowadzania tekstu, zarówno w aplikacjach .NET, jak i Java. W WPF TextBox pozwala na przyjmowanie danych od użytkownika, obsługę zdarzeń, walidację, formatowanie tekstu – ogólnie wszystko, co potrzeba do pracy z tekstem w GUI. W Swingu JTextField jest odpowiednikiem, bardzo intuicyjnym i prostym w użyciu, świetnie się sprawdza przy prostych formularzach czy interfejsach użytkownika. Co ciekawe, oba te komponenty są bardzo elastyczne, można je stylizować, podłączać do systemów walidacji czy nawet rozbudowywać o własne mechanizmy autouzupełniania. Spotkałem się wielokrotnie z sytuacją, gdzie poprawne zastosowanie TextBoxa lub JTextFielda znacząco podnosiło jakość aplikacji – bo jednak wygoda użytkownika i poprawność danych są kluczowe. Takie wybory są zgodne z dokumentacją Microsoftu oraz Oracla, więc trzymasz się dobrych praktyk. Z mojej perspektywy, jeśli chcesz pisać nowoczesne, użytkowe aplikacje desktopowe, znajomość tych kontrolek to absolutny must-have.

Pytanie 23

Programista tworzy system zarządzania buforem drukowania dokumentów. Najnowsze zlecenie drukowania dodawane jest na koniec kolejki, a najstarsze z nich są przekazywane do drukarki. Jaką strukturę danych najłatwiej zastosować w tej sytuacji?

A. LIFO
B. FIFO
C. Sterta
D. Stos
Stos (LIFO - Last In, First Out) działa odwrotnie – najnowsze zadanie jest przetwarzane jako pierwsze, co nie odpowiada kolejności drukowania. Sterta to inna struktura danych używana głównie do dynamicznej alokacji pamięci, a nie do zarządzania kolejkami zadań. LIFO nie nadaje się do implementacji kolejki wydruku, ponieważ najstarsze zadania mogą pozostawać nieprzetworzone, co prowadzi do nieefektywności i dezorganizacji procesów drukowania.

Pytanie 24

Który z poniższych składników NIE jest konieczny do stworzenia klasy w C++?

A. Deklaracja atrybutów klasy
B. Definicja funkcji członkowskich klasy
C. Zastosowanie słowa kluczowego class
D. Definicja destruktora
Do utworzenia klasy w C++ nie jest wymagana definicja destruktora. Destruktor to specjalna metoda klasy, która jest wywoływana automatycznie w momencie zniszczenia obiektu, ale jego obecność jest opcjonalna. Klasy, które nie operują bezpośrednio na zasobach zewnętrznych, takich jak dynamiczna pamięć lub pliki, często nie potrzebują destruktora, ponieważ domyślny destruktor generowany przez kompilator jest wystarczający. Aby utworzyć klasę, wystarczy deklaracja pól i metod oraz użycie słowa kluczowego 'class'. To sprawia, że C++ pozwala na szybkie definiowanie prostych klas, które można później rozwijać w miarę potrzeby.

Pytanie 25

Która z operacji logicznych zwróci wartość "true", gdy obie zmienne są sobie równe?

A. x != y
B. x && y
C. x || y
D. x == y
Operator `==` w języku C++ i wielu innych językach programowania (np. Python, Java, JavaScript) służy do porównywania dwóch wartości. Zwraca `true`, jeśli obie wartości są sobie równe, oraz `false`, jeśli są różne. Przykład: `if (x == y)` sprawdza, czy zmienna `x` jest równa zmiennej `y`. Operator ten jest kluczowy w instrukcjach warunkowych oraz pętlach, gdzie konieczne jest porównywanie wartości w celu podejmowania decyzji na podstawie wyniku tego porównania.

Pytanie 26

Które z wymienionych środowisk programistycznych jest rekomendowane do developing aplikacji w języku Python z użyciem frameworka Django?

A. Unity
B. XCode
C. Android Studio
D. PyCharm
PyCharm to jedno z najbardziej zaawansowanych środowisk programistycznych (IDE) dedykowanych do tworzenia aplikacji w języku Python. Jest to narzędzie preferowane przez programistów korzystających z frameworka Django, który jest popularnym rozwiązaniem do budowy aplikacji webowych. PyCharm oferuje rozbudowane wsparcie dla Django, umożliwiając szybkie tworzenie projektów, integrację z bazami danych oraz wygodne debugowanie aplikacji. IDE zapewnia również możliwość uruchamiania serwerów deweloperskich, podglądu zmian w czasie rzeczywistym oraz automatyczne uzupełnianie kodu, co znacząco zwiększa efektywność pracy nad aplikacjami webowymi. Dzięki PyCharm programiści mogą łatwo zarządzać migracjami bazy danych, tworzyć modele i szablony, co sprawia, że jest to narzędzie nieocenione w ekosystemie Django.

Pytanie 27

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

A. 170, 65, 255
B. 160, 64, 255
C. 160, 65, 255
D. 170, 64, 255
Kolor zapisany w postaci szesnastkowej #AA41FF to jeden z najpopularniejszych formatów wykorzystywanych np. w CSS i projektowaniu graficznym. Składa się z trzech dwucyfrowych wartości: AA dla czerwonego (R), 41 dla zielonego (G) i FF dla niebieskiego (B). Zamiana tych wartości na system dziesiętny jest kluczowa, żeby lepiej zrozumieć jak działa model RGB – czyli mieszanie trzech podstawowych barw światła w różnych proporcjach. AA w szesnastkowym to 170 w dziesiętnym (bo A=10, więc 10*16+10=170), 41 to 4*16+1=65, a FF to 15*16+15=255. Taka konwersja przydaje się w codziennej pracy z grafiką czy front-endem – na przykład podczas ręcznego tworzenia palet kolorów lub dostosowywania barw ikon w interfejsach użytkownika. Co ciekawe, w wielu narzędziach do projektowania można dowolnie przełączać się między tymi zapisami, żeby precyzyjnie ustawić wybrane odcienie. Moim zdaniem, zrozumienie tej konwersji pomaga lepiej ogarnąć, jak komputery interpretują kolory i jak potem wyświetlają je na ekranie. Praktyka pokazuje, że większość błędów przy pracy z kolorami wynika właśnie z nieprawidłowego przeliczania wartości. No i taka wiedza to prawdziwy fundament dla każdego, kto myśli poważnie o pracy z grafiką czy programowaniem front-endu – nie da się jej pominąć w żadnym sensownym kursie.

Pytanie 28

Jaka jest złożoność obliczeniowa poniższego algorytmu?

for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        for (int k = 0; k < n; k++) {
            array[i][j][k] = i + j + k;
        }
    }
}
A. O(n³)
B. O(n)
C. O(n²)
D. O(n log n)
Złożoność obliczeniowa przedstawionego algorytmu wynosi O(n³), co wynika z trzech zagnieżdżonych pętli, z których każda iteruje po n elementach. W praktyce oznacza to, że liczba operacji, które algorytm wykonuje, rośnie proporcjonalnie do sześcianu liczby n. Przykładowo, jeśli mamy dwa wymiary, złożoność będzie O(n²), ale w tym przypadku mamy trzy wymiary (i, j, k), co podwyższa złożoność do O(n³). Takie sytuacje zdarzają się często w problemach związanych z przetwarzaniem danych w trzech wymiarach, takich jak grafika komputerowa czy analiza danych 3D. W branży, dobrze jest pamiętać, że złożoność O(n³) może być nieefektywna dla dużych n, dlatego warto analizować algorytmy pod kątem ich wydajności i stosować różne techniki optymalizacji, jak na przykład podział danych czy struktury danych zmniejszające złożoność. Warto również zrozumieć, że dla dużych wartości n, czas wykonania algorytmu może być zauważalnie dłuższy, co wpływa na ogólną efektywność systemu.

Pytanie 29

Jaką instrukcję należy wykorzystać do poprawnej deklaracji zmiennej typu string w C++?

A. float name = "Jan"
B. bool name = "Jan"
C. string name = "Jan"
D. int name = "Jan"
Ta deklaracja 'string name = "Jan"' to naprawdę dobry sposób na zdefiniowanie zmiennej łańcuchowej w C++. Wiesz, 'string' to typ danych, 'name' to nazwa tej zmiennej, a 'Jan' to wartość, która jest jej przypisana. Typ 'string' jest częścią biblioteki <string> i daje nam wiele możliwości, gdy pracujemy z tekstem. Możemy łączyć, porównywać i modyfikować różne łańcuchy znaków bez większego problemu. To jest mega ważne w aplikacjach, które mają do czynienia z danymi tekstowymi, interfejsami użytkownika czy analizą danych, które wprowadzamy.

Pytanie 30

Który z poniższych formatów plików jest używany do konfiguracji projektów Node.js?

A. node.config
B. settings.ini
C. package.json
D. config.xml
Wybór innych formatów plików, takich jak 'config.xml', 'settings.ini' czy 'node.config', wskazuje na pewne nieporozumienia związane z funkcjonowaniem projektów Node.js. 'config.xml' jest formatem często stosowanym w aplikacjach mobilnych, zwłaszcza tych opartych na platformie Apache Cordova, i nie ma zastosowania w kontekście Node.js. Z kolei 'settings.ini' to typowy plik konfiguracyjny stosowany w wielu aplikacjach, ale nie jest on specyficzny dla Node.js i nie spełnia roli, jaką pełni 'package.json'. Plik 'node.config', mimo że sugeruje powiązanie z Node.js, nie jest standardowym formatem i nie jest używany w praktyce. Zrozumienie, że 'package.json' pełni centralną rolę w ekosystemie Node.js, jest kluczowe dla efektywnego zarządzania projektami oraz ich zależnościami. Ignorowanie tego faktu może prowadzić do problemów w zarządzaniu bibliotekami oraz ich wersjami, co jest istotne dla stabilności i bezpieczeństwa aplikacji. W praktyce, brak znajomości 'package.json' może skutkować trudnościami w implementacji nowych funkcjonalności czy aktualizacji istniejącego kodu.

Pytanie 31

Która z poniższych nie jest prawidłową metodą zarządzania stanem w React?

A. useState hook
B. Context API
C. React.stateManager
D. Redux
Odpowiedzi, które wskazałeś, takie jak Redux, Context API oraz useState hook, są w rzeczywistości powszechnie uznawanymi metodami zarządzania stanem w React. Redux, jako zewnętrzna biblioteka, usprawnia zarządzanie stanem poprzez wprowadzenie centralnego store'a, który przechowuje wszystkie dane w aplikacji. Dzięki temu, każdy komponent może subskrybować zmiany w stanie, co pozwala na prostą synchronizację danych oraz ich śledzenie. Context API jest wbudowane w React i pozwala na udostępnianie danych między komponentami bez potrzeby przekazywania propsów, co znacząco upraszcza hierarchię komponentów i poprawia ich czytelność. Hook useState natomiast, jest prostym i intuicyjnym rozwiązaniem do zarządzania lokalnym stanem w komponentach funkcyjnych, co jest szczególnie przydatne w mniejszych projektach. Zrozumienie, dlaczego te metody są uznawane za poprawne, jest kluczowe, ponieważ pozwala na efektywne zarządzanie stanem w aplikacjach React. Często błędne wnioski wynikają z nieznajomości narzędzi dostępnych w ekosystemie React lub z mylnego przekonania, że dany sposób zarządzania stanem musi być uniwersalny. W rzeczywistości, najlepsze podejście zależy od skali oraz specyfiki projektu.

Pytanie 32

Jaki tekst zostanie wyświetlony po uruchomieniu jednego z poniższych fragmentów kodu?
Kod w React:

<h2>{2+2}</h2>
Kod w Angular:
<h2>{{2+2}}</h2>
A. {2+2}
B. {{2+2}}
C. {4}
D. 4
To pytanie jest świetną okazją, żeby zobaczyć, jak działają wyrażenia w szablonach Reacta i Angulara. Odpowiedź „4” jest prawidłowa, bo zarówno w React, jak i w Angularze, zawarte w nawiasach klamrowych wyrażenie matematyczne 2+2 jest oceniane przez silnik JavaScript podczas renderowania komponentu. Nie jest to zwykły tekst, tylko dynamiczne wyliczenie. Dzięki temu React (w JSX) oraz Angular (w interpolacji {{}}) najpierw obliczają sumę, a potem podstawiają wynik w miejsce wyrażenia – czyli na ekranie pojawia się zwykły tekst „4”. Moim zdaniem to jedna z największych zalet tych frameworków, bo pozwala na bardzo elastyczne budowanie UI, gdzie dynamiczne dane mogą być wstawiane praktycznie wszędzie, bez potrzeby ręcznego tworzenia dodatkowych zmiennych czy długich instrukcji warunkowych. W praktyce często stosuje się takie podejście chociażby do wyświetlania wyników obliczeń, liczników, czy dynamicznych podsumowań. Z mojego doświadczenia, warto pamiętać, że każde wyrażenie w takich miejscach powinno być możliwie proste — złożone logiki lepiej wynieść do funkcji, bo wtedy szablon pozostaje czytelny. Warto też mieć świadomość, że React i Angular automatycznie konwertują wynik na tekst, więc nie trzeba się martwić o jawne rzutowanie. To podejście jest zgodne z dobrymi praktykami branżowymi – prosty, czytelny kod to podstawa w nowoczesnych aplikacjach webowych.

Pytanie 33

Z analizy złożoności obliczeniowej różnych algorytmów sortowania na dużych zbiorach danych (przekraczających 100 elementów) wynika, że najefektywniejszą metodą jest algorytm sortowania

sortowanie bąbelkoweO(n²)
sortowanie przez wstawianieO(n²)
sortowanie przez scalanieO(n log n)
sortowanie przez zliczanieO(n)
sortowanie kubełkoweO(n²)
A. kubełkowego
B. przez scalanie
C. przez zliczanie
D. bąbelkowego
Sortowanie bąbelkowe, mimo że jest łatwe do zrozumienia i zaimplementowania, ma złożoność czasową O(n²), co czyni je nieefektywnym dla dużych zbiorów danych, takich jak ponad 100 elementów. Działa poprzez wielokrotne przechodzenie przez listę, porównując sąsiednie elementy i zamieniając je miejscami, jeśli są w niewłaściwej kolejności. To powoduje, że algorytm ten staje się wolny przy większej ilości danych. Sortowanie przez scalanie, choć bardziej wydajne niż bąbelkowe, z złożonością O(n log n), nadal nie dorównuje szybkością sortowaniu przez zliczanie w specyficznych warunkach, gdzie zakres wartości jest ograniczony. Jest to metoda rekurencyjna, która dzieli listę na mniejsze części, sortuje je, a następnie scala w jedną posortowaną listę. Natomiast sortowanie kubełkowe, podobnie jak przez zliczanie, korzysta z dodatkowych struktur danych, lecz jego efektywność zależy od tego, jak elementy są równomiernie rozmieszczone w kubełkach, co może prowadzić do złożoności O(n²) w przypadku złej dystrybucji. Typowe błędy myślowe polegają na przecenianiu prostoty implementacji ponad złożoność czasową, a także niedocenianiu specyfiki danych wejściowych, co jest kluczowe dla wyboru odpowiedniego algorytmu sortującego. Przy rozważaniu wyboru algorytmu należy zawsze brać pod uwagę zarówno jego złożoność, jak i charakterystykę danych, jakie będą przetwarzane, co jest podstawą dobrych praktyk inżynierii oprogramowania.

Pytanie 34

Jakie korzyści płyną z użycia pseudokodu przy tworzeniu algorytmu?

A. Możliwość szybkie zrealizowania algorytmu w którymkolwiek języku
B. Zrozumiałość dla osób nieznających się na programowaniu
C. Generowanie dynamicznych struktur danych
D. Łatwość w zmianie kodu maszynowego
Szybkie wykonanie algorytmu w dowolnym języku wymaga faktycznego napisania kodu, a pseudokod jest jedynie opisem logicznym. Modyfikacja kodu maszynowego jest operacją niskopoziomową i nie ma bezpośredniego związku z pseudokodem. Tworzenie dynamicznych struktur danych to proces realizowany w językach programowania i nie jest celem samego pseudokodu – pseudokod jedynie opisuje sposób implementacji takich struktur na poziomie logicznym.

Pytanie 35

Jakie są korzyści z wykorzystania struktur danych typu mapa (np. HashMap w Javie) w kontekście tworzenia zbiorów danych?

A. Z powodu szybkiego uzyskiwania dostępu do elementów przy użyciu klucza
B. Bo pozwalają na sortowanie danych bez dodatkowych działań
C. Gdyż nie potrzebują znajomości wielkości danych przed kompilacją
D. Ponieważ struktury danych typu mapa zajmują mniej pamięci niż tablice
Mapa, na przykład HashMap w Javie, to taka fajna struktura, która trzyma pary klucz-wartość. Dzięki temu szybko możemy znaleźć dane, korzystając z unikalnego klucza. HashMap jest super, bo pozwala nam na błyskawiczne dodawanie, usuwanie i wyszukiwanie elementów w czasie O(1). To naprawdę przydaje się, gdy pracujemy z dużymi zbiorami danych. Używamy jej często w aplikacjach wymagających szybkiego dostępu do informacji, jak różne bazy danych czy strony internetowe. No i jeszcze jej elastyczność – można ją łatwo dostosować do zmieniających się zestawów danych, co jest dużym plusem.

Pytanie 36

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

A. CSS
B. JavaScript
C. HTTP
D. SQL
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 37

W klasie o nazwie samochod przypisano atrybuty: marka, rocznik, parametry[]. Atrybuty te powinny zostać zdefiniowane jako

A. metody
B. pola
C. funkcje
D. interfejsy
Pola w klasie samochod to właśnie te elementy, które przechowują dane, takie jak marka, rocznik czy tablica parametry. To jest absolutna podstawa programowania obiektowego – najczęściej spotyka się to w językach takich jak Java, C# albo nawet w Pythonie, choć tam często nazywamy je po prostu atrybutami. Dla przykładu, jeśli tworzysz klasę Samochod w C#, to pole 'marka' będzie np. typu string, 'rocznik' – int, a 'parametry' możesz zadeklarować jako tablicę albo listę (List<T>) zależnie od potrzeb. Przechowywanie danych w polach pozwala na lepszą organizację, bo każda instancja klasy ma swoje własne wartości tych pól. Tak się właśnie tworzy modele danych, na których potem operuje cała aplikacja – czy to baza samochodów w warsztacie, czy system ubezpieczeń komunikacyjnych. Takie podejście jest zgodne z zasadami hermetyzacji i solidnych, nowoczesnych standardów pisania kodu. Dużo profesjonalnych frameworków i narzędzi (np. Entity Framework, Hibernate) korzysta z takiego podejścia, nawet jeśli potem te pola opakowujesz w właściwości (properties). Krótko mówiąc, pola to nieodłączny element każdej klasy, która coś reprezentuje, i moim zdaniem nie da się dobrze projektować kodu obiektowego bez zrozumienia tej konwencji.

Pytanie 38

Wzorzec projektowy "Metoda szablonowa" (Template method) stosuje się do:

A. określenia szkieletu algorytmu i pozostawienia szczegółów implementacji dla podklas
B. organizowania obiektów w hierarchiczne struktury drzewiaste
C. gromadzenia obiektów w jednorodnej kolekcji
D. centralizacji zarządzania wieloma instancjami obiektów
Wzorzec projektowy 'Metoda szablonowa' to naprawdę sprytna sprawa, szczególnie w programowaniu obiektowym. Ten wzorzec pozwala zdefiniować ogólną strukturę algorytmu w klasie bazowej, a szczegóły implementacji przekazać do podklas. Brzmi jak coś z teorii, ale w praktyce często się przydaje, bo daje kontrolę nad przepływem działania algorytmu, nie tracąc elastyczności. To taki kompromis: masz szkielet (np. metoda w klasie abstrakcyjnej), ale nie zamykasz drogi na własne pomysły w podklasach. Typowym przykładem może być system obsługi płatności: cała procedura (np. przetwarzanie zamówienia) jest ustalona, ale poszczególne kroki typu 'autoryzuj', 'zrealizuj' czy 'zatwierdź' można nadpisywać. Daje to porządek i spójność kodu, a przy okazji nie zamyka na zmiany. Moim zdaniem, jeśli w projekcie pojawia się powtarzalny schemat postępowania, który tylko w detalach się różni, to Metoda szablonowa jest jednym z najczystszych rozwiązań. Warto pamiętać, że to podejście zgodne z zasadą Hollywood: „Don’t call us, we’ll call you” – to szkielet decyduje, kiedy wywołać szczegóły. Wielu seniorów poleca ten wzorzec, bo upraszcza utrzymanie i rozwijanie kodu, a IDE typu IntelliJ czy Visual Studio świetnie ogarniają takie abstrakcyjne klasy. Szczerze – w wielu firmach to po prostu standard.

Pytanie 39

Która z poniższych technologii jest używana do tworzenia animacji na stronach internetowych?

A. XML
B. HTTP Headers
C. CSS Animations
D. MySQL
CSS Animations to technologia, która pozwala na tworzenie dynamicznych efektów wizualnych na stronach internetowych. Umożliwia ona animowanie różnych właściwości CSS, takich jak kolor, położenie, rozmiar czy przezroczystość, w prosty sposób. Dzięki CSS Animations, deweloperzy mogą tworzyć płynne przejścia i efekty bez potrzeby używania JavaScriptu, co zwiększa wydajność i responsywność witryn. Przykładem zastosowania CSS Animations może być animowanie przycisków na stronie, które zmieniają kolor po najechaniu na nie kursorem. Z punktu widzenia dobrych praktyk, warto pamiętać o optymalizacji efektów animacyjnych, aby nie obciążały one zbytnio zasobów przeglądarki. CSS Animations są częścią standardu CSS3, co oznacza, że są szeroko wspierane przez różne przeglądarki i można je łatwo implementować w projektach webowych.

Pytanie 40

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

A. Jest automatycznie usuwana po zakończeniu działania programu
B. Dziedziczy atrybuty i metody z klasy bazowej
C. Nie może być zastosowana w strukturze dziedziczenia
D. Nie ma możliwości dodawania nowych metod
Stwierdzenie, że klasa pochodna nie może dodawać nowych metod, jest błędne – klasy pochodne mogą dodawać nowe metody, które rozszerzają funkcjonalność klasy bazowej. Automatyczne usuwanie klasy po zakończeniu programu dotyczy obiektów klasy, a nie samej klasy – za usuwanie obiektów odpowiada destruktor. Klasa, która nie może być używana w hierarchii dziedziczenia, to klasa oznaczona jako 'final' (w C++) lub 'sealed' (w C#), ale standardowe klasy pochodne nie mają tego ograniczenia, chyba że zostanie to jawnie zadeklarowane.