Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 17 grudnia 2025 18:19
  • Data zakończenia: 17 grudnia 2025 18:26

Egzamin zdany!

Wynik: 35/40 punktów (87,5%)

Wymagane minimum: 20 punktów (50%)

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

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

A. pola
B. funkcje
C. interfejsy
D. metody
Wydaje mi się, że często początkujący mają problem z rozróżnieniem między polami, metodami a funkcjami, szczególnie że w niektórych językach te pojęcia się trochę mieszają. Funkcje i metody służą do wykonywania operacji – czyli do działania, modyfikowania czegoś, wyliczania, a nie do przechowywania danych. Jeśli próbujesz zrobić z ‘marka’ czy ‘rocznik’ funkcję lub metodę, tracisz całą strukturę danych, bo te wartości powinny być częścią obiektu – czyli być przechowywane jako pola. Interfejsy to zupełnie inna bajka – one opisują, co klasa powinna potrafić (czyli jakie metody ma mieć), ale same nie przechowują żadnych danych. To tak jakbyś powiedział, że samochód jest instrukcją obsługi, a nie fizycznym przedmiotem z konkretnymi atrybutami. Typowym błędem jest też mylenie pojęcia 'parametry' jako argumentów funkcji – tutaj chodzi o właściwości opisujące obiekt, więc nie pasuje to do funkcji ani metod. Dopiero po zrozumieniu, że pola są miejscem przechowywania stanu obiektu, można dobrze zaprojektować klasę oddającą realny obiekt z rzeczywistości. W praktyce, złe przypisanie atrybutów do funkcji czy interfejsów skutkuje chaosem w kodzie, trudnościami w utrzymaniu aplikacji oraz problemami z rozwojem projektu. Pola są po prostu fundamentem do budowania logiki obiektowej i każda próba ich zastąpienia innymi mechanizmami rodzi niepotrzebne komplikacje.

Pytanie 2

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

push(arg) – dodaje element
pop() – usuwa ostatnio dodany element
peek() – zwraca ostatnio dodany element bez usuwania
isEmpty() – sprawdza czy istnieją dane w strukturze
A. stos
B. drzewo binarne
C. tablica
D. kolejka FIFO
Zestaw metod przedstawionych w pytaniu – czyli push, pop, peek oraz isEmpty – jednoznacznie wskazuje na strukturę danych zwaną stos (stack). To jest taki bardzo charakterystyczny „magazyn”, gdzie zawsze mamy do czynienia z zasadą LIFO, czyli Last In, First Out. Oznacza to, że ostatni element, który dodaliśmy metodą push, będzie tym pierwszym, który usuniemy przez pop. Peek natomiast pozwala tylko podejrzeć, co jest na górze stosu, ale niczego nie usuwa. isEmpty z kolei daje nam szybki sposób sprawdzenia, czy na stosie w ogóle coś jeszcze zostało. W praktyce, stosy są niezbędne w wielu algorytmach i strukturach programistycznych – na przykład podczas wywołań rekurencyjnych funkcji (sam system operacyjny używa stosu do obsługi wywołań procedur), przy obsłudze nawiasów w kompilatorach czy podczas implementacji algorytmu DFS (Depth-First Search) w grafach. Moim zdaniem, nawet jeśli na początku wydaje się, że stos nie jest tak „potężny” jak inne struktury, to jego prostota jest właśnie największym atutem i dlatego jest tak często wykorzystywany w praktyce. Branżowe standardy, na przykład w językach takich jak Java czy C#, bezpośrednio udostępniają gotowe klasy Stack, które właśnie implementują dokładnie te metody – to pokazuje, jak fundamentalna jest ta struktura. Pewnie warto też pamiętać, że stosy mają swoje ograniczenia (np. nie nadadzą się do kolejkowania zadań), ale tam gdzie trzeba działać LIFO, są niezastąpione.

Pytanie 3

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. 4 osoby
B. 5 osób
C. 2 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 4

Jakie narzędzie jest używane do automatyzacji testów interfejsu użytkownika aplikacji webowych?

A. Trello
B. JIRA
C. Selenium
D. Slack
Pozostałe odpowiedzi, takie jak JIRA, Slack i Trello, nie są narzędziami przeznaczonymi do automatyzacji testów interfejsu użytkownika. JIRA to popularne narzędzie do zarządzania projektami, które często wykorzystuje się do śledzenia błędów i planowania zadań w zespołach programistycznych. Jest ono nieocenione w kontekście zarządzania cyklem życia aplikacji i usprawniania komunikacji w zespole, ale nie służy do automatyzacji testów. Slack natomiast to narzędzie do komunikacji zespołowej, które umożliwia szybką wymianę informacji i współpracę w czasie rzeczywistym. Choć może być używane do powiadomień o wynikach testów, nie jest narzędziem do ich automatyzacji. Trello, z kolei, to aplikacja do zarządzania projektami, która pomaga w organizacji zadań i pracy zespołowej za pomocą tablic i kart. Choć może wspomagać procesy zarządzania testami poprzez wizualizację postępów, nie jest narzędziem testowym samym w sobie. Często zdarza się, że osoby nowe w branży mylą narzędzia wspomagające zarządzanie projektami z narzędziami do testowania, co może prowadzić do nieporozumień. Warto więc zrozumieć ich różne zastosowania, by skutecznie wykorzystać każde z nich według ich przeznaczenia.

Pytanie 5

Co to jest API w kontekście programowania?

A. System zarządzania relacyjnymi bazami danych
B. Narzędzie do testowania interfejsu użytkownika aplikacji
C. Metoda kompresji danych w aplikacjach webowych
D. Interfejs programistyczny aplikacji, który definiuje sposób komunikacji między różnymi komponentami oprogramowania
API, czyli Interfejs Programistyczny Aplikacji, to zestaw reguł i protokołów, które umożliwiają różnym komponentom oprogramowania komunikację ze sobą. W praktyce API działa jako most między różnymi systemami, pozwalając na wymianę danych oraz funkcji. Na przykład, API może być wykorzystywane do integracji z zewnętrznymi serwisami, takimi jak systemy płatności, co pozwala na łatwe wdrożenie funkcji zakupów online w aplikacji. Stosowanie API zgodnie z zasadami RESTful czy GraphQL jest powszechną praktyką, ponieważ ułatwia rozwój i utrzymanie aplikacji, umożliwiając tworzenie skalowalnych rozwiązań. Co więcej, dobrze zdefiniowane API zwiększa bezpieczeństwo aplikacji, ograniczając bezpośredni dostęp do wewnętrznych mechanizmów oraz danych. Firmy często tworzą dokumentację API, aby programiści mogli szybko zrozumieć, jak z niego korzystać, co jest zgodne z zasadami dobrych praktyk w branży programistycznej.

Pytanie 6

Jakie środowisko jest przeznaczone do tworzenia aplikacji mobilnych dla urządzeń Apple, wykorzystujące różne języki programowania, takie jak Java i Objective C?

A. NetBeans
B. XCode
C. React Native
D. Android Studio
XCode to środowisko, które faktycznie jest fundamentem tworzenia aplikacji na urządzenia Apple, czyli iPhone’y, iPady czy nawet MacBooki. Apple od lat inwestuje w rozwój XCode i właśnie tam programiści mogą budować zarówno aplikacje natywne, jak i np. gry – i to z wykorzystaniem różnych języków, takich jak Objective-C i Swift. Co ciekawe, dawniej używano też Objective-C prawie wyłącznie, ale od kilku lat Apple promuje Swift, bo jest nowocześniejszy i dużo przyjemniej się w nim pisze. Moim zdaniem XCode to taki niezbędnik – bez niego praktycznie nie da się pisać porządnych aplikacji na iOS czy macOS. Samo środowisko jest zintegrowane ze wszystkimi narzędziami Apple: symulatorem urządzeń, Interface Builderem do projektowania graficznego oraz narzędziami do debugowania i testowania. Z mojego doświadczenia, jak ktoś zaczyna przygodę z aplikacjami mobilnymi dla Apple, to właśnie XCode jest pierwszym programem, z którym spędzi dużo czasu. I trochę ułatwia życie, bo automatycznie konfiguruje projekty pod standardy Apple, nie trzeba nic ręcznie ustawiać. To też świetne miejsce do nauki, bo dokumentacja jest wprost wbudowana w środowisko. Co ważne, XCode jest wymagany, żeby wrzucić gotową aplikację do App Store – tak jest po prostu zrobiony ekosystem Apple i żadna alternatywa nie daje tyle integracji i wsparcia dla natywnych rozwiązań Apple.

Pytanie 7

Programista może wykorzystać framework Angular do realizacji aplikacji:

A. rodzaju front-end
B. mobilnej
C. rodzaju back-end
D. na komputerze
Angular to świetne narzędzie do tworzenia aplikacji front-endowych. Chodzi o to, że odpowiada za to, co widzi użytkownik i jak może z tym interagować. Dzięki Angular możemy budować dynamiczne i responsywne aplikacje webowe. Z tego co widzę, używamy tam komponentów, modułów i rzeczy typu dwukierunkowe wiązanie danych, co naprawdę ułatwia życie. Bez wątpienia, Angular jest jednym z najpopularniejszych frameworków do robienia interfejsów użytkownika, co tylko potwierdza jego efektywność.

Pytanie 8

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

A. Webpack
B. Context API
C. Redux
D. MobX
Webpack to narzędzie do budowania, które służy do zarządzania zasobami w projekcie, a nie do zarządzania stanem aplikacji. Jego głównym celem jest przekształcanie i optymalizacja plików, takich jak JavaScript, CSS czy obrazy, przed ich wdrożeniem na produkcję. Dzięki Webpackowi można tworzyć modułowe aplikacje, które pozwalają na łatwe zarządzanie zależnościami. Przykładem użycia Webpacka może być skonfigurowanie go do kompresji plików JavaScript oraz CSS w celu zwiększenia wydajności aplikacji. W praktyce, Webpack jest szeroko stosowany w projektach React, aby efektywnie łączyć i optymalizować kod z różnych źródeł, co przekłada się na szybsze ładowanie się aplikacji. Standardy dotyczące zarządzania projektami przewidują, że narzędzia do budowania, takie jak Webpack, powinny być odpowiednio skonfigurowane w celu zapewnienia najlepszych praktyk dotyczących wydajności i organizacji kodu.

Pytanie 9

Który z wymienionych sposobów może przyczynić się do optymalizacji kodu źródłowego?

A. Zamiana zmiennych globalnych na lokalne
B. Dodanie większej liczby komentarzy w kodzie
C. Eliminacja nieużywanych zmiennych oraz funkcji
D. Zwiększenie ilości instrukcji warunkowych
Usunięcie nieużywanych zmiennych i funkcji to jedna z najskuteczniejszych metod optymalizacji kodu źródłowego. Nadmiarowe zmienne i niepotrzebne funkcje mogą spowalniać aplikację, zwiększać jej zużycie pamięci i powodować problemy z czytelnością kodu. Ich eliminacja upraszcza kod, zmniejsza ryzyko błędów i poprawia wydajność programu. Oczyszczanie kodu to kluczowy element procesu refaktoryzacji, który pozwala na utrzymanie wysokiej jakości oprogramowania oraz lepszą organizację projektu. Dodatkowo, minimalizacja kodu pomaga w szybszym ładowaniu aplikacji webowych, co ma bezpośredni wpływ na doświadczenie użytkownika (UX) oraz pozycjonowanie w wyszukiwarkach (SEO).

Pytanie 10

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

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

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

    for(int i = 0; i < 6; i++)
        wynik += tab[i];
    return wynik;
}
A. 23
B. 10
C. 20
D. 0
Rozwiązując takie zadania, warto nauczyć się dokładnie patrzeć na strukturę kodu. Funkcja fun1 przyjmuje tablicę intów i sumuje jej elementy. Tu pętla for przechodzi po wszystkich sześciu indeksach – od 0 do 5. Gdy podmienisz na liczby z zadania: 3, 4, 2, 4, 10 oraz 0 – po prostu dodajesz te wartości do siebie. Suma wychodzi 23. Czyli wynik funkcji to właśnie 23. To taki bardzo typowy przykład sumowania elementów tablicy – nie tylko na lekcjach, ale praktycznie wszędzie, np. jak liczysz sumę zamówień w sklepie internetowym albo punkty gracza w grze. Jeśli chodzi o dobre praktyki w C++, to warto wiedzieć, że lepiej przekazywać tablicę z dodatkowym parametrem długości, żeby nie robić magicznych liczb jak to '6' w pętli – można się wtedy łatwo pomylić przy zmianie rozmiaru. Moim zdaniem dobrze jest od razu przyswoić sobie nawyk wykorzystywania std::vector zamiast „gołych” tablic, bo są bezpieczniejsze i elastyczniejsze. To już taki krok w stronę kodu produkcyjnego. Ale podsumowując – jeśli widzisz tak napisany kod, to zawsze patrz, ile razy pętla się wykona i jakie są wartości w tablicy. Tylko tyle i aż tyle. W praktyce ta umiejętność przekłada się na szybkie debugowanie i pisanie niezawodnych programów.

Pytanie 11

Jakie działania mogą przyczynić się do ochrony swojego cyfrowego wizerunku w sieci?

A. Weryfikacja ustawień prywatności na platformach społecznościowych
B. Dzieleni się swoimi danymi dostępowymi z przyjaciółmi
C. Zamieszczanie wszystkich szczegółów dotyczących swojego życia prywatnego
D. Niepotwierdzanie źródeł publikowanych informacji
Sprawdzanie ustawień prywatności na portalach społecznościowych jest kluczowe dla ochrony cyfrowego wizerunku. Regularne aktualizowanie ustawień prywatności pozwala na kontrolowanie, kto ma dostęp do publikowanych treści, co chroni przed nieuprawnionym wykorzystaniem zdjęć, filmów i informacji osobistych. Dostosowanie widoczności postów oraz ograniczenie udostępniania danych osobowych minimalizuje ryzyko kradzieży tożsamości i cyberprzemocy. To proste działanie znacząco podnosi poziom bezpieczeństwa w sieci i pozwala utrzymać pozytywny wizerunek w internecie.

Pytanie 12

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

A. Framework oferuje funkcje użyteczne w konkretnej dziedzinie problemu
B. Framework zapewnia API do szerszego zestawu funkcji
C. Framework określa strukturę aplikacji i zapewnia jej fundament
D. Framework stanowi zbiór funkcji, które programista ma możliwość wykorzystania
Framework dostarcza gotowy szkielet aplikacji i narzuca architekturę, zgodnie z którą programista musi budować swoją aplikację. Oferuje zestaw narzędzi i komponentów, które upraszczają rozwój oprogramowania, przy jednoczesnym ograniczeniu swobody działania. Dzięki frameworkowi, programista nie musi tworzyć aplikacji od podstaw – dostaje narzędzia, które integrują się ze sobą, co przyspiesza proces developmentu i zapewnia spójność aplikacji.

Pytanie 13

W jednostce centralnej, za obliczenia na liczbach zmiennoprzecinkowych odpowiada

A. FPU
B. ALU
C. AU
D. IU
Funkcjonuje takie przekonanie, że wszystkie jednostki w procesorze ogarniają po trochu te same rzeczy, ale to nie do końca tak działa. ALU, czyli Arithmetic Logic Unit, rzeczywiście odpowiada za większość podstawowych operacji arytmetycznych oraz logicznych – dodawanie, odejmowanie, AND, OR czy XOR, ale jest zoptymalizowana do operacji na liczbach całkowitych. Kiedy jednak w grę wchodzą liczby zmiennoprzecinkowe, ALU sobie zwyczajnie nie radzi – nie została do tego zaprojektowana. Warto też wspomnieć o IU, czyli Integer Unit, która – jak sugeruje sama nazwa – jest odpowiedzialna za przetwarzanie liczb całkowitych. Spotkałem się z sytuacjami, gdzie niektórzy mylą IU z FPU, bo niby też coś liczy, ale jeśli chodzi o typy float czy double, to IU nic nie wskóra. AU natomiast, tak szczerze, nie jest powszechnie stosowanym terminem w kontekście architektury procesora. Może się czasem pojawić jako ogólne określenie Arithmetic Unit, ale to raczej archaiczne albo bardzo szerokie pojęcie, nie wskazujące konkretnie, które operacje są obsługiwane. Spotkałem się z tym głównie w starych podręcznikach lub bardzo ogólnych opisach sprzętu, ale dzisiaj nikt poważny nie mówi o AU w kontekście obliczeń zmiennoprzecinkowych. Typowym błędem myślowym jest założenie, że skoro coś jest „arytmetyczne”, to obsłuży dowolny typ liczby. W praktyce inżynierowie projektujący architekturę procesorów zawsze wyraźnie rozdzielają jednostki dla liczb całkowitych od tych dla zmiennoprzecinkowych, bo to zupełnie inne algorytmy i logika działania. Standardy takie jak IEEE 754 dotyczą właśnie FPU i precyzji operacji na floatach, a nie ALU czy IU. W praktycznym zastosowaniu, np. w oprogramowaniu do grafiki, multimediach czy symulacjach naukowych, to właśnie obecność FPU decyduje o wydajności i poprawności obliczeń. Dlatego akurat w tej dziedzinie nie ma miejsca na dowolność – każda jednostka procesora ma swoje konkretne zadanie i nie warto ich ze sobą mieszać.

Pytanie 14

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. wyszukującego literę w ciągu
B. odwracającego ciąg
C. sortującego ciąg od znaku o najniższym kodzie ASCII do znaku o najwyższym kodzie
D. sprawdzającego, czy dany ciąg jest palindromem
W tym zadaniu chodziło o rozpoznanie, co właściwie robi metoda fun1. Jeśli przeanalizujesz kod, to widać, że w pętli for program przechodzi przez wszystkie znaki wejściowego łańcucha od końca do początku i dokleja je do zmiennej output. Efekt? Zwracany napis jest po prostu oryginalnym tekstem zapisanym wspak, czyli odwróconym. To bardzo prosty przykład algorytmu odwracania ciągu znaków. W praktyce takie rozwiązania przydają się choćby wtedy, gdy chcemy sprawdzić, czy łańcuch jest palindromem (choć samo odwracanie to tylko pierwszy krok), przy szyfrowaniu prostymi metodami czy podczas manipulacji danymi wejściowymi, na przykład w edytorach tekstu lub różnych parserach. Moim zdaniem, warto pamiętać o dobrych praktykach – w Javie, jeśli masz do czynienia z wieloma operacjami na napisach, lepiej używać StringBuildera zamiast tworzyć nowe Stringi, bo jest to wydajniejsze pod kątem zarządzania pamięcią. Dla ciekawych: w bibliotekach standardowych Javy już istnieją gotowe narzędzia do odwracania ciągów (np. StringBuilder.reverse()), ale znajomość działania takiego algorytmu pozwala lepiej zrozumieć, jak działają operacje na napisach "pod spodem". Z mojego doświadczenia, umiejętność samodzielnego napisania takich prostych funkcji bardzo pomaga przy nauce bardziej zaawansowanych algorytmów tekstowych oraz rozwija wyobraźnię programistyczną.

Pytanie 15

Które stwierdzenie dotyczące interfejsu w Java jest prawdziwe?

A. W interfejsie można definiować implementacje metod statycznych
B. Interfejs może dziedziczyć po wielu klasach jednocześnie
C. Wszystkie metody w interfejsie są domyślnie publiczne i abstrakcyjne
D. Interfejs może zawierać pola z dostępem protected
Interfejsy w języku Java są fundamentalnym elementem programowania obiektowego, pozwalającym na definiowanie kontraktów, które muszą być implementowane przez klasy. Stwierdzenie, że wszystkie metody w interfejsie są domyślnie publiczne i abstrakcyjne, jest całkowicie zgodne z zasadami języka Java. Oznacza to, że nie trzeba jawnie deklarować tych modyfikatorów dostępu, ponieważ metody zdefiniowane w interfejsie są zawsze dostępne dla klas implementujących ten interfejs. To podejście promuje luźne powiązania między kodem oraz ułatwia testowanie i utrzymanie aplikacji. Przykładem praktycznym może być interfejs Comparable, który definiuje metodę compareTo. Klasy, które implementują ten interfejs, muszą dostarczyć konkretnej logiki porównywania obiektów, co pozwala na ujednolicenie sposobu, w jaki obiekty są porównywane w kolekcjach. Warto również zauważyć, że od Javy 8 interfejsy mogą zawierać metody domyślne z implementacją, ale nawet te metody są publiczne. Poprawne zrozumienie roli interfejsów jest kluczowe w projektowaniu systemów z zastosowaniem wzorców projektowych, takich jak MVC czy strategia.

Pytanie 16

Dlaczego w wyniku działania tego kodu w języku C++ na ekranie pojawiła się wartość 0 zamiast 50?

int oblicz(int x)  {
    int i = 50;
    x = x + i;
    return i;
}

int main()  {
    int x = 0;
    int wynik = oblicz(x);
    std::cout << x;
}
A. Niepoprawnie zdefiniowano działanie wewnątrz funkcji.
B. Argument funkcji został przekazany przez wartość, a nie przez referencję.
C. Funkcja zwraca wartość, chociaż nie powinna jej zwracać.
D. Zmienna x powinna być inicjowana wartością równą 1, a nie 0.
Błąd związany z przekazywaniem argumentu przez wartość, a nie przez referencję, to klasyka w C++. W tym kodzie zmienna x idzie jako kopia, więc zmiany w oblicz nie wpływają na oryginał w main. Może popełniłeś błąd, bo nie do końca rozumiesz różnicę między tymi dwoma metodami. Te inne odpowiedzi wskazują na różne problemy, jak źle zainicjowana zmienna czy błędy w zwracaniu wartości. Ale w oblicz wszystko powinno działać poprawnie, bo zwraca wartość typu int, a problem leży w tym, że przekazujesz kopię argumentu. Warto pamiętać, że poprawny kod wymaga sensownego przepływu wartości między funkcjami i zrozumienia, że x w main nie zmienia się, bo modyfikujesz kopię. Często mylimy to i myślimy, że zmiany w funkcji wpływają na oryginały, a w C++ musisz użyć referencji albo wskaźników, żeby to zadziałało. Zrozumienie tego jest kluczowe, żeby dobrze ogarniać funkcje w C++ i unikać takich problemów w przyszłości.

Pytanie 17

Który z poniższych elementów nie jest związany z architekturą mikroserwisów?

A. Komunikacja przez API
B. Niezależne wdrażanie usług
C. Skalowalność poszczególnych usług
D. Monolityczny kod źródłowy
Monolityczny kod źródłowy to podejście, w którym wszystkie komponenty aplikacji są ze sobą ściśle powiązane i zintegrowane w jedną całość. W przeciwieństwie do architektury mikroserwisów, która pozwala na budowę systemów jako zbioru niezależnych usług, monolityczne podejście ogranicza możliwości rozwoju i skalowania aplikacji. W mikroserwisach poszczególne usługi mogą być rozwijane, wdrażane i skalowane niezależnie od siebie, co zwiększa elastyczność i skraca czas realizacji. Przykładem zastosowania architektury mikroserwisów może być serwis e-commerce, w którym oddzielne mikroserwisy obsługują płatności, zarządzanie produktami i wysyłkę. Dzięki temu, jeśli chcemy wprowadzić zmiany w systemie płatności, możemy to zrobić bez wpływu na inne obszary aplikacji. Warto również zauważyć, że podejście to umożliwia lepsze zarządzanie zespołami deweloperskimi, które mogą pracować równolegle nad różnymi usługami, co przyspiesza proces dostarczania wartości dla użytkowników.

Pytanie 18

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

A. Kompilowanie aplikacji
B. Opracowywanie interfejsu graficznego
C. Debugowanie kodu w celu znalezienia błędów
D. Projektowanie bazy danych
Debugowanie kodu w celu znalezienia błędów to jeden z kluczowych etapów testowania aplikacji. Proces ten polega na uruchamianiu programu w trybie debugowania, co pozwala na śledzenie jego działania linijka po linijce i identyfikowanie miejsc, w których występują błędy. Debugowanie umożliwia analizowanie wartości zmiennych, śledzenie przepływu programu i wykrywanie nieoczekiwanych zachowań, co jest niezbędne do usunięcia błędów i poprawy wydajności aplikacji. Narzędzia do debugowania, takie jak Visual Studio, PyCharm czy Chrome DevTools, pozwalają na dokładne testowanie kodu na różnych etapach jego rozwoju, co znacząco skraca czas naprawy błędów i zwiększa jakość oprogramowania.

Pytanie 19

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

A. Samodokumentujący się kod
B. Maksymalna złożoność funkcji
C. Konsekwentne nazewnictwo
D. Jedna odpowiedzialność funkcji
Maksymalna złożoność funkcji to pojęcie, które odnosi się do zasady, że funkcje powinny być jak najmniej złożone, aby były zrozumiałe i łatwe w utrzymaniu. Czysty kod promuje ideę, że każda funkcja powinna mieć jasno określoną odpowiedzialność, co w praktyce oznacza ograniczenie jej złożoności. Przykładem może być rozdzielenie złożonej logiki biznesowej na kilka prostszych funkcji, co ułatwia ich testowanie i ponowne wykorzystanie. Warto zwrócić uwagę, że zgodnie z zasadą KISS (Keep It Simple, Stupid) dąży się do prostoty w projektowaniu kodu, co nie tylko zwiększa jego czytelność, ale także minimalizuje ryzyko błędów. Dobrze napisany kod powinien być również samodokumentujący się, co oznacza, że jego struktura i nazwy zmiennych powinny jasno wskazywać na ich funkcjonalność. Przestrzeganie zasady maksymalnej złożoności funkcji jest kluczowe w kontekście długoterminowego utrzymania aplikacji, ponieważ zmniejsza koszty związane z modyfikacjami oraz poprawkami.

Pytanie 20

Technika konstruowania algorytmu polegająca na rozbiciu na dwa lub więcej mniejszych podproblemów, aż do momentu, gdy ich części będą wystarczająco proste do bezpośredniego rozwiązania, nosi nazwę:

A. dziel i zwyciężaj
B. heurystycznej
C. komiwojażera
D. najkrótszej trasy
Technika „dziel i zwyciężaj” (ang. divide and conquer) to jedno z tych podejść, które moim zdaniem warto naprawdę dobrze rozumieć, bo spotyka się je praktycznie wszędzie w informatyce. Chodzi tutaj o rozbijanie dużego problemu na mniejsze, bardziej strawne kawałki, które rozwiązujemy niezależnie, a potem składamy wyniki w całość. To bardzo eleganckie, bo pozwala np. mocno uprościć złożone zadania, a przy okazji często optymalizuje czas działania algorytmu. Przykładem mogą być sortowanie szybkie (quicksort) czy sortowanie przez scalanie (merge sort). W praktyce branżowej, kiedy pracuje się nad dużymi systemami albo algorytmami operującymi na wielkich zbiorach danych, taki sposób myślenia bardzo się przydaje, bo pozwala łatwo podzielić pracę nawet między kilku programistów. Standardy branżowe, zwłaszcza w kontekście rozwiązań algorytmicznych czy projektowania systemów, promują właśnie takie modularne podejście. Sam kiedyś przekonałem się, że dużo łatwiej jest testować i utrzymywać kod, kiedy trzyma się tej zasady. Fajnie wiedzieć, że często to właśnie „dziel i zwyciężaj” leży u podstaw wielu struktur danych, algorytmów wyszukiwania czy nawet analizy obrazu, nie tylko w typowym programowaniu. Warto pamiętać, że to nie tylko teoria – w codziennej pracy taki styl rozwiązywania problemów pozwala szybciej wychwytywać i naprawiać błędy, a to przecież kluczowe w projektach IT.

Pytanie 21

Definicja konstruktora dla zaprezentowanej klasy w języku C++ może być sformułowana jak poniżej:

class Owoc
{
    public:
        double waga;
        string nazwa;
        Owoc(double waga, string nazwa);
};

Deklaracja 1:
Owoc::Owoc(double waga, string nazwa) {
    this -> waga = waga;
    this -> nazwa = nazwa;
}

Deklaracja 2:
Construct::Owoc(double waga, string nazwa) {
    this -> waga = waga;
    this -> nazwa = nazwa;
}

Deklaracja 3:
Construct::Owoc(double waga, string nazwa) {
    this.waga = waga;
    this.nazwa = nazwa;
}

Deklaracja 4:
Owoc::Owoc(double waga, string nazwa) {
    this.waga = waga;
    this.nazwa = nazwa;
}
A. Deklaracji 1
B. Deklaracji 2
C. Deklaracji 4
D. Deklaracji 3
Wiele osób, szczególnie na początku nauki, myli się tu przez znajomość składni z innych języków lub nie do końca rozumie, jak działa zakres nazw w C++. Najczęstszy błąd w przedstawionych błędnych deklaracjach polega na używaniu nieprawidłowej nazwy klasy w kwalifikatorze zasięgu, czyli przed '::'. W C++ implementując konstruktor poza ciałem klasy, musimy napisać Owoc::Owoc(...), a nie, na przykład, Construct::Owoc(...). To bardzo podstawowa, ale kluczowa kwestia, która wynika z zasad języka. Często osoby przesiadające się z innych języków, np. z Javy czy C#, próbują też używać notacji this.waga (z kropką), co niestety w C++ jest nieprawidłowe – tutaj operator dostępu do składowych przez wskaźnik to '->', bo this jest wskaźnikiem do obiektu. Takie subtelności bywają podchwytliwe i sam pamiętam, jak łatwo się na tym przejechać, zwłaszcza jak się przeskakuje pomiędzy językami. Jeszcze inny typowy błąd to mylenie konstruktora z zupełnie innymi funkcjami albo próba zadeklarowania konstruktora w przestrzeni nazw, która nie odpowiada klasie – przez co kompilator nie rozpoznaje takiej funkcji jako konstruktora i pojawiają się często niejasne błędy kompilacji. Warto mocno zapamiętać, że w C++ musimy bardzo pilnować zarówno nazewnictwa, jak i składni operatorów, bo automatycznych podpowiedzi na etapie pisania kodu czasem brakuje. Dobrą praktyką jest też sprawdzanie, czy używamy poprawnych typów dostępu do pól (-> zamiast .). Wreszcie, nie można używać innych nazw klas niż tej, której konstruktor rzeczywiście definiujemy. Każde odstępstwo od tej reguły prowadzi do sporych problemów i nieporozumień w kodzie. Z mojego doświadczenia wynika, że te drobiazgi, które wydają się mało istotne, potem najbardziej komplikują pracę i utrzymanie projektu. Warto więc od razu przyzwyczajać się do poprawnej składni i nie kombinować z rozwiązaniami "z innych światów" – C++ rządzi się swoimi prawami i trzymając się ich, można zyskać sporo pewności przy pisaniu kodu.

Pytanie 22

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

A. Python
B. Java
C. C++
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.

Pytanie 23

Co będzie wynikiem działania poniższego kodu JavaScript?

const obj = { name: 'John', greet: function() { setTimeout(function() { console.log(`Hello, ${this.name}`); }, 1000); } }; obj.greet();
A. Hello, undefined
B. Hello, John
C. TypeError
D. Hello, null
Wynik działania tego kodu to `Hello, undefined`, co jest spowodowane tym, jak działa kontekst `this` w JavaScript. Gdy wywołujemy metodę `greet`, w kontekście tej metody `this` odnosi się do obiektu `obj`. Proszę zauważyć, że metoda `greet` używa funkcji anonimowej w `setTimeout`, a to zmienia kontekst `this`. W momencie, gdy `setTimeout` wywołuje funkcję, `this` nie odnosi się już do obiektu `obj`, lecz do globalnego obiektu (w przeglądarkach jest to `window`), gdzie `name` nie jest zdefiniowane. Dlatego w konsoli widzimy `Hello, undefined`. Takie zachowanie jest typowe dla JavaScript, więc warto zrozumieć, jak można to zmienić, np. używając funkcji strzałkowej (`() => {}`), która nie ma własnego kontekstu `this`, więc po prostu korzysta z kontekstu otaczającego. Użycie strzałek w takich przypadkach jest coraz częściej zalecane w nowoczesnym kodzie.

Pytanie 24

Co to jest XSS (Cross-Site Scripting)?

A. Framework do tworzenia responsywnych stron internetowych
B. Luka bezpieczeństwa pozwalająca na wstrzyknięcie złośliwego kodu do stron przeglądanych przez innych użytkowników
C. Protokół komunikacyjny używany w aplikacjach internetowych
D. Technika optymalizacji kodu JavaScript do zwiększenia wydajności strony
Cross-Site Scripting (XSS) to luka bezpieczeństwa, która umożliwia atakującym wstrzykiwanie złośliwego kodu JavaScript do stron internetowych, które są następnie przeglądane przez innych użytkowników. W wyniku tego ataku, złośliwy kod może być wykonany w kontekście przeglądarki ofiary, co może prowadzić do kradzieży sesji, danych osobowych, czy też przejęcia kontroli nad kontem użytkownika. Aby zapobiegać XSS, programiści powinni stosować techniki takie jak walidacja i oczyszczanie danych wejściowych, a także korzystanie z nagłówków HTTP, takich jak Content Security Policy (CSP). Przykładem może być sytuacja, gdy aplikacja webowa przyjmuje dane w formularzach bez odpowiedniego sprawdzenia, co pozwala na umieszczenie skryptu, który zyskuje dostęp do cookies użytkownika. Zrozumienie i zabezpieczenie się przed XSS jest kluczowe w kontekście budowania bezpiecznych aplikacji webowych, co jest zgodne z najlepszymi praktykami branżowymi.

Pytanie 25

Jakie jest fundamentalne zagadnienie w projektowaniu aplikacji w architekturze klient-serwer?

A. Brak podziału na role klienta i serwera
B. Funkcjonowanie aplikacji wyłącznie w trybie offline
C. Przeniesienie wszystkich obliczeń na stronę klienta
D. Użycie serwera jako głównego miejsca przetwarzania danych
Użycie serwera jako centralnego miejsca przetwarzania danych jest kluczowym elementem architektury klient-serwer. Serwer pełni rolę centralnego punktu, który zarządza żądaniami klientów, przechowuje dane i zapewnia odpowiedzi na zapytania. Taki model zapewnia większe bezpieczeństwo danych, ułatwia zarządzanie zasobami i umożliwia skalowanie aplikacji w miarę wzrostu liczby użytkowników. Architektura klient-serwer jest szeroko stosowana w aplikacjach webowych, systemach bankowych oraz usługach chmurowych, gdzie konieczna jest centralizacja danych i ich ochrona.

Pytanie 26

Celem zastosowania wzorca Obserwator w tworzeniu aplikacji WEB jest

A. dostosowanie interfejsu użytkownika do różnych typów odbiorców
B. monitorowanie interakcji użytkownika i wysyłanie wyjątków
C. informowanie obiektów o modyfikacji stanu innych obiektów
D. zarządzanie funkcjami synchronicznymi w kodzie aplikacji
Wzorzec Obserwator, znany również jako Observer, jest fundamentem programowania związanego z aplikacjami webowymi, szczególnie w kontekście architektury MVC (Model-View-Controller). Jego głównym celem jest umożliwienie obiektom (zwanym obserwatorami) subskrybowania zmian stanu innych obiektów (zwanych obserwowanymi). Kiedy stan obiektu obserwowanego ulega zmianie, wszystkie powiązane obiekty obserwujące są automatycznie powiadamiane o tej zmianie. Takie podejście jest szczególnie użyteczne w aplikacjach, gdzie interfejs użytkownika musi być dynamicznie aktualizowany w odpowiedzi na zmiany danych, na przykład w przypadku aplikacji do zarządzania danymi w czasie rzeczywistym. Przykładem może być aplikacja czatu, w której nowe wiadomości są automatycznie wyświetlane użytkownikom, gdy tylko są dodawane przez innych. Wzorzec ten jest również zgodny z zasadami SOLID, zwłaszcza z zasadą otwarte-zamknięte, umożliwiając rozwijanie aplikacji bez konieczności modyfikowania istniejących klas. W różnych technologiach webowych, takich jak JavaScript z użyciem frameworków takich jak React czy Angular, wzorzec Obserwator jest implementowany przez mechanizmy takie jak stany komponentów, co przyczynia się do lepszej organizacji kodu i zachowania jego czytelności.

Pytanie 27

W jakiej sytuacji kolekcja typu lista okaże się bardziej wydajna niż tablica?

A. Gdy liczba elementów w kolekcji zmienia się dynamicznie
B. Gdy mamy pewność co do dokładnego rozmiaru kolekcji przed kompilacją
C. Gdy liczba elementów w kolekcji jest niezmienna
D. Gdy chcemy uzyskać dostęp do elementów przy pomocy indeksu
Lista to dynamiczna struktura danych, która pozwala na efektywne dodawanie i usuwanie elementów, zwłaszcza gdy liczba elementów zmienia się w trakcie działania programu. Listy są bardziej elastyczne niż tablice, ponieważ mogą dynamicznie dostosowywać swoją wielkość bez potrzeby alokacji dodatkowej pamięci. W przypadku dynamicznych operacji, takich jak częste wstawianie i usuwanie elementów, listy są znacznie bardziej wydajne niż tablice, które wymagają przesunięcia wszystkich elementów po każdej operacji. Listy świetnie sprawdzają się w implementacji kolejek, stosów oraz w strukturach, które muszą rosnąć i kurczyć się podczas działania aplikacji.

Pytanie 28

Kod w bibliotece React.js oraz w frameworku Angular, który został zaprezentowany, ma na celu wyświetlenie

Fragment kodu React.js:
state = {    zm1: 0   };
hanleEv = () => {
    this.setState({zm1: this.state.zm1 + 1});
}
render() {
    return (<div>
        <span>{this.state.zm1}</span>
        <button onClick={this.handleEv}>BTN_1</button>
    </div>);
}
Fragment kodu Angular:
@Component({
    selector: 'sel1',
    template: `<span>{{ zm1 }}</span>
              <button (click)="onBtnCilcked()">BTN_1</button>`
})
export class Licznik1Component {
    zm1 = 0;
    onBtnCilcked() { this.zm1++; }
}
A. wartości 0 po naciśnięciu przycisku
B. wyłącznie przycisku oraz obsłużenie zdarzenia click, które ono generuje
C. tylko napisu BTN_1
D. liczby kliknięć przycisku
Ten kod, zarówno w React.js jak i w Angularze, jest klasycznym przykładem prostego licznika. To, co tu się dzieje, to tak naprawdę zliczanie kliknięć użytkownika w przycisk. Za każdym razem, gdy naciśniesz BTN_1, zmienna (zm1) jest inkrementowana – czyli po prostu zwiększana o jeden. W React za to odpowiada metoda setState, która zmienia stan komponentu – dzięki temu interfejs od razu aktualizuje się bez przeładowywania strony. W Angularze natomiast działa to przez tzw. dwukierunkową komunikację z template’em i automatyczną detekcję zmian – metoda onBtnCilcked w komponencie modyfikuje zmienną, a framework sam aktualizuje widok. Z mojego doświadczenia, takie podejście do zarządzania stanem to podstawa w nowoczesnych aplikacjach, szczególnie jeśli chodzi o responsywność i natychmiastową reakcję na akcje użytkownika. Liczniki są zresztą jednym z pierwszych przykładów, jakie się pisze ćwicząc frameworki frontendowe, bo świetnie pokazują, jak działa przepływ danych i odświeżanie elementów UI. Warto dodać, że trzymanie licznika kliknięć w stanie komponentu (a nie np. jako zmienną globalną) jest zgodne z dobrymi praktykami – bo ogranicza zakres danych i ułatwia zarządzanie większymi aplikacjami. Takie wzorce potem można z powodzeniem przenieść do trudniejszych projektów, na przykład liczników, koszyków, liczby zamówień czy nawet zaawansowanych dashboardów. W praktyce ten mechanizm inkrementowania wartości po kliknięciu użytkownika jest jednym z najczęściej używanych w interaktywnych aplikacjach internetowych.

Pytanie 29

Który z wymienionych frameworków służy do budowy aplikacji webowych w C#?

A. ASP.NET Core
B. Angular
C. Django
D. React.js
ASP.NET Core to nowoczesny, wydajny i skalowalny framework opracowany przez Microsoft, który jest przeznaczony do budowy aplikacji webowych w języku C#. ASP.NET Core umożliwia tworzenie dynamicznych stron internetowych, API oraz aplikacji mikroserwisowych. Jego modularność i wsparcie dla kontenerów (Docker) oraz chmury sprawiają, że jest to jeden z najczęściej wybieranych frameworków w środowiskach enterprise. ASP.NET Core obsługuje zarówno aplikacje serwerowe, jak i aplikacje klient-serwer, a dzięki technologii Razor Pages i Blazor pozwala na budowanie aplikacji, w których logika biznesowa jest ściśle zintegrowana z warstwą prezentacji. Dodatkowo ASP.NET Core oferuje wbudowane mechanizmy do zarządzania tożsamością użytkowników, autoryzacji i autentykacji, co czyni go doskonałym wyborem do tworzenia aplikacji biznesowych oraz korporacyjnych.

Pytanie 30

Zademonstrowana pętla wykorzystuje obiekt random do:

var random = new Random();
String pulaZnakow = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ";
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. wielokrotnego generowania liczby, aby stworzyć ciąg z liczb pseudolosowych
B. uzupełniania tablicy danymi w postaci liczb pseudolosowych
C. jednorazowego wylosowania znaku z określonego zestawu znaków
D. stworzenia losowego napisu o długości 8 znaków składającego się z liter
Kod, który został przedstawiony, to typowy przykład generowania losowego napisu, takiego jak hasło czy token sesji. Random służy tutaj do wielokrotnego losowania indeksów z określonego zakresu, które następnie są używane do pobierania znaków z puli liter. W efekcie – po przejściu całej pętli – zmienna 'wynik' zawiera napis złożony z 8 losowo dobranych liter z podanego zestawu. Tak się właśnie w praktyce koduje np. generator jednorazowych haseł lub krótkich identyfikatorów użytkowników. Często takie rozwiązania spotyka się w aplikacjach internetowych, gdzie bezpieczeństwo i nieprzewidywalność takich danych są kluczowe. Zresztą, korzystanie z Random i gotowej puli znaków to branżowy standard, jeśli chodzi o prostą losowość tekstową (chociaż do kryptografii są lepsze klasy, np. RNGCryptoServiceProvider). Warto też pamiętać, że pętle for idealnie nadają się do składania ciągów o z góry ustalonej długości, co jest bardzo czytelne i zgodne z dobrymi praktykami C#. Ogólnie, ten sposób generowania losowego stringa jest szybki, łatwy do zrozumienia i nieźle się skaluje – no i sprawdza się rewelacyjnie w różnych projektach, gdzie trzeba wygenerować coś pseudo-losowego, ale czytelnego dla człowieka. Sam się kiedyś złapałem na tym, jak często taki kod się przydaje przy rejestracji użytkowników czy obsłudze prostych quizów online.

Pytanie 31

Jakie informacje przedstawia diagram Gantta?

A. Plan działań w projekcie
B. Strukturę plików w projekcie
C. Model przepływu danych
D. Relacje między różnymi projektami
Diagram Gantta to narzędzie używane do wizualizacji harmonogramu zadań w projekcie. Przedstawia on zadania w układzie osi czasu, co pozwala na łatwe śledzenie terminów, zależności i etapów realizacji projektu. Diagram Gantta jest niezwykle przydatny w dużych projektach, ponieważ ułatwia planowanie zasobów i umożliwia identyfikowanie potencjalnych opóźnień. Dzięki czytelnej formie, managerowie mogą szybko ocenić, które zadania są w trakcie realizacji, a które są opóźnione. Diagramy Gantta są szeroko stosowane w zarządzaniu projektami budowlanymi, IT oraz w planowaniu kampanii marketingowych.

Pytanie 32

Zapisany fragment w C# wskazuje na definicję klasy Car, która:

public class Car: Vehicle {     ...   }
A. jest powiązana z klasą Vehicle
B. stanowi klasę bazową (nie dziedziczy po żadnej klasie)
C. używa prywatnych pól klasy Vehicle
D. dziedziczy po Vehicle
W przedstawionym kodzie w języku C# mamy definicję klasy Car, która dziedziczy po klasie Vehicle. Dziedziczenie to fundamentalny mechanizm programowania obiektowego, pozwalający jednej klasie przejąć właściwości i metody innej klasy. W praktyce oznacza to, że klasa Car automatycznie zyskuje dostęp do metod i właściwości publicznych oraz chronionych klasy Vehicle, co umożliwia ponowne użycie kodu i zwiększa jego przejrzystość. Dziedziczenie jest kluczowe w projektowaniu skalowalnych systemów, gdzie umożliwia tworzenie bardziej specyficznych klas na podstawie klas ogólnych, co jest zgodne z zasadą DRY (Don't Repeat Yourself). Przykładowo, jeżeli klasa Vehicle zawiera metody takie jak Start() i Stop(), klasa Car może je wykorzystać bez konieczności ponownego definiowania. Dobre praktyki w programowaniu obiektowym zalecają wykorzystywanie dziedziczenia do tworzenia hierarchii klas, które logicznie odwzorowują relacje „jest-a” pomiędzy obiektami w systemie. Ważne jest też unikanie zbyt głębokiego dziedziczenia, co może prowadzić do skomplikowanego i trudnego w utrzymaniu kodu. Zrozumienie dziedziczenia jest kluczowe dla efektywnego wykorzystania wzorców projektowych, takich jak wzorzec projektowy Adapter czy Dekorator.

Pytanie 33

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
B. GoldPoints, Name, Id
C. GoldPoints, Name, Id, Age
D. GoldPoints
Ta odpowiedź dobrze pokazuje, jak działa dziedziczenie i modyfikatory dostępu w C#. W klasie GoldCustomer masz dostęp do własnych pól, czyli GoldPoints, oraz do pól odziedziczonych po klasie bazowej Customer. Tutaj kluczowe jest rozumienie, które pola są faktycznie dostępne. Skoro Name jest publiczne, to bez żadnych kombinacji można się do niego dobrać z dowolnego miejsca – nawet spoza klasy. Id jest chronione (protected), więc według zasad OOP dostępne jest w klasie bazowej oraz wszystkich pochodnych – czyli właśnie w GoldCustomer. To bardzo praktyczne, bo często się zdarza, że potrzebujemy pracować na polach z klasy bazowej, ale nie chcemy, żeby były one widoczne na zewnątrz klasy (np. przez innych programistów korzystających z API). Age jest prywatne i tu już nie da się go bezpośrednio użyć w klasie pochodnej. Z mojego doświadczenia korzystanie z protected dla rzeczy, które mają być dostępne tylko w hierarchii dziedziczenia, to codzienność – pozwala zachować elastyczność, ale i bezpieczeństwo enkapsulacji. Praktycznie rzecz biorąc, jak piszesz klasy dziedziczące po innych, zawsze warto zerknąć na poziomy dostępu, bo od nich zależy, do czego masz dostęp i co możesz odziedziczyć. Wzorce projektowe, jak np. Template Method, mocno polegają na mechanizmach dziedziczenia i odpowiedniego ustawienia widoczności pól czy metod. Przemyślany dobór public, protected, private ułatwia utrzymanie kodu oraz chroni przed przypadkowym wykorzystaniem nieodpowiednich elementów klasy, co w większych projektach bywa naprawdę kluczowe.

Pytanie 34

Która z wymienionych sytuacji stanowi naruszenie praw autorskich?

A. Nabycie licencji na oprogramowanie
B. Używanie programu typu open-source zgodnie z warunkami licencji
C. Tworzenie kopii zapasowej legalnie zakupionego programu
D. Udostępnianie filmu objętego prawami autorskimi bez zgody właściciela
Publikowanie filmu chronionego prawami autorskimi bez zgody właściciela jest naruszeniem praw autorskich. Prawa autorskie chronią twórców przed nieuprawnionym kopiowaniem, dystrybucją i rozpowszechnianiem ich dzieł. W przypadku filmów, muzyki czy oprogramowania, każde użycie bez odpowiednich licencji lub zgody właściciela jest niezgodne z prawem. Twórcy mają prawo do wynagrodzenia za swoją pracę, a naruszenia mogą skutkować wysokimi grzywnami, a nawet postępowaniem sądowym. Przestrzeganie praw autorskich wspiera rozwój kultury i technologii, chroniąc interesy twórców.

Pytanie 35

Co to jest local storage w kontekście aplikacji webowych?

A. Mechanizm pozwalający na przechowywanie danych w przeglądarce użytkownika bez określonego czasu wygaśnięcia
B. Baza danych NoSQL działająca na serwerze aplikacji
C. System plików tymczasowych używany przez przeglądarkę
D. Technologia przechowywania danych w pamięci RAM aplikacji
Local storage to mechanizm dostępny w przeglądarkach internetowych, który pozwala na przechowywanie danych w formacie klucz-wartość. W przeciwieństwie do cookies, które mają czas wygaśnięcia, dane w local storage są przechowywane bezterminowo, co oznacza, że pozostają dostępne nawet po zamknięciu przeglądarki. Dzięki temu deweloperzy mogą tworzyć aplikacje webowe, które pamiętają preferencje użytkowników, stany formularzy czy inne istotne informacje. Typowym zastosowaniem local storage może być zapisywanie ustawień użytkownika w grach przeglądarkowych lub aplikacjach do zarządzania zadaniami. Warto również wspomnieć, że local storage ma limit pojemności wynoszący zazwyczaj około 5 MB na domenę, co czyni go odpowiednim dla przechowywania małych ilości danych. Ponadto, korzystając z local storage, deweloperzy powinni pamiętać o kwestiach bezpieczeństwa, takich jak unikanie przechowywania wrażliwych danych, a także o stosowaniu technik takich jak serializacja danych w formacie JSON, co ułatwia ich późniejsze wykorzystanie.

Pytanie 36

Które z wymienionych oznaczeń wskazuje na liniową złożoność algorytmu?

A. O(n²)
B. O(log n)
C. O(1)
D. O(n)
Złożoność O(n) oznacza liniową zależność czasu wykonania algorytmu od rozmiaru danych wejściowych. Oznacza to, że dla każdego dodatkowego elementu algorytm wykonuje jedną dodatkową operację. Algorytmy liniowe są jednymi z najczęściej stosowanych w praktyce, ponieważ oferują dobrą równowagę między szybkością a złożonością implementacji. Przykłady algorytmów o złożoności O(n) to przeszukiwanie liniowe (Linear Search), sumowanie elementów tablicy oraz niektóre algorytmy sortowania, takie jak Counting Sort dla określonych warunków. Liniowa złożoność czyni te algorytmy bardzo efektywnymi przy przetwarzaniu dużych zbiorów danych.

Pytanie 37

Jakie z wymienionych narzędzi jest szeroko stosowane do debugowania aplikacji internetowych?

A. Chrome DevTools
B. Blender
C. Postman
D. Git
Chrome DevTools to potężne narzędzie wbudowane w przeglądarkę Google Chrome, które umożliwia debugowanie aplikacji webowych. Umożliwia ono analizowanie struktury DOM, monitorowanie sieci, profilowanie wydajności oraz inspekcję kodu JavaScript. Chrome DevTools pozwala na śledzenie błędów w czasie rzeczywistym, edytowanie stylów CSS oraz modyfikowanie HTML bezpośrednio w przeglądarce, co znacznie przyspiesza proces rozwoju i testowania aplikacji webowych.

Pytanie 38

Jakie oprogramowanie służy do monitorowania błędów oraz zarządzania projektami?

A. Jasmine
B. Jira
C. Bugzilla
D. Git
Jira to zaawansowane oprogramowanie do zarządzania projektami oraz śledzenia błędów, stworzone przez firmę Atlassian. Jest powszechnie stosowane w zespołach zajmujących się rozwijaniem oprogramowania, ale również znajduje zastosowanie w różnych dziedzinach, takich jak zarządzanie projektami, wsparcie techniczne oraz śledzenie zadań. Jira oferuje bogaty zestaw funkcji, które umożliwiają planowanie sprintów, monitorowanie postępów prac, zarządzanie backlogiem oraz raportowanie wydajności zespołu. Użytkownicy mogą tworzyć niestandardowe workflow, co pozwala dostosować procesy pracy do specyficznych potrzeb organizacji. Dzięki integracji z innymi narzędziami Atlassian, takimi jak Confluence czy Bitbucket, Jira jest elementem ekosystemu, który wspiera współpracę w zespołach. Przykładem zastosowania Jira może być zarządzanie cyklem życia produktu, gdzie zespół deweloperski wykorzystuje to narzędzie do śledzenia błędów, zarządzania wymaganiami oraz planowania wydań. Korzystanie z Jira wspiera podejście Agile, co jest zgodne z nowoczesnymi standardami zarządzania projektami.

Pytanie 39

W jakich sytuacjach zastosowanie rekurencji może być bardziej korzystne niż użycie iteracji?

A. Gdy kod źródłowy ma być zoptymalizowany dla starszych kompilatorów
B. Kiedy liczba iteracji przewyższa maksymalny zakres zmiennej licznikowej
C. Gdy algorytm wymaga naturalnego podziału na mniejsze podproblemy
D. Kiedy program jest uruchamiany w środowisku wielowątkowym
Rekurencja jest bardziej efektywna od iteracji, gdy algorytm można naturalnie podzielić na mniejsze podproblemy. Przykładami są algorytmy podziału i zwycięzcy (divide and conquer), takie jak wyszukiwanie binarne, sortowanie szybkie (quick sort) czy obliczanie wartości liczb Fibonacciego. Rekurencja pozwala na bardziej eleganckie i przejrzyste rozwiązanie problemów, które mają strukturę rekurencyjną. W takich przypadkach kod jest krótszy i bardziej czytelny, co ułatwia jego konserwację i rozwój.

Pytanie 40

W jaki sposób określa się wypadek związany z pracą?

A. Każde zdarzenie, które prowadzi do opóźnienia w wykonaniu obowiązków
B. Każde zdarzenie, które wymaga interwencji technicznej w miejscu zatrudnienia
C. Nagłe zdarzenie związane z pracą, powodujące uraz lub śmierć
D. Każdy incydent wynikający z działania osób trzecich
Wypadek przy pracy to nagłe zdarzenie związane z wykonywaną pracą, które powoduje uraz lub śmierć pracownika. Wypadki te mogą być wynikiem zaniedbań, nieprzestrzegania zasad BHP lub nieodpowiedniego zabezpieczenia stanowiska pracy. Przykładami wypadków przy pracy są upadki z wysokości, porażenia prądem, oparzenia chemiczne lub uszkodzenia ciała przez maszyny. Pracodawca jest zobowiązany do zgłaszania każdego wypadku przy pracy, prowadzenia dochodzenia w celu ustalenia przyczyn i wdrażania działań zapobiegających powtórzeniu się podobnych sytuacji. Wypadki przy pracy są jedną z głównych przyczyn absencji oraz roszczeń pracowniczych, dlatego prewencja i edukacja w zakresie BHP są niezwykle istotne.